Browse Source

Fixed read_defined_attrs to include superclasses

Yentl Van Tendeloo 3 years ago
parent
commit
67dd1036d9

+ 3 - 6
bootstrap/mini_modify.alc

@@ -219,10 +219,6 @@ String function cmd_attr_optional(write : Boolean, model : Element, element_name
 				if (set_in(dict_keys(attrs), attr_name)):
 					String attr_edge
 					attr_edge = reverseKeyLookup(model["model"], dict_read_edge(model["model"][element_name], attr_name))
-					if (optional):
-						log("Setting to optional")
-					else:
-						log("Setting to mandatory")
 					model_undefine_attribute(model, element_name, attr_name)
 					model_define_attribute_ID(model, element_name, attr_name, optional, attrs[attr_name], attr_edge)
 					return "Success"!
@@ -243,7 +239,6 @@ String function cmd_undefine_attribute(write : Boolean, model : Element, element
 			if (set_in(dict_keys(attrs), attr_name)):
 				if (set_in(dict_keys(attrs), attr_name)):
 					model_undefine_attribute(model, element_name, attr_name)
-					log("REMOVE OK")
 					return "Success"!
 				else:
 					return "Attribute not defined: " + attr_name!
@@ -376,14 +371,16 @@ String function cmd_read_defined_attrs(model : Element, element_name : String):
 	Element attr_list
 	Element attr_keys
 	String attr_key
+	Element optionality
 
 	result = "Success: "
 	if (dict_in(model["model"], element_name)):
 		attr_list = getInstantiatableAttributes(model, element_name, "AttributeLink")
+		optionality = getAttributeOptionality(model, element_name, "AttributeLink")
 		attr_keys = dict_keys(attr_list)
 		while (0 < set_len(attr_keys)):
 			attr_key = set_pop(attr_keys)
-			if (value_eq(read_attribute(model, reverseKeyLookup(model["model"], dict_read_edge(model["model"][element_name], attr_key)), "optional"), True)):
+			if (optionality[attr_key]):
 				result = string_join(result, attr_key) + " ?: " + cast_string(attr_list[attr_key]) + "\n"
 			else:
 				result = string_join(result, attr_key) + " : " + cast_string(attr_list[attr_key]) + "\n"

+ 32 - 5
bootstrap/object_operations.alc

@@ -164,18 +164,45 @@ Element function getAttributes(model : Element, element : String):
 
 	return result!
 
+Element function getAttributeOptionality(model : Element, element : String, type : String):
+	Element all_links
+	Element result
+	String link
+	Element types
+
+	result = dict_create()
+	types = get_superclasses(model, element)
+
+	while (set_len(types) > 0):
+		element = set_pop(types)
+
+		all_links = allOutgoingAssociationInstances(model, element, type)
+		while (set_len(all_links) > 0):
+			link = set_pop(all_links)
+			if (value_eq(read_attribute(model, link, "optional"), True)):
+				dict_add(result, read_attribute(model, link, "name"), True)
+			else:
+				dict_add(result, read_attribute(model, link, "name"), False)
+
+	return result!
+
 Element function getInstantiatableAttributes(model : Element, element : String, type : String):
 	Element all_links
 	Element result
 	String link
+	Element types
 
 	result = dict_create()
+	types = get_superclasses(model, element)
+
+	while (set_len(types) > 0):
+		element = set_pop(types)
 
-	all_links = allOutgoingAssociationInstances(model, element, type)
-	while (set_len(all_links) > 0):
-		link = set_pop(all_links)
-		// WARNING: do not change this to dict_add_fast, as this crashes random code...
-		dict_add(result, read_attribute(model, link, "name"), readAssociationDestination(model, link))
+		all_links = allOutgoingAssociationInstances(model, element, type)
+		while (set_len(all_links) > 0):
+			link = set_pop(all_links)
+			// WARNING: do not change this to dict_add_fast, as this crashes random code...
+			dict_add(result, read_attribute(model, link, "name"), readAssociationDestination(model, link))
 
 	return result!
 

+ 1 - 0
interface/HUTN/includes/object_operations.alh

@@ -6,6 +6,7 @@ Element function allIncomingAssociationInstances(model: Element, target_name : S
 Element function getAttributeList(model: Element, element: String)
 Element function getAttributes(model: Element, element: String)
 Element function getInstantiatableAttributes(model: Element, element: String, type: String)
+Element function getAttributeOptionality(model: Element, element: String, type: String)
 String function print_dict(dict : Element)
 String function readAssociationSource(model : Element, name : String)
 String function readAssociationDestination(model : Element, name : String)

+ 60 - 0
unit/test_all.py

@@ -1952,6 +1952,66 @@ class TestModelverse(unittest.TestCase):
         except WritePermissionDenied:
             assert element_list("users/user/test/a") == before
 
+    def test_op_read_defined_attrs(self):
+        model_add("users/user/test/a", "formalisms/SimpleClassDiagrams", """
+            SimpleAttribute String {}
+            SimpleAttribute Natural {}
+            Class A {
+                name = "ABC"
+                value : Natural
+                new_name ?: String
+                name : String
+            }
+            Association B (A, A) {
+                name = "DEF"
+                edge_value : Natural
+                name : String
+                other_value ?: String
+            }
+            Class C {}
+            Class D : A {
+                additional_attr : Natural
+            }
+            Association E : B (D, A) {
+                next_attr : String
+            }
+            """)
+
+        # Normal operation
+        assert read_defined_attrs("users/user/test/a", "A") == ({"value": "Natural", "name": "String"}, {"new_name": "String"})
+        assert read_defined_attrs("users/user/test/a", "B") == ({"edge_value": "Natural", "name": "String"}, {"other_value": "String"})
+        assert read_defined_attrs("users/user/test/a", "C") == ({}, {})
+
+        # Works with inheritance
+        assert read_defined_attrs("users/user/test/a", "D") == ({"value": "Natural", "name": "String", "additional_attr": "Natural"}, {"new_name": "String"})
+        assert read_defined_attrs("users/user/test/a", "E") == ({"edge_value": "Natural", "name": "String", "next_attr": "String"}, {"other_value": "String"})
+
+        # Non-existing model
+        try:
+            read_defined_attrs("users/afa", "A")
+            self.fail()
+        except UnknownModel:
+            pass
+
+        # Non-existing element
+        before = element_list("users/user/test/a")
+        try:
+            read_defined_attrs("users/user/test/a", "AA")
+            self.fail()
+        except UnknownElement:
+            assert element_list("users/user/test/a") == before
+
+        # No read permissions
+        before = element_list("users/user/test/a")
+        try:
+            read_defined_attrs("administration/core", "formalisms")
+            self.fail()
+        except ReadPermissionDenied:
+            assert element_list("users/user/test/a") == before
+
+        # No write permissions, but can still query
+        assert read_defined_attrs("formalisms/SimpleClassDiagrams", "Association") == ({"name": "String"}, {"abstract": "Boolean", "constraint": "ActionCode", "lower_cardinality": "Natural", "upper_cardinality": "Natural", "source_lower_cardinality": "Natural", "source_upper_cardinality": "Natural", "target_lower_cardinality": "Natural", "target_upper_cardinality": "Natural"})
+
     """
     def test_op_model_render(self):
     def test_op_transformation_between(self):