object_operations.alc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. include "primitives.alh"
  2. include "conformance_scd.alh"
  3. include "constructors.alh"
  4. include "modelling.alh"
  5. Element function allInstances(model : Element, type_name : String):
  6. if (dict_in(model["metamodel"]["model"], type_name)):
  7. Element result
  8. Element accepted
  9. Element keys
  10. Element tm
  11. String key
  12. String class
  13. Element results
  14. result = create_node()
  15. accepted = get_subclasses(model["metamodel"], type_name)
  16. while (read_nr_out(accepted) > 0):
  17. class = set_pop(accepted)
  18. results = reverseKeyLookupMulti(model["type_mapping"], class)
  19. set_merge(result, results)
  20. return result!
  21. else:
  22. log("No such type in the metamodel: " + type_name)
  23. return create_node()!
  24. Element function selectPossibleIncoming(model : Element, target : String, limit_set : Element):
  25. // Find all possible incoming link types for the target model
  26. // Should also include those specified on the superclass(es)
  27. String type
  28. Element model_dict
  29. Element elem
  30. Element result
  31. Element target_element
  32. result = create_node()
  33. model_dict = model["model"]
  34. while (0 < list_len(limit_set)):
  35. type = set_pop(limit_set)
  36. elem = model_dict[type]
  37. if (is_nominal_subtype(model, target, reverseKeyLookup(model_dict, read_edge_dst(elem)))):
  38. set_add(result, type)
  39. return result!
  40. Element function selectPossibleOutgoing(model : Element, source : String, limit_set : Element):
  41. // Find all possible outgoing link types for the source model
  42. // Should also include those specified on the superclass(es)
  43. String type
  44. Element model_dict
  45. Element elem
  46. Element result
  47. Element source_element
  48. result = create_node()
  49. model_dict = model["model"]
  50. while (0 < list_len(limit_set)):
  51. type = set_pop(limit_set)
  52. elem = model_dict[type]
  53. if (is_nominal_subtype(model, source, reverseKeyLookup(model_dict, read_edge_src(elem)))):
  54. set_add(result, type)
  55. return result!
  56. Element function allOutgoingAssociationInstances(model : Element, source_name : String, assoc_name : String):
  57. // Read out all outgoing edges of the model and select those that are typed by the specified association
  58. Element result
  59. Element source
  60. String option
  61. Integer all_out
  62. Integer i
  63. result = create_node()
  64. source = model["model"][source_name]
  65. all_out = read_nr_out(source)
  66. i = 0
  67. while (i < all_out):
  68. option = reverseKeyLookup(model["model"], read_out(source, i))
  69. if (is_nominal_instance(model, option, assoc_name)):
  70. set_add(result, option)
  71. i = i + 1
  72. return result!
  73. Element function allIncomingAssociationInstances(model : Element, target_name : String, assoc_name : String):
  74. // Read out all outgoing edges of the model and select those that are typed by the specified association
  75. Element result
  76. Element source
  77. String option
  78. Integer all_out
  79. Integer i
  80. result = create_node()
  81. source = model["model"][target_name]
  82. all_out = read_nr_in(source)
  83. i = 0
  84. while (i < all_out):
  85. option = reverseKeyLookup(model["model"], read_in(source, i))
  86. if (is_nominal_instance(model, option, assoc_name)):
  87. set_add(result, option)
  88. i = i + 1
  89. return result!
  90. Element function allIncomingAssociationInstances_slow(model : Element, target_name : String, assoc_name : String):
  91. // Read out all outgoing edges of the model and select those that are typed by the specified association
  92. Element assocs
  93. String assoc
  94. Element result
  95. Element target
  96. assocs = allInstances(model, assoc_name)
  97. target = model["model"][target_name]
  98. result = create_node()
  99. while (0 < list_len(assocs)):
  100. assoc = set_pop(assocs)
  101. if (element_eq(target, read_edge_dst(model["model"][assoc]))):
  102. set_add(result, assoc)
  103. return result!
  104. Element function getAttributeList(model : Element, element : String):
  105. Element result
  106. Element keys
  107. Element type
  108. Element attr_name
  109. Element types
  110. String attr_type
  111. result = create_node()
  112. types = get_superclasses(model["metamodel"], read_type(model, element))
  113. while (read_nr_out(types) > 0):
  114. type = set_pop(types)
  115. // Add our own attributes
  116. keys = dict_keys(model["metamodel"]["model"][type])
  117. while (read_nr_out(keys) > 0):
  118. attr_name = set_pop(keys)
  119. if (is_physical_string(attr_name)):
  120. attr_type = reverseKeyLookup(model["metamodel"]["model"], model["metamodel"]["model"][type][attr_name])
  121. // WARNING: do not change this to dict_add_fast, as this crashes random code...
  122. dict_add(result, attr_name, attr_type)
  123. return result!
  124. Element function getInstantiatableAttributes(model : Element, element : String):
  125. // TODO check if this works!
  126. //output("WARNING: untested code triggered")
  127. Element all_links
  128. Element result
  129. String link
  130. result = create_node()
  131. all_links = allOutgoingAssociationInstances(model, element, "Attribute")
  132. while (read_nr_out(all_links) > 0):
  133. link = set_pop(all_links)
  134. // WARNING: do not change this to dict_add_fast, as this crashes random code...
  135. dict_add(result, read_attribute(model, link, "name"), read_type(model, readAssociationDestination(model, link)))
  136. return result!
  137. String function reverseKeyLookup(dict : Element, element : Element):
  138. // TODO don't know if this AL will actually work...
  139. Integer nr_in
  140. Integer nr_out
  141. Integer counter
  142. Element link
  143. nr_in = read_nr_in(element)
  144. counter = 0
  145. while (counter < nr_in):
  146. if (element_eq(read_edge_src(read_in(element, counter)), dict)):
  147. // Got a match
  148. return (read_edge_dst(read_out(read_in(element, counter), 0)))!
  149. counter = counter + 1
  150. return string_join(string_join("(unknown: ", cast_e2s(element)), " )")!
  151. Element function reverseKeyLookupMulti(dict : Element, element : Element):
  152. // TODO don't know if this AL will actually work...
  153. Integer nr_in
  154. Integer nr_out
  155. Integer counter
  156. Element link
  157. Element result
  158. result = create_node()
  159. nr_in = read_nr_in(element)
  160. counter = 0
  161. while (counter < nr_in):
  162. if (element_eq(read_edge_src(read_in(element, counter)), dict)):
  163. // Got a match
  164. set_add(result, read_edge_dst(read_out(read_in(element, counter), 0)))
  165. counter = counter + 1
  166. return result!
  167. String function print_dict(dict : Element):
  168. Element keys
  169. Element key
  170. String result
  171. keys = dict_keys(dict)
  172. result = ""
  173. while (0 < list_len(keys)):
  174. key = set_pop(keys)
  175. result = result + cast_v2s(key)
  176. result = result + ": "
  177. result = result + cast_v2s(dict[key])
  178. result = result + "\n"
  179. return result!
  180. String function readAssociationSource(model : Element, name : String):
  181. return reverseKeyLookup(model["model"], read_edge_src(model["model"][name]))!
  182. String function readAssociationDestination(model : Element, name : String):
  183. return reverseKeyLookup(model["model"], read_edge_dst(model["model"][name]))!
  184. Element function allAssociationDestinations(model : Element, name : String, association_type : String):
  185. Element tmp
  186. Element result
  187. result = create_node()
  188. tmp = allOutgoingAssociationInstances(model, name, association_type)
  189. while (read_nr_out(tmp) > 0):
  190. set_add(result, readAssociationDestination(model, set_pop(tmp)))
  191. return result!
  192. Element function allAssociationOrigins(model : Element, name : String, association_type : String):
  193. Element tmp
  194. Element result
  195. result = create_node()
  196. tmp = allIncomingAssociationInstances(model, name, association_type)
  197. while (read_nr_out(tmp) > 0):
  198. set_add(result, readAssociationSource(model, set_pop(tmp)))
  199. return result!
  200. Element function allowedAssociationsBetween(model : Element, src : String, dst : String):
  201. // Go to the type and find all possibilities
  202. String type
  203. Element all_types
  204. Integer nr_edges
  205. Integer i
  206. Element result
  207. Element edge
  208. String edge_name
  209. String dst_name
  210. result = create_node()
  211. type = read_type(model, src)
  212. all_types = get_superclasses(model["metamodel"], type)
  213. while (read_nr_out(all_types) > 0):
  214. type = set_pop(all_types)
  215. nr_edges = read_nr_out(model["metamodel"]["model"][type])
  216. i = 0
  217. while (i < nr_edges):
  218. edge = read_out(model["metamodel"]["model"][type], i)
  219. if (set_in(model["metamodel"]["model"], edge)):
  220. // Find destination
  221. dst_name = reverseKeyLookup(model["metamodel"]["model"], read_edge_dst(edge))
  222. edge_name = reverseKeyLookup(model["metamodel"]["model"], edge)
  223. if (is_nominal_instance(model, dst, dst_name)):
  224. // Find out whether our dst is an instance of the found destination type
  225. if (is_nominal_instance(model["metamodel"], edge_name, "Association")):
  226. set_add(result, edge_name)
  227. i = i + 1
  228. return result!
  229. String function read_type(model : Element, name : String):
  230. String result
  231. Element tm
  232. if (dict_in(model["model"], name)):
  233. if (dict_in(model["type_mapping"], name)):
  234. result = model["type_mapping"][name]
  235. if (dict_in(model["metamodel"]["model"], result)):
  236. return result!
  237. else:
  238. log("Could not find " + result)
  239. return ""!
  240. else:
  241. log("Untyped " + name)
  242. log("Type mapping: " + dict_to_string(model["type_mapping"]))
  243. return ""!
  244. else:
  245. log("Couldn't find type of " + name)
  246. return ""!