RAMification adds 'name' attribute, giving control over the names of created objects

This commit is contained in:
Joeri Exelmans 2024-12-03 20:28:16 +01:00
parent 7c01b126c2
commit da4f1718ce
8 changed files with 64 additions and 32 deletions

View file

@ -273,11 +273,15 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
if pattern_odapi.get_type_name(pattern_el) == "GlobalCondition":
return False
# Super-cheap and unreliable way of filtering out the 'condition'-attribute, added to every class:
return not (pattern_el_name.endswith("condition")
return ((not pattern_el_name.endswith("condition")
# as an extra safety measure, if the user defined her own 'condition' attribute, RAMification turned this into 'RAM_condition', and we can detect this
# of course this breaks if the class name already ended with 'RAM', but let's hope that never happens
# also, we are assuming the default "RAM_" prefix is used, but the user can change this...
and not pattern_el_name.endswith("RAM_condition"))
or pattern_el_name.endswith("RAM_condition"))
and (
not pattern_el_name.endswith("name")
or pattern_el_name.endswith("RAM_name") # same thing here as with the condition, explained above.
))
g_names, guest = model_to_graph(state, pattern_m, pattern_mm,
_filter=is_matchable)

View file

@ -56,6 +56,9 @@ def ramify(state: State, model: UUID, prefix = "RAM_") -> UUID:
# In RHS, this is just a piece of action code
ramified_scd._create_attribute_link(prefix+class_name, actioncode_modelref, "condition", optional=True)
# Optional: specify name of object to create
ramified_scd._create_attribute_link(prefix+class_name, actioncode_modelref, "name", optional=True)
already_ramified.add(class_name)
glob_cond = ramified_scd.create_class("GlobalCondition", abstract=None)
@ -97,6 +100,9 @@ def ramify(state: State, model: UUID, prefix = "RAM_") -> UUID:
# Additional constraint that can be specified
ramified_scd._create_attribute_link(prefix+assoc_name, actioncode_modelref, "condition", optional=True)
# Optional: specify name of link to create
ramified_scd._create_attribute_link(prefix+assoc_name, actioncode_modelref, "name", optional=True)
already_ramified.add(assoc_name)
# Associations can also have attributes...

View file

@ -22,10 +22,12 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, lhs_match: dict,
bottom = Bottom(state)
# Need to come up with a new, unique name when creating new element in host-model:
def first_available_name(prefix: str):
def first_available_name(suggested_name: str):
if len(bottom.read_outgoing_elements(host_m, suggested_name)) == 0:
return suggested_name # already unique :)
i = 0
while True:
name = prefix + str(i)
name = suggested_name + str(i)
if len(bottom.read_outgoing_elements(host_m, name)) == 0:
return name # found unique name
i += 1
@ -56,7 +58,10 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, lhs_match: dict,
lhs_keys = lhs_match.keys()
rhs_keys = set(k for k in bottom.read_keys(rhs_m)
# extremely dirty - should think of a better way
if "GlobalCondition" not in k and not k.endswith("_condition") and not k.endswith(".condition"))
if "GlobalCondition" not in k and not k.endswith("_condition") and not k.endswith(".condition")
and (not k.endswith("_name") or k.endswith("RAM_name")) and (not k.endswith(".name")))
print('filtered out:', set(k for k in bottom.read_keys(rhs_m) if k.endswith(".name") or k.endswith("_name")))
common = lhs_keys & rhs_keys
to_delete = lhs_keys - common
@ -75,6 +80,16 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, lhs_match: dict,
for rhs_name in remaining_to_create:
# Determine the type of the thing to create
rhs_obj = rhs_odapi.get(rhs_name)
# what to name our new object?
try:
name_expr = rhs_odapi.get_slot_value(rhs_obj, "name")
except:
name_expr = f'"{rhs_name}"' # <- if the 'name' slot doesnt exist, use the pattern element name
suggested_name = exec_then_eval(name_expr,
_globals={
**bind_api(host_odapi),
'matched': matched_callback,
})
rhs_type = rhs_odapi.get_type(rhs_obj)
host_type = ramify.get_original_type(bottom, rhs_type)
# for debugging:
@ -100,13 +115,13 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, lhs_match: dict,
try:
if od.is_typed_by(bottom, rhs_type, class_type):
obj_name = first_available_name(rhs_name)
obj_name = first_available_name(suggested_name)
host_od._create_object(obj_name, host_type)
host_odapi._ODAPI__recompute_mappings()
rhs_match[rhs_name] = obj_name
elif od.is_typed_by(bottom, rhs_type, assoc_type):
_, _, host_src, host_tgt = get_src_tgt()
link_name = first_available_name(rhs_name)
link_name = first_available_name(suggested_name)
host_od._create_link(link_name, host_type, host_src, host_tgt)
host_odapi._ODAPI__recompute_mappings()
rhs_match[rhs_name] = link_name

View file

@ -1,11 +1,9 @@
# We create the 'Top'-class with a GlobalCondition, because that's the only way we can control the name of the object to be created.
:GlobalCondition {
condition = ```
top = create_object("Top", "Class")
set_slot_value(top, "abstract", True)
lnk = create_link("generic_link", "Association", top, top)
# lnk also inherits top:
create_link(None, "Inheritance", lnk, top)
```;
}
Top:RAM_Class {
RAM_abstract = `True`;
}
generic_link:RAM_Association (Top -> Top)
:RAM_Inheritance (generic_link -> Top)