Make OD-API for consistent for constraints, LHS patterns, RHS actions.
This commit is contained in:
parent
1eb8a84553
commit
9c68b288c1
8 changed files with 108 additions and 79 deletions
|
|
@ -1,9 +1,11 @@
|
|||
from api.cd import CDAPI
|
||||
from api.od import ODAPI, bind_api_readonly
|
||||
from util.eval import exec_then_eval
|
||||
from state.base import State
|
||||
from uuid import UUID
|
||||
from services.bottom.V0 import Bottom
|
||||
from services.scd import SCD
|
||||
from services.od import OD
|
||||
from services import od as services_od
|
||||
from transformation.matcher.matcher import Graph, Edge, Vertex, MatcherVF2
|
||||
from transformation import ramify
|
||||
import itertools
|
||||
|
|
@ -76,7 +78,7 @@ 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-
|
|||
# ModelRefs are flattened
|
||||
def model_to_graph(state: State, model: UUID, metamodel: UUID, prefix=""):
|
||||
# with Timer("model_to_graph"):
|
||||
od = OD(model, metamodel, state)
|
||||
od = services_od.OD(model, metamodel, state)
|
||||
scd = SCD(model, state)
|
||||
scd_mm = SCD(metamodel, state)
|
||||
|
||||
|
|
@ -208,6 +210,7 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
|
|||
|
||||
# compute subtype relations and such:
|
||||
cdapi = CDAPI(state, host_mm)
|
||||
odapi = ODAPI(state, host_m, host_mm)
|
||||
|
||||
# Function object for pattern matching. Decides whether to match host and guest vertices, where guest is a RAMified instance (e.g., the attributes are all strings with Python expressions), and the host is an instance (=object diagram) of the original model (=class diagram)
|
||||
class RAMCompare:
|
||||
|
|
@ -251,16 +254,26 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
|
|||
if hasattr(g_vtx, 'modelref'):
|
||||
if not hasattr(h_vtx, 'modelref'):
|
||||
return False
|
||||
g_ref_m, g_ref_mm = g_vtx.modelref
|
||||
h_ref_m, h_ref_mm = h_vtx.modelref
|
||||
nested_matches = [m for m in match_od(state, h_ref_m, h_ref_mm, g_ref_m, g_ref_mm)]
|
||||
|
||||
python_code = services_od.read_primitive_value(self.bottom, g_vtx.node_id, pattern_mm)[0]
|
||||
return exec_then_eval(python_code,
|
||||
_globals=bind_api_readonly(odapi),
|
||||
_locals={'this': h_vtx.node_id})
|
||||
|
||||
# nested_matches = [m for m in match_od(state, h_ref_m, h_ref_mm, g_ref_m, g_ref_mm)]
|
||||
|
||||
|
||||
# print('begin recurse')
|
||||
# g_ref_m, g_ref_mm = g_vtx.modelref
|
||||
# h_ref_m, h_ref_mm = h_vtx.modelref
|
||||
# print('nested_matches:', nested_matches)
|
||||
if len(nested_matches) == 0:
|
||||
return False
|
||||
elif len(nested_matches) == 1:
|
||||
return True
|
||||
else:
|
||||
raise Exception("We have a problem: there is more than 1 match in the nested models.")
|
||||
# if len(nested_matches) == 0:
|
||||
# return False
|
||||
# elif len(nested_matches) == 1:
|
||||
# return True
|
||||
# else:
|
||||
# raise Exception("We have a problem: there is more than 1 match in the nested models.")
|
||||
# print('end recurse')
|
||||
|
||||
# Then, match by value
|
||||
|
||||
|
|
@ -280,23 +293,15 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
|
|||
if h_vtx.value == IS_MODELREF:
|
||||
return False
|
||||
|
||||
# # print(g_vtx.value, h_vtx.value)
|
||||
# def get_slot(h_vtx, slot_name: str):
|
||||
# slot_node = self.host_od.get_slot(h_vtx.node_id, slot_name)
|
||||
# return slot_node
|
||||
|
||||
# def read_int(slot: UUID):
|
||||
# i = Integer(slot, self.bottom.state)
|
||||
# return i.read()
|
||||
|
||||
try:
|
||||
return eval(g_vtx.value, {}, {
|
||||
'v': h_vtx.value,
|
||||
# 'get_slot': functools.partial(get_slot, h_vtx),
|
||||
# 'read_int': read_int,
|
||||
})
|
||||
except Exception as e:
|
||||
return False
|
||||
# python_code = g_vtx.value
|
||||
# try:
|
||||
# return exec_then_eval(python_code,
|
||||
# _globals=bind_api_readonly(odapi),
|
||||
# _locals={'this': h_vtx.node_id})
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
# return False
|
||||
return True
|
||||
|
||||
# Convert to format understood by matching algorithm
|
||||
h_names, host = model_to_graph(state, host_m, host_mm)
|
||||
|
|
@ -309,7 +314,7 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
|
|||
if guest_name in g_names
|
||||
}
|
||||
|
||||
matcher = MatcherVF2(host, guest, RAMCompare(Bottom(state), OD(host_mm, host_m, state)))
|
||||
matcher = MatcherVF2(host, guest, RAMCompare(Bottom(state), services_od.OD(host_mm, host_m, state)))
|
||||
for m in matcher.match(graph_pivot):
|
||||
# print("\nMATCH:\n", m)
|
||||
# Convert mapping
|
||||
|
|
|
|||
|
|
@ -4,12 +4,14 @@
|
|||
# - ? that's it?
|
||||
|
||||
from uuid import UUID
|
||||
from api.od import ODAPI, bind_api
|
||||
from services.bottom.V0 import Bottom
|
||||
from transformation import ramify
|
||||
from services import od
|
||||
from services.primitives.string_type import String
|
||||
from services.primitives.actioncode_type import ActionCode
|
||||
from services.primitives.integer_type import Integer
|
||||
from util.eval import exec_then_eval
|
||||
|
||||
def process_rule(state, lhs: UUID, rhs: UUID):
|
||||
bottom = Bottom(state)
|
||||
|
|
@ -41,6 +43,8 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, name_mapping: dic
|
|||
|
||||
to_delete, to_create, common = process_rule(state, lhs_m, rhs_m)
|
||||
|
||||
odapi = ODAPI(state, host_m, mm)
|
||||
|
||||
# Perform deletions
|
||||
for pattern_name_to_delete in to_delete:
|
||||
# For every name in `to_delete`, look up the name of the matched element in the host graph
|
||||
|
|
@ -95,7 +99,8 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, name_mapping: dic
|
|||
if type_name == "ActionCode":
|
||||
# Assume the string is a Python expression to evaluate
|
||||
python_expr = ActionCode(UUID(bottom.read_value(rhs_el_to_create)), bottom.state).read()
|
||||
result = eval(python_expr, {}, {})
|
||||
|
||||
result = exec_then_eval(python_expr, _globals=bind_api(odapi))
|
||||
# Write the result into the host model.
|
||||
# This will be the *value* of an attribute. The attribute-link (connecting an object to the attribute) will be created as an edge later.
|
||||
if isinstance(result, int):
|
||||
|
|
@ -152,8 +157,10 @@ def rewrite(state, lhs_m: UUID, rhs_m: UUID, pattern_mm: UUID, name_mapping: dic
|
|||
print(' -> is modelref')
|
||||
old_value, _ = od.read_primitive_value(bottom, host_el, mm)
|
||||
rhs_el, = bottom.read_outgoing_elements(rhs_m, pattern_el_name)
|
||||
expr, _ = od.read_primitive_value(bottom, rhs_el, pattern_mm)
|
||||
result = eval(expr, {}, {'v': old_value})
|
||||
python_expr, _ = od.read_primitive_value(bottom, rhs_el, pattern_mm)
|
||||
result = exec_then_eval(python_expr,
|
||||
_globals=bind_api(odapi),
|
||||
_locals={'this': host_el})
|
||||
# print('eval result=', result)
|
||||
if isinstance(result, int):
|
||||
# overwrite the old value, in-place
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue