Browse Source

Handle 'condition' object-attribute in RHS as well

Joeri Exelmans 9 months ago
parent
commit
e3d4889f91
2 changed files with 24 additions and 8 deletions
  1. 3 4
      transformation/ramify.py
  2. 21 4
      transformation/rewriter.py

+ 3 - 4
transformation/ramify.py

@@ -43,9 +43,6 @@ def ramify(state: State, model: UUID, prefix = "RAM_") -> UUID:
         # We don't add a 'label' attribute (as described in literature on RAMification)
         # Instead, the names of the objects (which only exist in the scope of the object diagram 'model', and are not visible to the matcher) are used as labels
 
-        # Optional constraint on the object
-        # ramified_scd._create_attribute_link(prefix+class_name, string_modelref, "constraint", optional=True)
-
         for (attr_name, attr_edge) in od.get_attributes(bottom, class_node):
             # print('  creating attribute', attr_name, "with type String")
             # Every attribute becomes 'string' type
@@ -54,7 +51,9 @@ def ramify(state: State, model: UUID, prefix = "RAM_") -> UUID:
             # create traceability link
             bottom.create_edge(ramified_attr_link, attr_edge, RAMIFIES_LABEL)
 
-        # Additional constraint that can be specified
+        # Additional condition that can be specified
+        # In LHS, this will be a boolean expression (pre-condition)
+        # In RHS, this is just a piece of action code
         ramified_scd._create_attribute_link(prefix+class_name, actioncode_modelref, "condition", optional=True)
 
         already_ramified.add(class_name)

+ 21 - 4
transformation/rewriter.py

@@ -19,8 +19,8 @@ def preprocess_rule(state, lhs: UUID, rhs: UUID, name_mapping):
 
     to_delete = { name for name in bottom.read_keys(lhs) if name not in bottom.read_keys(rhs) and name in name_mapping }
     to_create = { name for name in bottom.read_keys(rhs) if name not in bottom.read_keys(lhs)
-        # extremely dirty:
-        and "GlobalCondition" not in name }
+        # extremely dirty - should think of a better way
+        and "GlobalCondition" not in name and not name.endswith("_condition") and not name.endswith(".condition") }
     common = { name for name in bottom.read_keys(lhs) if name in bottom.read_keys(rhs) and name in name_mapping }
 
     return to_delete, to_create, common
@@ -66,8 +66,8 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, lhs_name_mapping:
 
     to_delete, to_create, common = preprocess_rule(state, lhs_m, rhs_m, lhs_name_mapping)
 
-    print("to_delete:", to_delete)
-    print("to_create:", to_create)
+    # print("to_delete:", to_delete)
+    # print("to_create:", to_create)
 
     # to be grown
     rhs_name_mapping = { name : lhs_name_mapping[name] for name in common }
@@ -205,6 +205,23 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, lhs_name_mapping:
             # print(msg)
             raise Exception(msg)
 
+    # Finally, we iterate over the (now complete) mapping RHS -> Host, to execute all the user-specified conditions
+    for rhs_name, host_name in rhs_name_mapping.items():
+        host_obj = host_odapi.get(host_name)
+        rhs_obj = rhs_odapi.get(rhs_name)
+        rhs_type = rhs_odapi.get_type(rhs_obj)
+        rhs_type_of_type = rhs_mm_odapi.get_type(rhs_type)
+        rhs_type_of_type_name = rhs_mm_odapi.get_name(rhs_type_of_type)
+        if rhs_mm_odapi.cdapi.is_subtype(super_type_name="Class", sub_type_name=rhs_type_of_type_name):
+            # rhs_obj is an object or link (because association is subtype of class)
+            python_code = rhs_odapi.get_slot_value_default(rhs_obj, "condition", default="")
+            simply_exec(python_code,
+                _globals={
+                    **bind_api(host_odapi),
+                    'matched': matched_callback,
+                },
+                _locals={'this': host_obj})
+
     # Execute global conditions
     for cond_name, cond in rhs_odapi.get_all_instances("GlobalCondition"):
         python_code = rhs_odapi.get_slot_value(cond, "condition")