commons.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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 get_associations_between(model, node1, node2):
  72. """ Returns a list of association IDs between the nodes node1 and node2 """
  73. edges_n1 = mv.read_outgoing(model, node1, "Edge")
  74. edges_n1.update(mv.read_incoming(model, node1, "Edge"))
  75. edges_n2 = mv.read_outgoing(model, node2, "Edge")
  76. edges_n2.update(mv.read_incoming(model, node2, "Edge"))
  77. return list(edges_n1.intersection(edges_n2))
  78. def get_all_attributes_of_type(model, node_type):
  79. # type: (str, str) -> list(Attribute)
  80. """ Returns a list of attributes of a node with type node_type in a model """
  81. ret = []
  82. node_attribute_links = mv.all_instances(model, "NodeAttribute")
  83. for link in node_attribute_links:
  84. src_node = mv.read_association_source(model, link)[0]
  85. src_typ = mv.read_attrs(model, src_node)["typeID"]
  86. if src_typ != node_type:
  87. continue
  88. attr_node_name = mv.read_association_destination(model, link)[0]
  89. attr_dict = mv.read_attrs(model, attr_node_name)
  90. attr = Attribute(attr_dict["key"], attr_dict["value"])
  91. ret.append(attr)
  92. return ret
  93. def get_attributes_of_node(model, node_id):
  94. # type: (str, str) -> list(Attribute)
  95. """ Returns a list of attributes of a specific node with id node_id """
  96. ret = []
  97. outgoings = mv.read_outgoing(model, node_id, "NodeAttribute")
  98. if not outgoings:
  99. return []
  100. for link in outgoings:
  101. dest = mv.read_association_destination(model, link)[0]
  102. attr_dict = mv.read_attrs(model, dest)
  103. attr = Attribute(attr_dict["key"], attr_dict["value"])
  104. ret.append(attr)
  105. return ret
  106. def model_contains_type(model, node_type):
  107. """
  108. True if some node in model is typed by node_type, False otherwise.
  109. """
  110. all_types = all_nodes_with_type(model, node_type)
  111. if not all_types:
  112. return False
  113. return True
  114. def has_edge_to_type(model, node_id, type_id):
  115. """
  116. True if the node identified by node_id is connected to a node of type type_id, False otherwise.
  117. """
  118. outgoings = mv.read_outgoing(model, node_id, "Edge")
  119. dest_ids = []
  120. for edge in outgoings:
  121. dest_node = mv.read_association_destination(model, edge)[0]
  122. dest_ids.append(dest_node)
  123. dest_types = []
  124. for node_id in dest_ids:
  125. node_type = get_node_type(model, node_id)
  126. dest_types.append(node_type)
  127. return type_id in dest_types
  128. def is_edge_supported(from_type, to_type):
  129. """
  130. True if an association between from_type and to_type exists in any example model
  131. False otherwise
  132. """
  133. for m in all_example_models():
  134. nodes_from = all_nodes_with_type(m, from_type)
  135. nodes_to = all_nodes_with_type(m, to_type)
  136. for nf in nodes_from:
  137. for nt in nodes_to:
  138. assocs = get_associations_between(m, nf, nt)
  139. if assocs:
  140. # somewhere in an example model, there is such an association
  141. return True
  142. return False
  143. def new_instance_model():
  144. """
  145. Adds a new, empty instance model to the Modelverse.
  146. Returns the name of the new model
  147. """
  148. existing_models = all_instance_models()
  149. idx = 1
  150. nums = []
  151. for model in existing_models:
  152. m = model.split("/")[-1]
  153. try:
  154. idx = int(re.search(r'\d+', m).group())
  155. nums.append(idx)
  156. except AttributeError:
  157. pass
  158. if nums:
  159. idx = sorted(nums)[-1] + 1
  160. im = "models/instance/im{}".format(idx)
  161. print("Adding new instance model {}".format(im))
  162. mv.model_add(im, "formalisms/graphMM")
  163. mid = mv.instantiate(im, "Model")
  164. mv.attr_assign(im, mid, "is_example", False)
  165. mv.attr_assign(im, mid, "descr", "")
  166. return im
  167. def new_example_model():
  168. """
  169. Adds a new, empty example model to the Modelverse.
  170. Returns the name of the new model
  171. """
  172. existing_models = all_example_models()
  173. idx = 1
  174. nums = []
  175. for model in existing_models:
  176. m = model.split("/")[-1]
  177. try:
  178. idx = int(re.search(r'\d+', m).group())
  179. nums.append(idx)
  180. except AttributeError:
  181. pass
  182. if nums:
  183. idx = sorted(nums)[-1] + 1
  184. exm = "models/example/ex{}".format(idx)
  185. print("Adding new example model {}".format(exm))
  186. mv.model_add(exm, "formalisms/graphMM")
  187. mid = mv.instantiate(exm, "Model")
  188. mv.attr_assign(exm, mid, "is_example", True)
  189. mv.attr_assign(exm, mid, "descr", "")
  190. return exm