conformance_finding.alc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. include "primitives.alh"
  2. include "object_operations.alh"
  3. include "typing.alh"
  4. Boolean function find_type_mapping(model : Element):
  5. // Finds a correct type mapping for the provided model (with partial type mapping)
  6. // We go through several phases:
  7. // 1) remove elements from type mapping that are not in the model or metamodel
  8. // 2) find a mapping based on the current partial mapping
  9. // 3) (optional) verify that the mapping is correct with conformance checking
  10. // Returns True if the type mapping was altered
  11. // Start of with some initialization
  12. Element tm
  13. Element elems
  14. String elem
  15. Element diff
  16. tm = get_type_mapping_as_dict(model)
  17. // 1a) remove elements from type mapping that are not in the model
  18. Element reverse
  19. reverse = make_reverse_dictionary_multi(tm)
  20. elems = dict_keys(reverse)
  21. diff = set_difference(elems, dict_keys(model["metamodel"]["model"]))
  22. while (set_len(diff) > 0):
  23. elems = reverse[set_pop(diff)]
  24. while (set_len(elems) > 0):
  25. dict_delete(tm, set_pop(elems))
  26. // 1b) remove elements from type mapping that are not in the model
  27. elems = dict_keys(tm)
  28. if (bool_not(set_equality(elems, dict_keys(model["model"])))):
  29. // First do a simplified check to see which ones are known to be there
  30. diff = set_difference(elems, dict_keys(model["model"]))
  31. while (set_len(diff) > 0):
  32. elem = set_pop(diff)
  33. dict_delete(tm, elem)
  34. // 2) find a mapping based on the current partial mapping, but only if it is not yet complete
  35. // TODO this must be expanded for other things than trivial metamodels!
  36. //if (dict_len(model["model"]) > dict_len(tm)):
  37. if (set_len(set_difference(dict_keys(model["model"]), dict_keys(tm))) > 0):
  38. // TODO for now, this only returns something for a simple case, where the MM has one edge, and one node
  39. // and it makes the assumption that SCD is the M3 level...
  40. // First find the name of the edge and node elements
  41. Element elems
  42. String elem
  43. Element nodes
  44. Element edges
  45. nodes = allInstances(model["metamodel"], "Class")
  46. edges = allInstances(model["metamodel"], "Association")
  47. // Filter out classes from the associations
  48. Element new_nodes
  49. String node
  50. new_nodes = set_create()
  51. while (set_len(nodes) > 0):
  52. node = set_pop(nodes)
  53. if (bool_not(is_edge(model["metamodel"]["model"][node]))):
  54. set_add(new_nodes, node)
  55. nodes = new_nodes
  56. log("Nodes: " + set_to_string(nodes))
  57. log("Edges: " + set_to_string(edges))
  58. // Simple allocation: this seems like conformance bottom
  59. if (bool_and(set_len(edges) == 1, set_len(nodes) == 1)):
  60. String node_source_element
  61. String edge_element
  62. node_source_element = set_pop(nodes)
  63. edge_element = set_pop(edges)
  64. elems = dict_keys(model["model"])
  65. while (set_len(elems) > 0):
  66. elem = set_pop(elems)
  67. if (is_edge(model["model"][elem])):
  68. retype(model, elem, edge_element)
  69. else:
  70. retype(model, elem, node_source_element)
  71. return True!
  72. // Simple allocation: this seems like a traceability model or so
  73. // Make sure to check that the edge goes from one node to the other!
  74. if (bool_and(set_len(edges) == 1, set_len(nodes) == 2)):
  75. String node_target_element
  76. String node_source_element
  77. String edge_element
  78. edge_element = set_pop(edges)
  79. node_source_element = readAssociationSource(model["metamodel"], edge_element)
  80. node_target_element = readAssociationDestination(model["metamodel"], edge_element)
  81. if (value_eq(node_source_element, node_target_element)):
  82. log("Could not automatically deduce mapping in a trivial way!")
  83. return False!
  84. elems = dict_keys(model["model"])
  85. while (set_len(elems) > 0):
  86. elem = set_pop(elems)
  87. if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)):
  88. // An edge, and there is always exactly one, so type
  89. retype(model, elem, edge_element)
  90. // The source and target are ALWAYS typed as well!
  91. retype(model, readAssociationSource(model, elem), node_source_element)
  92. retype(model, readAssociationDestination(model, elem), node_target_element)
  93. return True!
  94. // Simple allocation: this seems like a dictionary model or so
  95. if (bool_and(set_len(edges) == 2, set_len(nodes) == 3)):
  96. String main_edge
  97. String small_edge
  98. main_edge = set_pop(edges)
  99. small_edge = set_pop(edges)
  100. if (readAssociationSource(model["metamodel"], main_edge) == small_edge):
  101. // Switch both
  102. String tmp
  103. tmp = main_edge
  104. main_edge = small_edge
  105. small_edge = tmp
  106. if (readAssociationSource(model["metamodel"], small_edge) == main_edge):
  107. String origin
  108. String value
  109. String key
  110. String middle_edge
  111. origin = readAssociationSource(model["metamodel"], main_edge)
  112. value = readAssociationDestination(model["metamodel"], main_edge)
  113. key = readAssociationDestination(model["metamodel"], small_edge)
  114. if (bool_and(bool_and(origin != value, origin != key), value != key)):
  115. // All three nodes are different, meaning that we are complete and have identified a simple mapping!
  116. elems = dict_keys(model["model"])
  117. while (set_len(elems) > 0):
  118. elem = set_pop(elems)
  119. if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)):
  120. // An edge with no outgoing links, meaning that it is the small_edge
  121. retype(model, elem, small_edge)
  122. // Source is main_edge and target is key
  123. middle_edge = readAssociationSource(model, elem)
  124. retype(model, middle_edge, main_edge)
  125. retype(model, readAssociationDestination(model, elem), key)
  126. // The main_edge goes from root to the value
  127. retype(model, readAssociationSource(model, middle_edge), origin)
  128. retype(model, readAssociationDestination(model, middle_edge), value)
  129. return True!
  130. log("Could not automatically deduce mapping in a trivial way!")
  131. log("Model: " + set_to_string(dict_keys(model["model"])))
  132. log("TM: " + set_to_string(dict_keys(tm)))
  133. log("DIFF: " + set_to_string(set_difference(dict_keys(model["model"]), dict_keys(tm))))
  134. return False!
  135. return True!