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): """ 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) 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) 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)) def repair(self): """ Check if this operation invalidated any instance models by making an attribute mandatory. If yes, every node with the same type must have this attribute, so add it if necessary. """ if commons.is_attribute_mandatory(self._node_type, self._key): print("Attribute {} for type {} became mandatory, adding it to instance models ...".format(self._key, self._node_type)) for im in commons.all_instance_models(): nodes = commons.all_nodes_with_type(im, self._node_type) for node_id in nodes: attrs = commons.get_attributes_of_node(im, node_id) if self._key not in [at.key for at in attrs]: self.execute(im, node_id, self._key, self._value, local=True) class AttributeDelete(object): def __init__(self): self._key = "" self._node_id = "" self._node_type = "" def execute(self, model, node_id, key, local): """ 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) else: for exm in commons.all_example_models(): nodes = commons.get_nodes_with_attribute(exm, self._key, self._node_type) for nid in nodes: self.execute(exm, nid, self._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 def repair(self): """ Check if this operation invalidated any instance models by making an instance model attribute invalid. If yes, delete this attribute from the instance model. """ 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 == self._key: # there still is an attribute with the key, so it is not invalid -> finished return print("Attribute {} was the last, deleting it from all instance models ...".format(self._key)) for im in commons.all_instance_models(): nodes = commons.get_nodes_with_attribute(im, self._key, self._node_type) for nid in nodes: self.execute(im, nid, self._key, local=True) 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