commons.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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, node_type):
  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 = [mv.read_association_destination(model, edge)[0] for edge in outgoings]
  120. dest_types = [get_node_type(model, _node_id) for _node_id in dest_ids]
  121. # also need to check incomings of node_id
  122. incomings = mv.read_incoming(model, node_id, "Edge")
  123. src_ids = [mv.read_association_source(model, edge)[0] for edge in incomings]
  124. src_types = [get_node_type(model, _node_id) for _node_id in src_ids]
  125. return node_type in dest_types + src_types
  126. def is_edge_supported(from_type, to_type):
  127. """
  128. True if an association between from_type and to_type exists in any example model
  129. False otherwise
  130. """
  131. for m in all_example_models():
  132. nodes_from = all_nodes_with_type(m, from_type)
  133. nodes_to = all_nodes_with_type(m, to_type)
  134. for nf in nodes_from:
  135. for nt in nodes_to:
  136. assocs = get_associations_between(m, nf, nt)
  137. if assocs:
  138. # somewhere in an example model, there is such an association
  139. return True
  140. return False
  141. def new_instance_model():
  142. """
  143. Adds a new, empty instance model to the Modelverse.
  144. Returns the name of the new model
  145. """
  146. existing_models = all_instance_models()
  147. idx = 1
  148. nums = []
  149. for model in existing_models:
  150. m = model.split("/")[-1]
  151. try:
  152. idx = int(re.search(r'\d+', m).group())
  153. nums.append(idx)
  154. except AttributeError:
  155. pass
  156. if nums:
  157. idx = sorted(nums)[-1] + 1
  158. im = "models/instance/im{}".format(idx)
  159. print("Adding new instance model {}".format(im))
  160. mv.model_add(im, "formalisms/graphMM")
  161. mid = mv.instantiate(im, "Model")
  162. mv.attr_assign(im, mid, "is_example", False)
  163. mv.attr_assign(im, mid, "descr", "")
  164. return im
  165. def new_example_model():
  166. """
  167. Adds a new, empty example model to the Modelverse.
  168. Returns the name of the new model
  169. """
  170. existing_models = all_example_models()
  171. idx = 1
  172. nums = []
  173. for model in existing_models:
  174. m = model.split("/")[-1]
  175. try:
  176. idx = int(re.search(r'\d+', m).group())
  177. nums.append(idx)
  178. except AttributeError:
  179. pass
  180. if nums:
  181. idx = sorted(nums)[-1] + 1
  182. exm = "models/example/ex{}".format(idx)
  183. print("Adding new example model {}".format(exm))
  184. mv.model_add(exm, "formalisms/graphMM")
  185. mid = mv.instantiate(exm, "Model")
  186. mv.attr_assign(exm, mid, "is_example", True)
  187. mv.attr_assign(exm, mid, "descr", "")
  188. return exm