object_operations.alc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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 getAttributeList(model : Element, element : String):
  91. Element result
  92. Element keys
  93. Element type
  94. Element attr_name
  95. Element types
  96. String attr_type
  97. result = create_node()
  98. types = get_superclasses(model["metamodel"], read_type(model, element))
  99. while (read_nr_out(types) > 0):
  100. type = set_pop(types)
  101. // Add our own attributes
  102. keys = dict_keys(model["metamodel"]["model"][type])
  103. while (read_nr_out(keys) > 0):
  104. attr_name = set_pop(keys)
  105. if (is_physical_string(attr_name)):
  106. attr_type = reverseKeyLookup(model["metamodel"]["model"], model["metamodel"]["model"][type][attr_name])
  107. // WARNING: do not change this to dict_add_fast, as this crashes random code...
  108. dict_add(result, attr_name, attr_type)
  109. return result!
  110. Element function getInstantiatableAttributes(model : Element, element : String):
  111. // TODO check if this works!
  112. //output("WARNING: untested code triggered")
  113. Element all_links
  114. Element result
  115. String link
  116. result = create_node()
  117. all_links = allOutgoingAssociationInstances(model, element, "Attribute")
  118. while (read_nr_out(all_links) > 0):
  119. link = set_pop(all_links)
  120. // WARNING: do not change this to dict_add_fast, as this crashes random code...
  121. dict_add(result, read_attribute(model, link, "name"), read_type(model, readAssociationDestination(model, link)))
  122. return result!
  123. String function reverseKeyLookup(dict : Element, element : Element):
  124. // TODO don't know if this AL will actually work...
  125. Integer nr_in
  126. Integer nr_out
  127. Integer counter
  128. Element link
  129. nr_in = read_nr_in(element)
  130. counter = 0
  131. while (counter < nr_in):
  132. if (element_eq(read_edge_src(read_in(element, counter)), dict)):
  133. // Got a match
  134. return (read_edge_dst(read_out(read_in(element, counter), 0)))!
  135. counter = counter + 1
  136. return string_join(string_join("(unknown: ", cast_e2s(element)), " )")!
  137. Element function reverseKeyLookupMulti(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. Element result
  144. result = create_node()
  145. nr_in = read_nr_in(element)
  146. counter = 0
  147. while (counter < nr_in):
  148. if (element_eq(read_edge_src(read_in(element, counter)), dict)):
  149. // Got a match
  150. set_add(result, read_edge_dst(read_out(read_in(element, counter), 0)))
  151. counter = counter + 1
  152. return result!
  153. String function print_dict(dict : Element):
  154. Element keys
  155. Element key
  156. String result
  157. keys = dict_keys(dict)
  158. result = ""
  159. while (0 < list_len(keys)):
  160. key = set_pop(keys)
  161. result = result + cast_v2s(key)
  162. result = result + ": "
  163. result = result + cast_v2s(dict[key])
  164. result = result + "\n"
  165. return result!
  166. String function readAssociationSource(model : Element, name : String):
  167. return reverseKeyLookup(model["model"], read_edge_src(model["model"][name]))!
  168. String function readAssociationDestination(model : Element, name : String):
  169. return reverseKeyLookup(model["model"], read_edge_dst(model["model"][name]))!
  170. Element function allAssociationDestinations(model : Element, name : String, association_type : String):
  171. Element tmp
  172. Element result
  173. result = create_node()
  174. tmp = allOutgoingAssociationInstances(model, name, association_type)
  175. while (read_nr_out(tmp) > 0):
  176. set_add(result, readAssociationDestination(model, set_pop(tmp)))
  177. return result!
  178. Element function allAssociationOrigins(model : Element, name : String, association_type : String):
  179. Element tmp
  180. Element result
  181. result = create_node()
  182. tmp = allIncomingAssociationInstances(model, name, association_type)
  183. while (read_nr_out(tmp) > 0):
  184. set_add(result, readAssociationSource(model, set_pop(tmp)))
  185. return result!
  186. Element function allowedAssociationsBetween(model : Element, src : String, dst : String):
  187. // Go to the type and find all possibilities
  188. String type
  189. Element all_types
  190. Integer nr_edges
  191. Integer i
  192. Element result
  193. Element edge
  194. String edge_name
  195. String dst_name
  196. result = create_node()
  197. type = read_type(model, src)
  198. all_types = get_superclasses(model["metamodel"], type)
  199. while (read_nr_out(all_types) > 0):
  200. type = set_pop(all_types)
  201. nr_edges = read_nr_out(model["metamodel"]["model"][type])
  202. i = 0
  203. while (i < nr_edges):
  204. edge = read_out(model["metamodel"]["model"][type], i)
  205. if (set_in(model["metamodel"]["model"], edge)):
  206. // Find destination
  207. dst_name = reverseKeyLookup(model["metamodel"]["model"], read_edge_dst(edge))
  208. edge_name = reverseKeyLookup(model["metamodel"]["model"], edge)
  209. if (is_nominal_instance(model, dst, dst_name)):
  210. // Find out whether our dst is an instance of the found destination type
  211. if (is_nominal_instance(model["metamodel"], edge_name, "Association")):
  212. set_add(result, edge_name)
  213. i = i + 1
  214. return result!
  215. String function read_type(model : Element, name : String):
  216. String result
  217. Element tm
  218. if (dict_in(model["model"], name)):
  219. if (dict_in(model["type_mapping"], name)):
  220. result = model["type_mapping"][name]
  221. if (dict_in(model["metamodel"]["model"], result)):
  222. return result!
  223. else:
  224. log("Could not find " + result)
  225. return ""!
  226. else:
  227. log("Untyped " + name)
  228. return ""!
  229. else:
  230. log("Couldn't find type of " + name)
  231. return ""!