import sys sys.path.append("../wrappers") from wrappers import modelverse as mv import commons class AttributeAdd(object): def __init__(self): self._key = "" self._value = "" self._node_id = "" self._node_type = "" def execute(self, model, node_id, key, value, local, check_if_last=False): """ Add a new attribute (key, value) to node with node_id in model. """ self._key = key self._value = value self._node_id = node_id if not self._node_type: self._node_type = commons.get_node_type(model, node_id) if local: mv.transformation_execute_MANUAL("graph_ops/add_attribute", {"gm":model}, {"gm":model}, callback=self._callback) if check_if_last: if commons.is_attribute_mandatory(self._node_type, key): print("Attribute {} for type {} became mandatory, adding it to instance models ...".format(key, self._node_type)) for im in commons.all_instance_models(): nodes = commons.all_nodes_with_type(im, self._node_type) for nid in nodes: self.execute(im, nid, key, value, local=True, check_if_last=False) else: for m in commons.all_models(): nodes = commons.all_nodes_with_type(m, self._node_type) for nid in nodes: self.execute(m, nid, key, value, local=True, check_if_last=False) def _callback(self, model): attr_id = mv.instantiate(model, "gm/Attribute") mv.attr_assign(model, attr_id, "key", self._key) mv.attr_assign(model, attr_id, "value", self._value) mv.instantiate(model, "gm/NodeAttribute", ("gm/"+self._node_id, attr_id)) class AttributeDelete(object): def __init__(self): self._key = "" self._node_id = "" self._node_type = "" def execute(self, model, node_id, key, local, check_if_last=False): """ Deletes an attribute identified by its key from node_id in model. """ self._key = key self._node_id = node_id if not self._node_type: self._node_type = commons.get_node_type(model, node_id) if local: mv.transformation_execute_MANUAL("graph_ops/del_attribute", {"gm":model}, {"gm":model}, callback=self._callback) if check_if_last: # a local attribute delete can break the conformance for instance models if the attribute was the last in # all example models -> check and correct this if necessary for exm in commons.all_example_models(): all_attrs = commons.get_all_attributes_of_type(exm, self._node_type) for attr in all_attrs: if attr.key == key: # wasn't the last, we're done here return # it was the last -> delete this attribute in all instance models to maintain conformance print("Attribute {} was the last, deleting it from all instance models to maintain conformance ...".format(key)) for im in commons.all_instance_models(): nodes = commons.get_nodes_with_attribute(im, key, self._node_type) for node in nodes: self.execute(im, node, key, local=True, check_if_last=False) else: # delete all attributes with key in all example models for m in commons.all_models(): nodes = commons.all_nodes_with_type(m, self._node_type) for nid in nodes: self.execute(m, nid, key, local=True) def _callback(self, model): outgoings = mv.read_outgoing(model, "gm/"+self._node_id, "gm/NodeAttribute") for edge in outgoings: attr = mv.read_association_destination(model, edge)[0] attr_key = mv.read_attrs(model, attr)["key"] if attr_key == self._key: mv.delete_element(model, attr) break class AttributeChange(object): """ Remark: This is currently not needed since the UI does not have the functionality to update an attribute key in-place. Instead, an attribute must be deleted and added with the new key to effectively change the key. Therefore, this is only here for the sake of completeness. """ def __init__(self): self._node_id = "" self._old_key = "" self._new_key = "" self._node_type = "" def execute(self, model, node_id, old_key, new_key, local): """ Update the attribute key old_key of node_id in model to new_key. """ self._node_id = node_id self._old_key = old_key self._new_key = new_key if not self._node_type: self._node_type = commons.get_node_type(model, node_id) if local: mv.transformation_execute_MANUAL("graph_ops/change_attribute", {"gm":model}, {"gm":model}, callback=self._callback) else: for m in commons.all_models(): nodes = commons.all_nodes_with_type(m, self._node_type) for nid in nodes: self.execute(m, nid, old_key, new_key, local=True) def _callback(self, model): outgoings = mv.read_outgoing(model, "gm/"+self._node_id, "gm/NodeAttribute") for link in outgoings: attr = mv.read_association_destination(model, link)[0] attr_key = mv.read_attrs(model, attr)["key"] if attr_key == self._old_key: mv.attr_assign(model, attr, "key", self._new_key) break