import re from wrappers import modelverse as mv class Attribute(object): """ Helper class for attribute representation as key value pair """ def __init__(self, key, val): self.key = key self.val = val def __eq__(self, other): if other.key == self.key and other.val == self.val: return True return False def __repr__(self): return "{}={}".format(self.key, self.val) def all_models(): """ Returns a list of paths of all example- and instance models """ return all_instance_models() + all_example_models() def all_instance_models(): """ Returns a list of paths of all instance models """ try: instance_models = mv.model_list("models/instance") except mv.UnknownLocation: # no instance models return [] instance_models_full = ["models/instance/"+m for m in instance_models] return instance_models_full def all_example_models(): """ Returns a list of paths of all example models """ try: example_models = mv.model_list("models/example") except mv.UnknownLocation: # no example models return [] example_models_full = ["models/example/"+exm for exm in example_models] return example_models_full def all_consyn_models(): """ Returns a list of paths of all concrete syntax models """ try: consyn_models = mv.model_list("models/consyn") except mv.UnknownLocation: return [] consyn_models_full = ["models/consyn/"+csm for csm in consyn_models] return consyn_models_full def all_nodes_with_type(model, typ): """ Returns a list of nodes in model model with type typ """ all_nodes = mv.all_instances(model, "Node") ret = [node for node in all_nodes if mv.read_attrs(model, node)["typeID"] == typ] return ret def get_node_type(model, node_id): """ Returns the type attribute of node in model as string""" return mv.read_attrs(model, node_id)["typeID"] def get_available_types(): """ Returns a list of all types of nodes in all example models """ types = [] for m in all_example_models(): nodes = mv.all_instances(m, "Node") for node in nodes: typ = get_node_type(m, node) types.append(typ) return list(set(types)) def count_occurences(node_type, model): """ Returns the number of occurences of a node with type node_type in a model """ ctr = 0 all_nodes = mv.all_instances(model, "Node") for node in all_nodes: typ = get_node_type(model, node) if typ == node_type: ctr += 1 return ctr def get_associations_between(model, node1, node2): """ Returns a list of association IDs between the nodes node1 and node2 """ edges_n1 = mv.read_outgoing(model, node1, "Edge") edges_n1.update(mv.read_incoming(model, node1, "Edge")) edges_n2 = mv.read_outgoing(model, node2, "Edge") edges_n2.update(mv.read_incoming(model, node2, "Edge")) return list(edges_n1.intersection(edges_n2)) def get_all_attributes_of_type(model, node_type): # type: (str, str) -> list(Attribute) """ Returns a list of attributes of a node with type node_type in a model """ ret = [] node_attribute_links = mv.all_instances(model, "NodeAttribute") for link in node_attribute_links: src_node = mv.read_association_source(model, link)[0] src_typ = mv.read_attrs(model, src_node)["typeID"] if src_typ != node_type: continue attr_node_name = mv.read_association_destination(model, link)[0] attr_dict = mv.read_attrs(model, attr_node_name) attr = Attribute(attr_dict["key"], attr_dict["value"]) ret.append(attr) return ret def get_attributes_of_node(model, node_id): # type: (str, str) -> list(Attribute) """ Returns a list of attributes of a specific node with id node_id """ ret = [] outgoings = mv.read_outgoing(model, node_id, "NodeAttribute") if not outgoings: return [] for link in outgoings: dest = mv.read_association_destination(model, link)[0] attr_dict = mv.read_attrs(model, dest) attr = Attribute(attr_dict["key"], attr_dict["value"]) ret.append(attr) return ret def model_contains_type(model, node_type): """ True if some node in model is typed by node_type, False otherwise. """ all_types = all_nodes_with_type(model, node_type) if not all_types: return False return True def has_edge_to_type(model, node_id, node_type): """ True if the node identified by node_id is connected to a node of type type_id, False otherwise. """ outgoings = mv.read_outgoing(model, node_id, "Edge") dest_ids = [mv.read_association_destination(model, edge)[0] for edge in outgoings] dest_types = [get_node_type(model, _node_id) for _node_id in dest_ids] # also need to check incomings of node_id incomings = mv.read_incoming(model, node_id, "Edge") src_ids = [mv.read_association_source(model, edge)[0] for edge in incomings] src_types = [get_node_type(model, _node_id) for _node_id in src_ids] return node_type in dest_types + src_types def is_edge_supported(from_type, to_type): """ True if an association between from_type and to_type exists in any example model False otherwise """ for m in all_example_models(): nodes_from = all_nodes_with_type(m, from_type) nodes_to = all_nodes_with_type(m, to_type) for nf in nodes_from: for nt in nodes_to: assocs = get_associations_between(m, nf, nt) if assocs: # somewhere in an example model, there is such an association return True return False def new_instance_model(): """ Adds a new, empty instance model to the Modelverse. Returns the name of the new model """ existing_models = all_instance_models() idx = 1 nums = [] for model in existing_models: m = model.split("/")[-1] try: idx = int(re.search(r'\d+', m).group()) nums.append(idx) except AttributeError: pass if nums: idx = sorted(nums)[-1] + 1 im = "models/instance/im{}".format(idx) print("Adding new instance model {}".format(im)) mv.model_add(im, "formalisms/graphMM") mid = mv.instantiate(im, "Model") mv.attr_assign(im, mid, "is_example", False) mv.attr_assign(im, mid, "descr", "") return im def new_example_model(): """ Adds a new, empty example model to the Modelverse. Returns the name of the new model """ existing_models = all_example_models() idx = 1 nums = [] for model in existing_models: m = model.split("/")[-1] try: idx = int(re.search(r'\d+', m).group()) nums.append(idx) except AttributeError: pass if nums: idx = sorted(nums)[-1] + 1 exm = "models/example/ex{}".format(idx) print("Adding new example model {}".format(exm)) mv.model_add(exm, "formalisms/graphMM") mid = mv.instantiate(exm, "Model") mv.attr_assign(exm, mid, "is_example", True) mv.attr_assign(exm, mid, "descr", "") return exm