|
@@ -8,94 +8,116 @@ class NodeAdd(object):
|
|
|
def __init__(self):
|
|
|
self._node_type = ""
|
|
|
|
|
|
- def execute(self, model, node_type, local, check_if_last=False):
|
|
|
+ def execute(self, model, node_type, local):
|
|
|
"""
|
|
|
- Add a new node with type node_type to model model.
|
|
|
+ Add a new node with type node_type to model.
|
|
|
If local is true, the node is only added to the model.
|
|
|
- If local is false, the node will be added to all models.
|
|
|
+ If local is false, the node will be added to all example models.
|
|
|
"""
|
|
|
self._node_type = node_type
|
|
|
if local:
|
|
|
mv.transformation_execute_MANUAL("graph_ops/add_node", {"gm":model}, {"gm":model},
|
|
|
callback=self._callback)
|
|
|
- # Local add can make a type mandatory and therefore break conformance
|
|
|
- if check_if_last:
|
|
|
- if commons.is_type_mandatory(node_type):
|
|
|
- print("Type {} became mandatory, adding it to instance models ...".format(node_type))
|
|
|
- # local add made type mandatory, so need to add to instance models (if not exists already)
|
|
|
- for im in commons.all_instance_models():
|
|
|
- if not commons.all_nodes_with_type(im, self._node_type):
|
|
|
- self.execute(im, node_type, local=True, check_if_last=False)
|
|
|
-
|
|
|
else:
|
|
|
- for m in commons.all_models():
|
|
|
+ for m in commons.all_example_models():
|
|
|
self.execute(m, node_type, local=True)
|
|
|
|
|
|
def _callback(self, model):
|
|
|
node_id = mv.instantiate(model, "gm/Node")
|
|
|
mv.attr_assign(model, node_id, "typeID", self._node_type)
|
|
|
|
|
|
+ def repair(self):
|
|
|
+ """
|
|
|
+ Check if the node add invalidated any instance models by making a type mandatory.
|
|
|
+ If yes, repair by adding a node of the same type to it.
|
|
|
+ """
|
|
|
+ if commons.is_type_mandatory(self._node_type):
|
|
|
+ for im in commons.all_instance_models():
|
|
|
+ if not commons.all_nodes_with_type(im, self._node_type):
|
|
|
+ print("Adding mandatory type {} to model {}".format(self._node_type, im))
|
|
|
+ self.execute(im, self._node_type, local=True)
|
|
|
+
|
|
|
|
|
|
class NodeDelete(object):
|
|
|
def __init__(self):
|
|
|
self._node = ""
|
|
|
self._node_type = ""
|
|
|
- self._was_last = False
|
|
|
+ self.was_last = False
|
|
|
|
|
|
- def execute(self, model, node, local, check_if_last=False):
|
|
|
+ def execute(self, model, node, local):
|
|
|
self._node = node
|
|
|
self._node_type = commons.get_node_type(model, node)
|
|
|
|
|
|
if local:
|
|
|
mv.transformation_execute_MANUAL("graph_ops/del_node", {"gm":model}, {"gm":model},
|
|
|
callback=self._callback)
|
|
|
- if check_if_last:
|
|
|
- # check if we just deleted the last instance of the node in all example models
|
|
|
- # if yes, delete it in instance models as well to preserve their validity
|
|
|
- remaining_instances = 0
|
|
|
- for m in commons.all_example_models():
|
|
|
- remaining_instances += len(commons.all_nodes_with_type(m, self._node_type))
|
|
|
- if remaining_instances == 0:
|
|
|
- # it was indeed the last one, delete from instance models
|
|
|
- self._was_last = True
|
|
|
- for m in commons.all_instance_models():
|
|
|
- nodes_to_delete = commons.all_nodes_with_type(m, self._node_type)
|
|
|
- for node in nodes_to_delete:
|
|
|
- self.execute(m, node, local=True)
|
|
|
else:
|
|
|
- for m in commons.all_models():
|
|
|
+ for m in commons.all_example_models():
|
|
|
nodes_to_delete = commons.all_nodes_with_type(m, self._node_type)
|
|
|
for node in nodes_to_delete:
|
|
|
self.execute(m, node, local=True)
|
|
|
|
|
|
- def was_last(self):
|
|
|
- return self._was_last
|
|
|
-
|
|
|
def _callback(self, model):
|
|
|
mv.delete_element(model, "gm/"+self._node)
|
|
|
|
|
|
+ def repair(self):
|
|
|
+ """
|
|
|
+ Check if this operation invalidated any instance model by leaving a node untyped.
|
|
|
+ If yes, delete untyped node as well.
|
|
|
+ """
|
|
|
+ remaining_instances = 0
|
|
|
+ for exm in commons.all_example_models():
|
|
|
+ remaining_instances += len(commons.all_nodes_with_type(exm, self._node_type))
|
|
|
+ if remaining_instances == 0:
|
|
|
+ self.was_last = True
|
|
|
+ print("Type {} became unavailable, deleting from all instance models ...".format(self._node_type))
|
|
|
+ for im in commons.all_instance_models():
|
|
|
+ nodes_to_delete = commons.all_nodes_with_type(im, self._node_type)
|
|
|
+ for node in nodes_to_delete:
|
|
|
+ self.execute(im, node, local=True)
|
|
|
+
|
|
|
|
|
|
class NodeRetype(object):
|
|
|
def __init__(self):
|
|
|
self._node = ""
|
|
|
+ self._old_type = ""
|
|
|
self._new_type = ""
|
|
|
+ self._scope = ""
|
|
|
|
|
|
def execute(self, model, node, new_type, local):
|
|
|
"""
|
|
|
Retype the node in model to new_type.
|
|
|
- If local is true, the change only affects the single node.
|
|
|
- If local is false, the change affects all nodes in all models.
|
|
|
+ If local is true, new_type must already exist and the change only affects the given node.
|
|
|
+ If local is false, all nodes in all example models are renamed to a new type (which must not exist yet).
|
|
|
"""
|
|
|
self._node = node
|
|
|
self._new_type = new_type
|
|
|
+ self._old_type = commons.get_node_type(model, node)
|
|
|
+ if local:
|
|
|
+ self._scope = "Local"
|
|
|
+ else:
|
|
|
+ self._scope = "Global"
|
|
|
+
|
|
|
if local:
|
|
|
mv.transformation_execute_MANUAL("graph_ops/retype_node", {"gm":model}, {"gm":model},
|
|
|
callback=self._callback)
|
|
|
else:
|
|
|
- node_type = commons.get_node_type(model, node)
|
|
|
- for m in commons.all_models():
|
|
|
- for node in commons.all_nodes_with_type(m, node_type):
|
|
|
- self.execute(m, node, new_type, local=True)
|
|
|
+ for exm in commons.all_example_models():
|
|
|
+ for node in commons.all_nodes_with_type(exm, self._old_type):
|
|
|
+ print("NodeRetype: retyping {} in {}".format(node, exm))
|
|
|
+ self.execute(exm, node, new_type, local=True)
|
|
|
|
|
|
def _callback(self, model):
|
|
|
mv.attr_assign(model, "gm/"+self._node, "typeID", self._new_type)
|
|
|
+
|
|
|
+ def repair(self):
|
|
|
+ """
|
|
|
+ Check if this operation invalidated any instance models.
|
|
|
+ Depends on the scope: if local, need to retype all instance model nodes with the old type as well
|
|
|
+ """
|
|
|
+ if self._scope == "Global":
|
|
|
+ for im in commons.all_instance_models():
|
|
|
+ for node in commons.all_nodes_with_type(im, self._old_type):
|
|
|
+ self.execute(im, node, self._new_type, local=True)
|
|
|
+ else:
|
|
|
+ pass # TODO implement
|