conformance_finding.alc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. tm = get_type_mapping_as_dict(model)
  16. // 1) remove elements from type mapping that are not in the model or metamodel
  17. elems = dict_keys(tm)
  18. while (set_len(elems) > 0):
  19. elem = set_pop(elems)
  20. if (bool_not(dict_in(model["model"], elem))):
  21. // Remove the key, as the model does not contain the element anymore
  22. dict_delete(tm, elem)
  23. else:
  24. if (bool_not(dict_in(model["metamodel"]["model"], tm[elem]))):
  25. // Remove the key, as the metamodel does not contain the type anymore
  26. dict_delete(tm, elem)
  27. // 2) find a mapping based on the current partial mapping, but only if it is not yet complete
  28. // TODO this must be expanded for other things than trivial metamodels!
  29. if (dict_len(model["model"]) > dict_len(tm)):
  30. // TODO for now, this only returns something for a simple case, where the MM has one edge, and one node
  31. // and it makes the assumption that SCD is the M3 level...
  32. // First find the name of the edge and node elements
  33. Element elems
  34. String elem
  35. Element nodes
  36. Element edges
  37. nodes = allInstances(model["metamodel"], "Class")
  38. edges = allInstances(model["metamodel"], "Association")
  39. // Simple allocation: this seems like conformance bottom
  40. if (bool_and(set_len(edges) == 1, set_len(nodes) == 1)):
  41. String node_source_element
  42. String edge_element
  43. node_source_element = set_pop(nodes)
  44. edge_element = set_pop(edges)
  45. elems = dict_keys(model["model"])
  46. while (set_len(elems) > 0):
  47. elem = set_pop(elems)
  48. if (is_edge(model["model"][elem])):
  49. retype(model, elem, edge_element)
  50. else:
  51. retype(model, elem, node_source_element)
  52. return True!
  53. // Simple allocation: this seems like a traceability model or so
  54. // Make sure to check that the edge goes from one node to the other!
  55. if (bool_and(set_len(edges) == 1, set_len(nodes) == 2)):
  56. String node_target_element
  57. String node_source_element
  58. String edge_element
  59. edge_element = set_pop(edges)
  60. node_source_element = readAssociationSource(model["metamodel"], edge_element)
  61. node_target_element = readAssociationDestination(model["metamodel"], edge_element)
  62. if (value_eq(node_source_element, node_target_element)):
  63. log("Could not automatically deduce mapping in a trivial way!")
  64. return False!
  65. elems = dict_keys(model["model"])
  66. while (set_len(elems) > 0):
  67. elem = set_pop(elems)
  68. if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)):
  69. // An edge, and there is always exactly one, so type
  70. retype(model, elem, edge_element)
  71. // The source and target are ALWAYS typed as well!
  72. retype(model, readAssociationSource(model, elem), node_source_element)
  73. retype(model, readAssociationDestination(model, elem), node_target_element)
  74. return True!
  75. // Simple allocation: this seems like a dictionary model or so
  76. log("Edges: " + cast_string(set_len(edges)))
  77. log("Nodes: " + cast_string(set_len(nodes)))
  78. if (bool_and(set_len(edges) == 2, set_len(nodes) == 3)):
  79. log("Potential dictionary...")
  80. String main_edge
  81. String small_edge
  82. main_edge = set_pop(edges)
  83. small_edge = set_pop(edges)
  84. log("Main edge: " + main_edge)
  85. log("Small edge: " + small_edge)
  86. log("Main source: " + readAssociationSource(model["metamodel"], main_edge))
  87. log("Main destination: " + readAssociationDestination(model["metamodel"], main_edge))
  88. log("Small source: " + readAssociationSource(model["metamodel"], small_edge))
  89. log("Small destination: " + readAssociationDestination(model["metamodel"], small_edge))
  90. if (readAssociationSource(model["metamodel"], main_edge) == small_edge):
  91. // Switch both
  92. log("Switch")
  93. String tmp
  94. tmp = main_edge
  95. main_edge = small_edge
  96. small_edge = tmp
  97. if (readAssociationSource(model["metamodel"], small_edge) == main_edge):
  98. log("Dictionary working...")
  99. String origin
  100. String value
  101. String key
  102. String middle_edge
  103. origin = readAssociationSource(model["metamodel"], main_edge)
  104. value = readAssociationDestination(model["metamodel"], main_edge)
  105. key = readAssociationDestination(model["metamodel"], small_edge)
  106. if (bool_and(bool_and(origin != value, origin != key), value != key)):
  107. // All three nodes are different, meaning that we are complete and have identified a simple mapping!
  108. elems = dict_keys(model["model"])
  109. while (set_len(elems) > 0):
  110. elem = set_pop(elems)
  111. if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)):
  112. // An edge with no outgoing links, meaning that it is the small_edge
  113. retype(model, elem, small_edge)
  114. // Source is main_edge and target is key
  115. middle_edge = readAssociationSource(model, elem)
  116. retype(model, middle_edge, main_edge)
  117. log("Type " + middle_edge + " : " + main_edge)
  118. retype(model, readAssociationDestination(model, elem), key)
  119. log("Type " + readAssociationDestination(model, elem) + " : " + key)
  120. // The main_edge goes from root to the value
  121. retype(model, readAssociationSource(model, middle_edge), origin)
  122. log("Type " + readAssociationSource(model, middle_edge) + " : " + origin)
  123. retype(model, readAssociationDestination(model, middle_edge), value)
  124. log("Type " + readAssociationDestination(model, middle_edge) + " : " + value)
  125. return True!
  126. log("Could not automatically deduce mapping in a trivial way!")
  127. log("Model: " + set_to_string(dict_keys(model["model"])))
  128. log("TM: " + set_to_string(dict_keys(tm)))
  129. return False!
  130. return True!