implement 'topification': adding an abstract 'Top'-class to a class diagram, and making all classes inherit from it
This commit is contained in:
parent
daa50d8c82
commit
ffc07fd83c
8 changed files with 86 additions and 0 deletions
5
transformation/topify/rules/r_create_inheritance_lhs.od
Normal file
5
transformation/topify/rules/r_create_inheritance_lhs.od
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
some_class:RAM_Class
|
||||||
|
|
||||||
|
top:RAM_Class {
|
||||||
|
condition = `get_name(this) == "Top"`;
|
||||||
|
}
|
||||||
7
transformation/topify/rules/r_create_inheritance_nac.od
Normal file
7
transformation/topify/rules/r_create_inheritance_nac.od
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# If our class already inherits from another class, then DON'T create an inheritance link
|
||||||
|
|
||||||
|
some_class:RAM_Class
|
||||||
|
|
||||||
|
any_other_class:RAM_Class
|
||||||
|
|
||||||
|
:RAM_Inheritance(some_class -> any_other_class)
|
||||||
9
transformation/topify/rules/r_create_inheritance_nac2.od
Normal file
9
transformation/topify/rules/r_create_inheritance_nac2.od
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Only create inheritance link once:
|
||||||
|
|
||||||
|
some_class:RAM_Class
|
||||||
|
|
||||||
|
top:RAM_Class {
|
||||||
|
condition = `get_name(this) == "Top"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
:RAM_Inheritance (some_class -> top)
|
||||||
9
transformation/topify/rules/r_create_inheritance_rhs.od
Normal file
9
transformation/topify/rules/r_create_inheritance_rhs.od
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
some_class:RAM_Class
|
||||||
|
|
||||||
|
top:RAM_Class {
|
||||||
|
condition = `get_name(this) == "Top"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create inheritance link
|
||||||
|
|
||||||
|
:RAM_Inheritance (some_class -> top)
|
||||||
1
transformation/topify/rules/r_create_top_lhs.od
Normal file
1
transformation/topify/rules/r_create_top_lhs.od
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
# empty
|
||||||
5
transformation/topify/rules/r_create_top_nac.od
Normal file
5
transformation/topify/rules/r_create_top_nac.od
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Top-class should not yet already exist:
|
||||||
|
|
||||||
|
top:RAM_Class {
|
||||||
|
condition = `get_name(this) == "Top"`;
|
||||||
|
}
|
||||||
8
transformation/topify/rules/r_create_top_rhs.od
Normal file
8
transformation/topify/rules/r_create_top_rhs.od
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# 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)
|
||||||
|
```;
|
||||||
|
}
|
||||||
42
transformation/topify/topify.py
Normal file
42
transformation/topify/topify.py
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
from uuid import UUID
|
||||||
|
from transformation.rule import RuleMatcherRewriter
|
||||||
|
from transformation.ramify import ramify
|
||||||
|
from util.loader import load_rules
|
||||||
|
|
||||||
|
import os
|
||||||
|
THIS_DIR = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
# Given a class diagram, extend it (in-place) with a "Top"-type, i.e., an (abstract) supertype of all types. The set of instances of the "Top" is always the set of all objects in the diagram.
|
||||||
|
def topify_cd(state, cd: UUID):
|
||||||
|
# meta-meta-model
|
||||||
|
scd_mmm = UUID(state.read_value(state.read_dict(state.read_root(), "SCD")))
|
||||||
|
|
||||||
|
scd_mmm_ramified = ramify(state, scd_mmm)
|
||||||
|
|
||||||
|
matcher_rewriter = RuleMatcherRewriter(state, scd_mmm, scd_mmm_ramified)
|
||||||
|
|
||||||
|
# topification is implemented via model transformation
|
||||||
|
rules = load_rules(state,
|
||||||
|
lambda rule_name, kind: f"{THIS_DIR}/rules/r_{rule_name}_{kind}.od",
|
||||||
|
scd_mmm_ramified, ["create_top", "create_inheritance"])
|
||||||
|
|
||||||
|
# 1. Execute rule 'create_top' once
|
||||||
|
rule = rules["create_top"]
|
||||||
|
match_set = list(matcher_rewriter.match_rule(cd, rule.lhs, rule.nacs, "create_top"))
|
||||||
|
if len(match_set) != 1:
|
||||||
|
raise Exception(f"Expected rule 'create_top' to match only once, instead got {len(match_set)} matches")
|
||||||
|
lhs_match = match_set[0]
|
||||||
|
cd, rhs_match = matcher_rewriter.exec_rule(cd, rule.lhs, rule.rhs, lhs_match, "create_top")
|
||||||
|
|
||||||
|
# 2. Execute rule 'create_inheritance' as many times as possible
|
||||||
|
rule = rules["create_inheritance"]
|
||||||
|
while True:
|
||||||
|
iterator = matcher_rewriter.match_rule(cd, rule.lhs, rule.nacs, "create_inheritance")
|
||||||
|
# find first match, and re-start matching
|
||||||
|
try:
|
||||||
|
lhs_match = iterator.__next__() # may throw StopIteration
|
||||||
|
cd, rhs_match = matcher_rewriter.exec_rule(cd, rule.lhs, rule.rhs, lhs_match, "create_inheritance")
|
||||||
|
except StopIteration:
|
||||||
|
break # no more matches
|
||||||
|
|
||||||
|
return cd
|
||||||
Loading…
Add table
Add a link
Reference in a new issue