model_management.alc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. include "primitives.alh"
  2. include "io.alh"
  3. include "object_operations.alh"
  4. include "constructors.alh"
  5. include "metamodels.alh"
  6. include "library.alh"
  7. include "modelling.alh"
  8. Element function model_fuse(models : Element):
  9. Element new_model
  10. Element tagged_model
  11. String model_name
  12. Element model
  13. Element keys
  14. Element second_keys
  15. String key
  16. Element selected_MM
  17. String type
  18. Element reverse
  19. // Read out some data first
  20. tagged_model = set_pop(models)
  21. set_add(models, tagged_model)
  22. new_model = instantiate_model(tagged_model[1]["metamodel"])
  23. // Do the iteration
  24. while (read_nr_out(models) > 0):
  25. tagged_model = set_pop(models)
  26. model_name = string_join(list_read(tagged_model, 0), "/")
  27. model = list_read(tagged_model, 1)
  28. reverse = make_reverse_dictionary(model["model"])
  29. // Add all elements from 'model', but prepend it with the 'model_name'
  30. keys = dict_keys(model["model"])
  31. second_keys = create_node()
  32. while (read_nr_out(keys) > 0):
  33. key = set_pop(keys)
  34. type = read_type(model, key)
  35. if (is_edge(model["model"][key])):
  36. String src
  37. String dst
  38. src = string_join(model_name, reverse[cast_id2s(read_edge_src(model["model"][key]))])
  39. dst = string_join(model_name, reverse[cast_id2s(read_edge_dst(model["model"][key]))])
  40. if (bool_and(dict_in(new_model["model"], src), dict_in(new_model["model"], dst))):
  41. instantiate_link(new_model, type, model_name + key, src, dst)
  42. else:
  43. set_add(second_keys, key)
  44. elif (has_value(model["model"][key])):
  45. instantiate_value(new_model, type, model_name + key, model["model"][key])
  46. else:
  47. instantiate_node(new_model, type, model_name + key)
  48. if (read_nr_out(keys) == 0):
  49. keys = second_keys
  50. second_keys = create_node()
  51. return new_model!
  52. Element function model_copy(src_model : Element):
  53. Element dst_model
  54. Element name
  55. Element keys
  56. Element second_keys
  57. String type
  58. Element reverse
  59. reverse = make_reverse_dictionary(src_model["model"])
  60. dst_model = instantiate_model(src_model["metamodel"])
  61. keys = dict_keys(src_model["model"])
  62. second_keys = create_node()
  63. while (read_nr_out(keys) > 0):
  64. name = set_pop(keys)
  65. if (is_edge(src_model["model"][name])):
  66. // Is an edge, so potentially queue it
  67. String src
  68. String dst
  69. src = reverse[cast_id2s(read_edge_src(src_model["model"][name]))]
  70. dst = reverse[cast_id2s(read_edge_dst(src_model["model"][name]))]
  71. type = read_type(src_model, name)
  72. if (bool_and(dict_in(dst_model["model"], src), dict_in(dst_model["model"], dst))):
  73. // All present, so create the link between them
  74. instantiate_link(dst_model, type, name, src, dst)
  75. else:
  76. set_add(second_keys, name)
  77. elif (has_value(src_model["model"][name])):
  78. // Has a value, so copy that as well
  79. type = read_type(src_model, name)
  80. instantiate_value(dst_model, type, name, src_model["model"][name])
  81. else:
  82. // Is a node
  83. type = read_type(src_model, name)
  84. instantiate_node(dst_model, type, name)
  85. if (read_nr_out(keys) == 0):
  86. keys = second_keys
  87. second_keys = create_node()
  88. return dst_model!
  89. Element function model_retype_on_name(model : Element, new_MM : Element, operation : String, name : String):
  90. String key
  91. String type
  92. Element keys
  93. Integer length
  94. keys = dict_keys(model["model"])
  95. length = string_len(name)
  96. while (read_nr_out(keys) > 0):
  97. key = set_pop(keys)
  98. if (dict_in(model["model"], key)):
  99. // Check if the element is still there, as a delete of a node might remove all attached links automatically
  100. type = read_type(model, key)
  101. if (operation == "+"):
  102. // Keep all, but augment typename
  103. dict_delete(model["type_mapping"], key)
  104. dict_add_fast(model["type_mapping"], key, name + type)
  105. elif (operation == "-"):
  106. // Keep only if typename beginning matches and remove from typename
  107. if (string_startswith(type, name)):
  108. dict_delete(model["type_mapping"], key)
  109. dict_add_fast(model["type_mapping"], key, string_substr(type, length, string_len(type)))
  110. else:
  111. model_delete_element(model, key)
  112. dict_delete(model, "metamodel")
  113. dict_add_fast(model, "metamodel", new_MM)
  114. return model!
  115. Element function model_join(models : Element, metamodel : Element, tracability_model : Element):
  116. Element new_model
  117. Element tagged_model
  118. String retyping_key
  119. Element elem_map
  120. Element model
  121. Element keys
  122. String new_name
  123. Element second_keys
  124. String src
  125. String dst
  126. String key
  127. String type
  128. new_model = instantiate_model(metamodel)
  129. elem_map = create_node()
  130. // Do the iteration
  131. while (read_nr_out(models) > 0):
  132. tagged_model = set_pop(models)
  133. retyping_key = string_join(list_read(tagged_model, 0), "/")
  134. model = list_read(tagged_model, 1)
  135. // Add all elements from 'model'
  136. keys = dict_keys(model["model"])
  137. second_keys = create_node()
  138. while (read_nr_out(keys) > 0):
  139. // Copy the new element
  140. key = set_pop(keys)
  141. type = read_type(model, key)
  142. if (is_edge(model["model"][key])):
  143. src = cast_id2s(read_edge_src(model["model"][key]))
  144. dst = cast_id2s(read_edge_dst(model["model"][key]))
  145. if (bool_and(dict_in(elem_map, src), dict_in(elem_map, dst))):
  146. new_name = instantiate_link(new_model, retyping_key + type, "", elem_map[src], elem_map[dst])
  147. else:
  148. set_add(second_keys, key)
  149. new_name = ""
  150. elif (has_value(model["model"][key])):
  151. new_name = instantiate_value(new_model, retyping_key + type, "", model["model"][key])
  152. else:
  153. new_name = instantiate_node(new_model, retyping_key + type, "")
  154. if (new_name != ""):
  155. // Add the new name to a map which registers the mapping to the new name
  156. dict_add_fast(elem_map, cast_id2s(model["model"][key]), new_name)
  157. if (read_nr_out(keys) == 0):
  158. keys = second_keys
  159. second_keys = create_node()
  160. // Now link in the tracability model
  161. // Go over all TracabilityLink elements and connect them in the merged model as well
  162. if (element_neq(tracability_model, read_root())):
  163. Element tracability_links
  164. String tracability_link
  165. String new_name_src
  166. String new_name_dst
  167. tracability_links = allInstances(tracability_model, "TracabilityLink")
  168. while (read_nr_out(tracability_links) > 0):
  169. log("Using tracability link!")
  170. tracability_link = set_pop(tracability_links)
  171. // Get necessary information from the tracability link
  172. new_name_src = elem_map[cast_id2s(read_edge_src(tracability_model["model"][tracability_link]))]
  173. new_name_dst = elem_map[cast_id2s(read_edge_dst(tracability_model["model"][tracability_link]))]
  174. type = read_attribute(tracability_model, tracability_link, "type")
  175. // Connect the two with the info we have
  176. new_name = instantiate_link(new_model, type, "", new_name_src, new_name_dst)
  177. if (new_name == ""):
  178. log("ERROR: could not create a tracability link; ignoring")
  179. return new_model!
  180. Element function model_split(merged_model : Element, models : Element, tracability : Boolean):
  181. Element result
  182. Element metamodel
  183. Element model_tuple
  184. Element tracability_model
  185. Element keys
  186. String key
  187. String src
  188. String dst
  189. Element reverse
  190. Element mapping
  191. String retyping_key
  192. String original_type
  193. Element elem
  194. Element second_keys
  195. String type
  196. Element splitted
  197. String source
  198. String target
  199. String link
  200. result = create_node()
  201. tracability_model = instantiate_model(import_node("models/Tracability"))
  202. reverse = make_reverse_dictionary(merged_model["model"])
  203. mapping = create_node()
  204. second_keys = create_node()
  205. while (read_nr_out(models) > 0):
  206. model_tuple = set_pop(models)
  207. retyping_key = model_tuple[0]
  208. metamodel = model_tuple[1]
  209. dict_add_fast(result, retyping_key, instantiate_model(metamodel))
  210. keys = dict_keys(merged_model["model"])
  211. while (read_nr_out(keys) > 0):
  212. key = set_pop(keys)
  213. elem = merged_model["model"][key]
  214. type = read_type(merged_model, key)
  215. splitted = string_split(type, "/")
  216. if (list_len(splitted) == 1):
  217. // Only one, so no split possible
  218. // Indicates a tracability element!
  219. if (bool_and(tracability, is_edge(elem))):
  220. // Got a tracability link!
  221. // Is always an edge (for now?)
  222. // Find out source and target and hope that they are already present
  223. src = reverse[cast_id2s(read_edge_src(elem))]
  224. dst = reverse[cast_id2s(read_edge_dst(elem))]
  225. // All present, so create the link between them
  226. source = reuse_element(tracability_model, "Reference", "", read_edge_src(elem))
  227. target = reuse_element(tracability_model, "Reference", "", read_edge_dst(elem))
  228. link = instantiate_link(tracability_model, "TracabilityLink", "", source, target)
  229. instantiate_attribute(tracability_model, link, "type", type)
  230. else:
  231. retyping_key = splitted[0]
  232. if (dict_in(result, retyping_key)):
  233. original_type = splitted[1]
  234. if (is_edge(elem)):
  235. // Is an edge, so potentially queue it
  236. src = reverse[cast_id2s(read_edge_src(elem))]
  237. dst = reverse[cast_id2s(read_edge_dst(elem))]
  238. if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
  239. // All present, so create the link between them
  240. // Though we first check the model to which it was mapped, as this should be the same as we have now
  241. if (bool_and(dict_in(result[retyping_key]["model"], mapping[src]), dict_in(result[retyping_key]["model"], mapping[dst]))):
  242. // The matching worked fine
  243. dict_add_fast(mapping, key, instantiate_link(result[retyping_key], original_type, "", mapping[src], mapping[dst]))
  244. else:
  245. log("ERROR mapping: source/target mapped to model, but not found in expected model; ignoring")
  246. else:
  247. // Still source or destination in the queue, so we wait for that
  248. set_add(second_keys, key)
  249. elif (has_value(elem)):
  250. // Has a value, so copy that as well
  251. dict_add_fast(mapping, key, instantiate_value(result[retyping_key], original_type, "", elem))
  252. else:
  253. // Is a node
  254. dict_add_fast(mapping, key, instantiate_node(result[retyping_key], original_type, ""))
  255. if (read_nr_out(keys) == 0):
  256. keys = second_keys
  257. second_keys = create_node()
  258. // Finally, we also add tracability information as a separate model
  259. if (tracability):
  260. dict_add_fast(result, "__tracability", tracability_model)
  261. return result!