model_management.alc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. include "utils.alh"
  9. Element function model_fuse(models : Element):
  10. Element new_model
  11. Element tagged_model
  12. String model_name
  13. Element model
  14. Element keys
  15. Element second_keys
  16. String key
  17. Element selected_MM
  18. String type
  19. Element reverse
  20. // Read out some data first
  21. if (set_len(models) == 0):
  22. log("Cannot fuse empty set of models!")
  23. return read_root()!
  24. tagged_model = set_read(models)
  25. new_model = instantiate_model(tagged_model[1]["metamodel"])
  26. // Do the iteration
  27. while (set_len(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 = set_create()
  35. while (set_len(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_id(read_edge_src(model["model"][key]))])
  42. dst = string_join(model_name, reverse[cast_id(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 (set_len(keys) == 0):
  52. keys = second_keys
  53. second_keys = set_create()
  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 = set_create()
  66. while (set_len(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_id(read_edge_src(src_model["model"][name]))]
  73. dst = reverse[cast_id(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 (set_len(keys) == 0):
  89. keys = second_keys
  90. second_keys = set_create()
  91. return dst_model!
  92. Element function model_join(models : Element, metamodel : Element, tracability_model : Element):
  93. Element new_model
  94. Element tagged_model
  95. String retyping_key
  96. Element elem_map
  97. Element model
  98. Element keys
  99. String new_name
  100. Element second_keys
  101. String src
  102. String dst
  103. String key
  104. String type
  105. new_model = instantiate_model(metamodel)
  106. elem_map = dict_create()
  107. Element retyping_keys
  108. retyping_keys = set_create()
  109. // Do the iteration
  110. while (set_len(models) > 0):
  111. tagged_model = set_pop(models)
  112. retyping_key = string_join(list_read(tagged_model, 0), "/")
  113. model = list_read(tagged_model, 1)
  114. set_add(retyping_keys, retyping_key)
  115. // Add all elements from 'model'
  116. keys = dict_keys(model["model"])
  117. second_keys = set_create()
  118. while (set_len(keys) > 0):
  119. // Copy the new element
  120. key = set_pop(keys)
  121. type = read_type(model, key)
  122. new_name = retyping_key + key
  123. if (is_edge(model["model"][key])):
  124. src = cast_id(read_edge_src(model["model"][key]))
  125. dst = cast_id(read_edge_dst(model["model"][key]))
  126. if (bool_and(dict_in(elem_map, src), dict_in(elem_map, dst))):
  127. new_name = instantiate_link(new_model, retyping_key + type, new_name, elem_map[src], elem_map[dst])
  128. else:
  129. set_add(second_keys, key)
  130. new_name = ""
  131. elif (has_value(model["model"][key])):
  132. new_name = instantiate_value(new_model, retyping_key + type, new_name, model["model"][key])
  133. else:
  134. new_name = instantiate_node(new_model, retyping_key + type, new_name)
  135. if (new_name != ""):
  136. // Add the new name to a map which registers the mapping to the new name
  137. dict_add_fast(elem_map, cast_id(model["model"][key]), new_name)
  138. if (set_len(keys) == 0):
  139. keys = second_keys
  140. second_keys = set_create()
  141. // Now link in the tracability model
  142. // Go over all TracabilityLink elements and connect them in the merged model as well
  143. if (element_neq(tracability_model, read_root())):
  144. Element tracability_links
  145. String tracability_link
  146. String new_name_src
  147. String new_name_dst
  148. String src_name
  149. String dst_name
  150. Element src_models
  151. String src_model
  152. Element dst_models
  153. String dst_model
  154. tracability_links = allInstances(tracability_model, "TracabilityLink")
  155. while (set_len(tracability_links) > 0):
  156. tracability_link = set_pop(tracability_links)
  157. src_name = read_attribute(tracability_model, readAssociationSource(tracability_model, tracability_link), "name")
  158. dst_name = read_attribute(tracability_model, readAssociationDestination(tracability_model, tracability_link), "name")
  159. type = read_attribute(tracability_model, tracability_link, "type")
  160. // Now try to find all possible combinations
  161. // that is, find all models for which src_name exists, and all models for which dst_name exists, and connect them
  162. src_models = set_copy(retyping_keys)
  163. while (set_len(src_models) > 0):
  164. src_model = set_pop(src_models)
  165. if (dict_in(new_model["model"], src_model + src_name)):
  166. // This element exists for this source model
  167. dst_models = set_copy(retyping_keys)
  168. while (set_len(dst_models) > 0):
  169. dst_model = set_pop(dst_models)
  170. if (dict_in(new_model["model"], dst_model + dst_name)):
  171. // Found a match for source and target, so create a link
  172. new_name = instantiate_link(new_model, type, "", src_model + src_name, dst_model + dst_name)
  173. if (new_name == ""):
  174. log("ERROR: could not create a tracability link; ignoring")
  175. return new_model!
  176. Element function model_split(merged_model : Element, models : Element, tracability : Boolean):
  177. if (set_len(models) == 0):
  178. // No results needed, so stop immediately unless tracability is True
  179. if (bool_not(tracability)):
  180. return dict_create()!
  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. String src_name
  201. String dst_name
  202. String new_name
  203. result = dict_create()
  204. tracability_model = instantiate_model(import_node("models/Tracability"))
  205. reverse = make_reverse_dictionary(merged_model["model"])
  206. mapping = dict_create()
  207. second_keys = set_create()
  208. while (set_len(models) > 0):
  209. model_tuple = set_pop(models)
  210. retyping_key = model_tuple[0]
  211. metamodel = model_tuple[1]
  212. dict_add_fast(result, retyping_key, instantiate_model(metamodel))
  213. keys = dict_keys(merged_model["model"])
  214. while (set_len(keys) > 0):
  215. key = set_pop(keys)
  216. elem = merged_model["model"][key]
  217. type = read_type(merged_model, key)
  218. splitted = string_split_nr(type, "/", 1)
  219. if (list_len(splitted) == 1):
  220. // Only one, so no split possible
  221. // Indicates a tracability element!
  222. if (bool_and(tracability, is_edge(elem))):
  223. // Got a tracability link!
  224. // Is always an edge (for now?)
  225. // Find out source and target and hope that they are already present
  226. src = reverse[cast_id(read_edge_src(elem))]
  227. dst = reverse[cast_id(read_edge_dst(elem))]
  228. // All present, so create the link between them
  229. src_name = list_pop_final(string_split_nr(src, "/", 1))
  230. dst_name = list_pop_final(string_split_nr(dst, "/", 1))
  231. source = instantiate_node(tracability_model, "Reference", "")
  232. target = instantiate_node(tracability_model, "Reference", "")
  233. instantiate_attribute(tracability_model, source, "name", src_name)
  234. instantiate_attribute(tracability_model, target, "name", dst_name)
  235. link = instantiate_link(tracability_model, "TracabilityLink", "", source, target)
  236. instantiate_attribute(tracability_model, link, "type", type)
  237. else:
  238. retyping_key = splitted[0]
  239. if (list_len(string_split(key, "/")) > 1):
  240. new_name = list_read(string_split_nr(key, "/", 1), 1)
  241. else:
  242. new_name = key
  243. if (dict_in(result, retyping_key)):
  244. original_type = splitted[1]
  245. if (is_edge(elem)):
  246. // Is an edge, so potentially queue it
  247. src = reverse[cast_id(read_edge_src(elem))]
  248. dst = reverse[cast_id(read_edge_dst(elem))]
  249. if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
  250. // All present, so create the link between them
  251. // Though we first check the model to which it was mapped, as this should be the same as we have now
  252. if (bool_and(dict_in(result[retyping_key]["model"], mapping[src]), dict_in(result[retyping_key]["model"], mapping[dst]))):
  253. // The matching worked fine
  254. dict_add_fast(mapping, key, instantiate_link(result[retyping_key], original_type, new_name, mapping[src], mapping[dst]))
  255. else:
  256. log("ERROR mapping: source/target mapped to model, but not found in expected model; ignoring")
  257. else:
  258. // Still source or destination in the queue, so we wait for that
  259. set_add(second_keys, key)
  260. elif (has_value(elem)):
  261. // Has a value, so copy that as well
  262. dict_add_fast(mapping, key, instantiate_value(result[retyping_key], original_type, new_name, elem))
  263. else:
  264. // Is a node
  265. dict_add_fast(mapping, key, instantiate_node(result[retyping_key], original_type, new_name))
  266. if (set_len(keys) == 0):
  267. keys = second_keys
  268. second_keys = set_create()
  269. // Finally, we also add tracability information as a separate model
  270. if (tracability):
  271. dict_add_fast(result, "__tracability", tracability_model)
  272. log("Tracability model created with # links = " + cast_value(dict_len(tracability_model["model"])))
  273. return result!