ramify.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. from state.base import State
  2. from uuid import UUID
  3. from services.bottom.V0 import Bottom
  4. from services.scd import SCD
  5. from framework.conformance import Conformance
  6. def ramify(state: State, model: UUID) -> UUID:
  7. def print_tree(root, max_depth, depth=0):
  8. print(" "*depth, "root=", root, "value=", state.read_value(root))
  9. src,tgt = state.read_edge(root)
  10. if src != None:
  11. print(" "*depth, "src...")
  12. print_tree(src, max_depth, depth+1)
  13. if tgt != None:
  14. print(" "*depth, "tgt...")
  15. print_tree(tgt, max_depth, depth+1)
  16. for edge in state.read_outgoing(root):
  17. for edge_label in state.read_outgoing(edge):
  18. [_,tgt] = state.read_edge(edge_label)
  19. label = state.read_value(tgt)
  20. print(" "*depth, " key:", label)
  21. [_, tgt] = state.read_edge(edge)
  22. value = state.read_value(tgt)
  23. if value != None:
  24. print(" "*depth, " ->", tgt, " (value:", value, ")")
  25. else:
  26. print(" "*depth, " ->", tgt)
  27. if depth < max_depth:
  28. if isinstance(value, str) and len(value) == 36:
  29. i = None
  30. try:
  31. i = UUID(value)
  32. except ValueError as e:
  33. # print("invalid UUID:", value)
  34. pass
  35. if i != None:
  36. print_tree(i, max_depth, depth+1)
  37. print_tree(tgt, max_depth, depth+1)
  38. bottom = Bottom(state)
  39. scd_metamodel_id = state.read_dict(state.read_root(), "SCD")
  40. scd_metamodel = UUID(state.read_value(scd_metamodel_id))
  41. class_upper_card_node, = bottom.read_outgoing_elements(scd_metamodel, "Class_upper_cardinality")
  42. src_upper_card_node, = bottom.read_outgoing_elements(scd_metamodel, "Association_source_upper_cardinality")
  43. tgt_upper_card_node, = bottom.read_outgoing_elements(scd_metamodel, "Association_target_upper_cardinality")
  44. attr_link_node, = bottom.read_outgoing_elements(scd_metamodel, "AttributeLink")
  45. attr_link_name_node, = bottom.read_outgoing_elements(scd_metamodel, "AttributeLink_name")
  46. glob_constr_node, = bottom.read_outgoing_elements(scd_metamodel, "GlobalConstraint")
  47. inheritance_node, = bottom.read_outgoing_elements(scd_metamodel, "Inheritance")
  48. string_type_id = state.read_dict(state.read_root(), "String")
  49. string_type = UUID(state.read_value(string_type_id))
  50. scd = SCD(model, state)
  51. # print_tree(model, 2)
  52. # for el in SCD(scd_metamodel, state).list_elements():
  53. # print(el)
  54. def find_outgoing_typed_by(src: UUID, type_node: UUID):
  55. edges = []
  56. for outgoing_edge in bottom.read_outgoing_edges(src):
  57. for typedBy in bottom.read_outgoing_elements(outgoing_edge, "Morphism"):
  58. if typedBy == type_node:
  59. edges.append(outgoing_edge)
  60. break
  61. return edges
  62. def navigate_modelref(node: UUID):
  63. uuid = bottom.read_value(node)
  64. return UUID(uuid)
  65. def find_upper_cardinality(class_node: UUID, type_node: UUID):
  66. upper_card_edges = find_outgoing_typed_by(class_node, type_node)
  67. if len(upper_card_edges) == 1:
  68. ref = bottom.read_edge_target(upper_card_edges[0])
  69. integer, = bottom.read_outgoing_elements(
  70. navigate_modelref(ref),
  71. "integer")
  72. # finally, the value we're looking for:
  73. return bottom.read_value(integer)
  74. def get_attributes(class_node: UUID):
  75. attr_edges = find_outgoing_typed_by(class_node, attr_link_node)
  76. result = []
  77. for attr_edge in attr_edges:
  78. name_edge, = find_outgoing_typed_by(attr_edge, attr_link_name_node)
  79. if name_edge == None:
  80. raise Exception("Expected attribute to have a name...")
  81. ref_name = bottom.read_edge_target(name_edge)
  82. string, = bottom.read_outgoing_elements(
  83. navigate_modelref(ref_name),
  84. "string")
  85. attr_name = bottom.read_value(string)
  86. ref_type = bottom.read_edge_target(attr_edge)
  87. typ = navigate_modelref(ref_type)
  88. result.append((attr_name, typ))
  89. return result
  90. ramified = state.create_node()
  91. ramified_scd = SCD(ramified, state)
  92. string_modelref = ramified_scd.create_model_ref("String", string_type)
  93. print()
  94. classes = scd.get_classes()
  95. for class_name, class_node in classes.items():
  96. # For every class in our original model, create a class:
  97. # - abstract: False
  98. # - min-card: 0
  99. # - max-card: same as original
  100. upper_card = find_upper_cardinality(class_node, class_upper_card_node)
  101. print('creating class', class_name, "with upper card", upper_card)
  102. ramified_scd.create_class(class_name, abstract=None, max_c=upper_card)
  103. for (attr_name, attr_type) in get_attributes(class_node):
  104. print(' creating attribute', attr_name, "with type String")
  105. # Every attribute becomes 'string' type
  106. # The string will be a Python expression
  107. ramified_scd._create_attribute_link(class_name, string_modelref, attr_name, optional=False)
  108. associations = scd.get_associations()
  109. for assoc_name, assoc_node in associations.items():
  110. # For every association in our original model, create an association:
  111. # - src-min-card: 0
  112. # - src-max-card: same as original
  113. # - tgt-min-card: 0
  114. # - tgt-max-card: same as original
  115. src_upper_card = find_upper_cardinality(assoc_node, src_upper_card_node)
  116. tgt_upper_card = find_upper_cardinality(assoc_node, tgt_upper_card_node)
  117. print('creating assoc', assoc_name, "with src upper card", src_upper_card, "and tgt upper card", tgt_upper_card)
  118. ramified_scd._create_association(assoc_name,
  119. bottom.read_edge_source(assoc_node),
  120. bottom.read_edge_target(assoc_node),
  121. src_max_c=src_upper_card,
  122. tgt_max_c=tgt_upper_card)
  123. for inh_name, inh_node in scd.get_inheritances().items():
  124. # Re-create inheritance links like in our original model:
  125. print('creating inheritance', inh_name)
  126. ramified_scd._create_inheritance(
  127. bottom.read_edge_source(inh_node),
  128. bottom.read_edge_target(inh_node))
  129. # The RAMified meta-model should also conform to 'SCD':
  130. conf = Conformance(state, model, scd_metamodel)
  131. print("conforms?", conf.check_nominal(log=True))