MVS adapter: When flattening ModelRefs, prefix the names of all elements in ref'ed models

This commit is contained in:
Joeri Exelmans 2024-09-10 13:41:21 +02:00
parent ae5eaedb4b
commit 99bcf9a542
2 changed files with 12 additions and 21 deletions

View file

@ -70,9 +70,9 @@ class MVSEdge(NamedNode):
# dirty way of detecting whether a node is a ModelRef # dirty way of detecting whether a node is a ModelRef
UUID_REGEX = re.compile(r"[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]") UUID_REGEX = re.compile(r"[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z]-[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]")
# Converts an object/class diagram in MVS state to the pattern matcher graph type # Converts an object diagram in MVS state to the pattern matcher graph type
# ModelRefs are flattened # ModelRefs are flattened
def model_to_graph(state: State, model: UUID, metamodel: UUID): def model_to_graph(state: State, model: UUID, metamodel: UUID, prefix=""):
with Timer("model_to_graph"): with Timer("model_to_graph"):
od = OD(model, metamodel, state) od = OD(model, metamodel, state)
scd = SCD(model, state) scd = SCD(model, state)
@ -106,13 +106,12 @@ def model_to_graph(state: State, model: UUID, metamodel: UUID):
if isinstance(value, str): if isinstance(value, str):
if UUID_REGEX.match(value) != None: if UUID_REGEX.match(value) != None:
# side-effect # side-effect
modelrefs[el] = UUID(value) modelrefs[el] = (UUID(value),name)
return MVSNode(IS_MODELREF, el, name) return MVSNode(IS_MODELREF, el, name)
return MVSNode(value, el, name) return MVSNode(value, el, name)
# MVS-Nodes become vertices # MVS-Nodes become vertices
uuid_to_vtx = { node: to_vtx(node, key) for key in bottom.read_keys(model) for node in bottom.read_outgoing_elements(model, key) } uuid_to_vtx = { node: to_vtx(node, prefix+key) for key in bottom.read_keys(model) for node in bottom.read_outgoing_elements(model, key) }
uuid_to_vtx = { key: val for key,val in uuid_to_vtx.items() if val != None }
graph.vtxs = [ vtx for vtx in uuid_to_vtx.values() ] graph.vtxs = [ vtx for vtx in uuid_to_vtx.values() ]
# For every MSV-Edge, two edges are created (for src and tgt) # For every MSV-Edge, two edges are created (for src and tgt)
@ -131,13 +130,13 @@ def model_to_graph(state: State, model: UUID, metamodel: UUID):
label="tgt")) label="tgt"))
for node, ref in modelrefs.items(): for node, (ref, name) in modelrefs.items():
# Get MM of ref'ed model # Get MM of ref'ed model
type_node, = bottom.read_outgoing_elements(node, "Morphism") type_node, = bottom.read_outgoing_elements(node, "Morphism")
print("modelref type node:", type_node) print("modelref type node:", type_node)
# Recursively convert ref'ed model to graph # Recursively convert ref'ed model to graph
ref_model = model_to_graph(state, ref, type_node) ref_model = model_to_graph(state, ref, type_node, prefix=name+'/')
# Flatten and create link to ref'ed model # Flatten and create link to ref'ed model
graph.vtxs += ref_model.vtxs graph.vtxs += ref_model.vtxs
@ -214,7 +213,9 @@ class RAMCompare:
return False return False
def has_subtype(self, g_vtx_type, h_vtx_type): def match_types(self, g_vtx_type, h_vtx_type):
# types only match with their supertypes
# we assume that 'RAMifies'-traceability links have been created between guest and host types
g_vtx_original_types = self.bottom.read_outgoing_elements(g_vtx_type, "RAMifies") g_vtx_original_types = self.bottom.read_outgoing_elements(g_vtx_type, "RAMifies")
for typ in g_vtx_original_types: for typ in g_vtx_original_types:
# print(g_vtx, "is ramified") # print(g_vtx, "is ramified")
@ -233,8 +234,9 @@ class RAMCompare:
# First check if the types match (if we have type-information) # First check if the types match (if we have type-information)
if hasattr(g_vtx, 'typ'): if hasattr(g_vtx, 'typ'):
if not hasattr(h_vtx, 'typ'): if not hasattr(h_vtx, 'typ'):
# if guest has a type, host must have a type
return False return False
return self.has_subtype(g_vtx.typ, h_vtx.typ) return self.match_types(g_vtx.typ, h_vtx.typ)
# Then, match by value # Then, match by value
@ -254,17 +256,6 @@ class RAMCompare:
if h_vtx.value == IS_MODELREF: if h_vtx.value == IS_MODELREF:
return False return False
# # types only match with their supertypes
# # we assume that 'RAMifies'-traceability links have been created between guest and host types
# # we need these links, because the guest types are different types (RAMified)
# if isinstance(g_vtx.value, IS_TYPE):
# if not isinstance(h_vtx.value, IS_TYPE):
# return False
# return self.has_subtype(g_vtx.value.type, h_vtx.value.type)
# if isinstance(h_vtx.value, IS_TYPE):
# return False
# print(g_vtx.value, h_vtx.value) # print(g_vtx.value, h_vtx.value)
def get_slot(h_vtx, slot_name: str): def get_slot(h_vtx, slot_name: str):
slot_node = self.host_od.get_slot(h_vtx.node_id, slot_name) slot_node = self.host_od.get_slot(h_vtx.node_id, slot_name)

View file

@ -12,7 +12,7 @@ class Integer:
def create(self, value: int): def create(self, value: int):
# delete existing integer, if there is one # delete existing integer, if there is one
if "string" in self.bottom.read_keys(self.model): if "integer" in self.bottom.read_keys(self.model):
instance, = self.bottom.read_outgoing_elements(self.model, "integer") instance, = self.bottom.read_outgoing_elements(self.model, "integer")
self.bottom.delete_element(instance) self.bottom.delete_element(instance)
_instance = self.bottom.create_node(value) _instance = self.bottom.create_node(value)