123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- 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 is_type_mandatory(node_type):
- """
- True if node_type is a mandatory type (i.e. it occurs at least once in every example model),
- False otherwise.
- """
- for exm in all_example_models():
- nodes_with_type = all_nodes_with_type(exm, node_type)
- if not nodes_with_type:
- return False
- return True
- 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
- def get_nodes_with_attribute(model, attr_key, node_type):
- """
- Returns all nodes which have an attribute identified by attr_key and are typed by node_type
- """
- ret = []
- typed_nodes = all_nodes_with_type(model, node_type)
- for node_id in typed_nodes:
- attrs = get_attributes_of_node(model, node_id)
- for attr in attrs:
- if attr.key == attr_key:
- ret.append(node_id)
- return ret
|