commons.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import re
  2. from wrappers import modelverse as mv
  3. class Attribute(object):
  4. """
  5. Helper class for attribute representation as key value pair
  6. """
  7. def __init__(self, key, val):
  8. self.key = key
  9. self.val = val
  10. def __eq__(self, other):
  11. if other.key == self.key and other.val == self.val:
  12. return True
  13. return False
  14. def __repr__(self):
  15. return "{}={}".format(self.key, self.val)
  16. def all_models():
  17. """ Returns a list of paths of all example- and instance models """
  18. return all_instance_models() + all_example_models()
  19. def all_instance_models():
  20. """ Returns a list of paths of all instance models """
  21. try:
  22. instance_models = mv.model_list("models/instance")
  23. except mv.UnknownLocation:
  24. # no instance models
  25. return []
  26. instance_models_full = ["models/instance/"+m for m in instance_models]
  27. return instance_models_full
  28. def all_example_models():
  29. """ Returns a list of paths of all example models """
  30. try:
  31. example_models = mv.model_list("models/example")
  32. except mv.UnknownLocation:
  33. # no example models
  34. return []
  35. example_models_full = ["models/example/"+exm for exm in example_models]
  36. return example_models_full
  37. def all_consyn_models():
  38. """ Returns a list of paths of all concrete syntax models """
  39. try:
  40. consyn_models = mv.model_list("models/consyn")
  41. except mv.UnknownLocation:
  42. return []
  43. consyn_models_full = ["models/consyn/"+csm for csm in consyn_models]
  44. return consyn_models_full
  45. def all_nodes_with_type(model, typ):
  46. """ Returns a list of nodes in model model with type typ """
  47. all_nodes = mv.all_instances(model, "Node")
  48. ret = [node for node in all_nodes if mv.read_attrs(model, node)["typeID"] == typ]
  49. return ret
  50. def get_node_type(model, node_id):
  51. """ Returns the type attribute of node in model as string"""
  52. return mv.read_attrs(model, node_id)["typeID"]
  53. def get_available_types():
  54. """ Returns a list of all types of nodes in all example models """
  55. types = []
  56. for m in all_example_models():
  57. nodes = mv.all_instances(m, "Node")
  58. for node in nodes:
  59. typ = get_node_type(m, node)
  60. types.append(typ)
  61. return list(set(types))
  62. def count_occurences(node_type, model):
  63. """ Returns the number of occurences of a node with type node_type in a model """
  64. ctr = 0
  65. all_nodes = mv.all_instances(model, "Node")
  66. for node in all_nodes:
  67. typ = get_node_type(model, node)
  68. if typ == node_type:
  69. ctr += 1
  70. return ctr
  71. def is_type_mandatory(node_type):
  72. """
  73. True if node_type is a mandatory type (i.e. it occurs at least once in every example model),
  74. False otherwise.
  75. """
  76. for exm in all_example_models():
  77. nodes_with_type = all_nodes_with_type(exm, node_type)
  78. if not nodes_with_type:
  79. return False
  80. return True
  81. def get_associations_between(model, node1, node2):
  82. """ Returns a list of association IDs between the nodes node1 and node2 """
  83. edges_n1 = mv.read_outgoing(model, node1, "Edge")
  84. edges_n1.update(mv.read_incoming(model, node1, "Edge"))
  85. edges_n2 = mv.read_outgoing(model, node2, "Edge")
  86. edges_n2.update(mv.read_incoming(model, node2, "Edge"))
  87. return list(edges_n1.intersection(edges_n2))
  88. def get_all_attributes_of_type(model, node_type):
  89. # type: (str, str) -> list(Attribute)
  90. """ Returns a list of attributes of a node with type node_type in a model """
  91. ret = []
  92. node_attribute_links = mv.all_instances(model, "NodeAttribute")
  93. for link in node_attribute_links:
  94. src_node = mv.read_association_source(model, link)[0]
  95. src_typ = mv.read_attrs(model, src_node)["typeID"]
  96. if src_typ != node_type:
  97. continue
  98. attr_node_name = mv.read_association_destination(model, link)[0]
  99. attr_dict = mv.read_attrs(model, attr_node_name)
  100. attr = Attribute(attr_dict["key"], attr_dict["value"])
  101. ret.append(attr)
  102. return ret
  103. def get_attributes_of_node(model, node_id):
  104. # type: (str, str) -> list(Attribute)
  105. """ Returns a list of attributes of a specific node with id node_id """
  106. ret = []
  107. outgoings = mv.read_outgoing(model, node_id, "NodeAttribute")
  108. if not outgoings:
  109. return []
  110. for link in outgoings:
  111. dest = mv.read_association_destination(model, link)[0]
  112. attr_dict = mv.read_attrs(model, dest)
  113. attr = Attribute(attr_dict["key"], attr_dict["value"])
  114. ret.append(attr)
  115. return ret
  116. def model_contains_type(model, node_type):
  117. """
  118. True if some node in model is typed by node_type, False otherwise.
  119. """
  120. all_types = all_nodes_with_type(model, node_type)
  121. if not all_types:
  122. return False
  123. return True
  124. def has_edge_to_type(model, node_id, node_type):
  125. """
  126. True if the node identified by node_id is connected to a node of type type_id, False otherwise.
  127. """
  128. outgoings = mv.read_outgoing(model, node_id, "Edge")
  129. dest_ids = [mv.read_association_destination(model, edge)[0] for edge in outgoings]
  130. dest_types = [get_node_type(model, _node_id) for _node_id in dest_ids]
  131. # also need to check incomings of node_id
  132. incomings = mv.read_incoming(model, node_id, "Edge")
  133. src_ids = [mv.read_association_source(model, edge)[0] for edge in incomings]
  134. src_types = [get_node_type(model, _node_id) for _node_id in src_ids]
  135. return node_type in dest_types + src_types
  136. def is_edge_supported(from_type, to_type):
  137. """
  138. True if an association between from_type and to_type exists in any example model
  139. False otherwise
  140. """
  141. for m in all_example_models():
  142. nodes_from = all_nodes_with_type(m, from_type)
  143. nodes_to = all_nodes_with_type(m, to_type)
  144. for nf in nodes_from:
  145. for nt in nodes_to:
  146. assocs = get_associations_between(m, nf, nt)
  147. if assocs:
  148. # somewhere in an example model, there is such an association
  149. return True
  150. return False
  151. def new_instance_model():
  152. """
  153. Adds a new, empty instance model to the Modelverse.
  154. Returns the name of the new model
  155. """
  156. existing_models = all_instance_models()
  157. idx = 1
  158. nums = []
  159. for model in existing_models:
  160. m = model.split("/")[-1]
  161. try:
  162. idx = int(re.search(r'\d+', m).group())
  163. nums.append(idx)
  164. except AttributeError:
  165. pass
  166. if nums:
  167. idx = sorted(nums)[-1] + 1
  168. im = "models/instance/im{}".format(idx)
  169. print("Adding new instance model {}".format(im))
  170. mv.model_add(im, "formalisms/graphMM")
  171. mid = mv.instantiate(im, "Model")
  172. mv.attr_assign(im, mid, "is_example", False)
  173. mv.attr_assign(im, mid, "descr", "")
  174. return im
  175. def new_example_model():
  176. """
  177. Adds a new, empty example model to the Modelverse.
  178. Returns the name of the new model
  179. """
  180. existing_models = all_example_models()
  181. idx = 1
  182. nums = []
  183. for model in existing_models:
  184. m = model.split("/")[-1]
  185. try:
  186. idx = int(re.search(r'\d+', m).group())
  187. nums.append(idx)
  188. except AttributeError:
  189. pass
  190. if nums:
  191. idx = sorted(nums)[-1] + 1
  192. exm = "models/example/ex{}".format(idx)
  193. print("Adding new example model {}".format(exm))
  194. mv.model_add(exm, "formalisms/graphMM")
  195. mid = mv.instantiate(exm, "Model")
  196. mv.attr_assign(exm, mid, "is_example", True)
  197. mv.attr_assign(exm, mid, "descr", "")
  198. return exm
  199. def get_nodes_with_attribute(model, attr_key, node_type):
  200. """
  201. Returns all nodes which have an attribute identified by attr_key and are typed by node_type
  202. """
  203. ret = []
  204. typed_nodes = all_nodes_with_type(model, node_type)
  205. for node_id in typed_nodes:
  206. attrs = get_attributes_of_node(model, node_id)
  207. for attr in attrs:
  208. if attr.key == attr_key:
  209. ret.append(node_id)
  210. return ret