model_management.alc 11 KB

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