model_management.alc 12 KB

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