model_management.alc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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, key, 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, key, model["model"][key])
  152. else:
  153. new_name = instantiate_node(new_model, retyping_key + type, key)
  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. tracability_link = set_pop(tracability_links)
  170. // Get necessary information from the tracability link
  171. new_name_src = elem_map[cast_id2s(read_edge_src(tracability_model["model"][tracability_link]))]
  172. new_name_dst = elem_map[cast_id2s(read_edge_dst(tracability_model["model"][tracability_link]))]
  173. type = read_attribute(tracability_model, tracability_link, "type")
  174. // Connect the two with the info we have
  175. new_name = instantiate_link(new_model, type, "", new_name_src, new_name_dst)
  176. if (new_name == ""):
  177. log("ERROR: could not create a tracability link; ignoring")
  178. return new_model!
  179. Element function model_split(merged_model : Element, models : Element, tracability : Boolean):
  180. if (read_nr_out(models) == 0):
  181. // No results needed, so stop immediately unless tracability is True
  182. if (bool_not(tracability)):
  183. return create_node()!
  184. Element result
  185. Element metamodel
  186. Element model_tuple
  187. Element tracability_model
  188. Element keys
  189. String key
  190. String src
  191. String dst
  192. Element reverse
  193. Element mapping
  194. String retyping_key
  195. String original_type
  196. Element elem
  197. Element second_keys
  198. String type
  199. Element splitted
  200. String source
  201. String target
  202. String link
  203. String src_name
  204. String dst_name
  205. result = create_node()
  206. tracability_model = instantiate_model(import_node("models/Tracability"))
  207. reverse = make_reverse_dictionary(merged_model["model"])
  208. mapping = create_node()
  209. second_keys = create_node()
  210. while (read_nr_out(models) > 0):
  211. model_tuple = set_pop(models)
  212. retyping_key = model_tuple[0]
  213. metamodel = model_tuple[1]
  214. dict_add_fast(result, retyping_key, instantiate_model(metamodel))
  215. keys = dict_keys(merged_model["model"])
  216. while (read_nr_out(keys) > 0):
  217. key = set_pop(keys)
  218. elem = merged_model["model"][key]
  219. type = read_type(merged_model, key)
  220. splitted = string_split(type, "/")
  221. if (list_len(splitted) == 1):
  222. // Only one, so no split possible
  223. // Indicates a tracability element!
  224. if (bool_and(tracability, is_edge(elem))):
  225. // Got a tracability link!
  226. // Is always an edge (for now?)
  227. // Find out source and target and hope that they are already present
  228. log("Create tracability link in model!")
  229. src = reverse[cast_id2s(read_edge_src(elem))]
  230. dst = reverse[cast_id2s(read_edge_dst(elem))]
  231. src_name = list_read(string_split(read_type(merged_model, src), "/"), 0)
  232. dst_name = list_read(string_split(read_type(merged_model, dst), "/"), 0)
  233. log("Source model name: " + cast_v2s(src_name))
  234. log("Destination model name: " + cast_v2s(dst_name))
  235. log("Result: " + dict_to_string(result))
  236. // Check if we actually keep both models around, as otherwise it is useless anyway
  237. if (bool_and(dict_in(result, src_name), dict_in(result, dst_name))):
  238. if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
  239. // All present, so create the link between them
  240. Element src_model
  241. Element dst_model
  242. src_model = result[src_name]
  243. dst_model = result[dst_name]
  244. source = reuse_element(tracability_model, "Reference", "", src_model["model"][mapping[src]])
  245. target = reuse_element(tracability_model, "Reference", "", dst_model["model"][mapping[dst]])
  246. link = instantiate_link(tracability_model, "TracabilityLink", "", source, target)
  247. instantiate_attribute(tracability_model, link, "type", type)
  248. else:
  249. // Not yet available!
  250. set_add(second_keys, key)
  251. else:
  252. retyping_key = splitted[0]
  253. if (dict_in(result, retyping_key)):
  254. original_type = splitted[1]
  255. if (is_edge(elem)):
  256. // Is an edge, so potentially queue it
  257. src = reverse[cast_id2s(read_edge_src(elem))]
  258. dst = reverse[cast_id2s(read_edge_dst(elem))]
  259. if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
  260. // All present, so create the link between them
  261. // Though we first check the model to which it was mapped, as this should be the same as we have now
  262. if (bool_and(dict_in(result[retyping_key]["model"], mapping[src]), dict_in(result[retyping_key]["model"], mapping[dst]))):
  263. // The matching worked fine
  264. dict_add_fast(mapping, key, instantiate_link(result[retyping_key], original_type, "", mapping[src], mapping[dst]))
  265. else:
  266. log("ERROR mapping: source/target mapped to model, but not found in expected model; ignoring")
  267. else:
  268. // Still source or destination in the queue, so we wait for that
  269. set_add(second_keys, key)
  270. elif (has_value(elem)):
  271. // Has a value, so copy that as well
  272. dict_add_fast(mapping, key, instantiate_value(result[retyping_key], original_type, "", elem))
  273. else:
  274. // Is a node
  275. dict_add_fast(mapping, key, instantiate_node(result[retyping_key], original_type, ""))
  276. if (read_nr_out(keys) == 0):
  277. keys = second_keys
  278. second_keys = create_node()
  279. // Finally, we also add tracability information as a separate model
  280. if (tracability):
  281. dict_add_fast(result, "__tracability", tracability_model)
  282. log("Tracability model created with # links = " + cast_v2s(read_nr_out(tracability_model["model"])))
  283. return result!