model_management.alc 9.9 KB

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