model_management.alc 11 KB

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