scd.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. from uuid import UUID
  2. from state.base import State
  3. from services.bottom.V0 import Bottom
  4. from services.primitives.boolean_type import Boolean
  5. from services.primitives.integer_type import Integer
  6. from services.primitives.string_type import String
  7. import re
  8. class SCD:
  9. def __init__(self, model: UUID, state: State):
  10. type_model_id = state.read_dict(state.read_root(), "SCD")
  11. self.scd_model = UUID(state.read_value(type_model_id))
  12. self.model = model
  13. self.bottom = Bottom(state)
  14. def create_class(self, name: str, abstract: bool = None, min_c: int = None, max_c: int = None):
  15. def set_cardinality(bound: str, value: int):
  16. _c_model = self.bottom.create_node()
  17. Integer(_c_model, self.bottom.state).create(value)
  18. _c_node = self.bottom.create_node(str(_c_model))
  19. self.bottom.create_edge(self.model, _c_node, f"{name}.{bound}_cardinality")
  20. _c_link = self.bottom.create_edge(class_node, _c_node)
  21. self.bottom.create_edge(self.model, _c_link, f"{name}.{bound}_cardinality_link")
  22. _scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Integer")
  23. _scd_link, = self.bottom.read_outgoing_elements(self.scd_model, f"Class_{bound}_cardinality")
  24. self.bottom.create_edge(_c_node, _scd_node, "Morphism")
  25. self.bottom.create_edge(_c_link, _scd_link, "Morphism")
  26. # create class + attributes + morphism links
  27. class_node = self.bottom.create_node() # create class node
  28. self.bottom.create_edge(self.model, class_node, name) # attach to model
  29. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Class") # retrieve type
  30. self.bottom.create_edge(class_node, scd_node, "Morphism") # create morphism link
  31. if abstract is not None:
  32. abstract_model = self.bottom.create_node()
  33. Boolean(abstract_model, self.bottom.state).create(abstract)
  34. abstract_node = self.bottom.create_node(str(abstract_model))
  35. self.bottom.create_edge(self.model, abstract_node, f"{name}.abstract")
  36. abstract_link = self.bottom.create_edge(class_node, abstract_node)
  37. self.bottom.create_edge(self.model, abstract_link, f"{name}.abstract_link")
  38. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Boolean")
  39. scd_link, = self.bottom.read_outgoing_elements(self.scd_model, "Class_abstract")
  40. self.bottom.create_edge(abstract_node, scd_node, "Morphism")
  41. self.bottom.create_edge(abstract_link, scd_link, "Morphism")
  42. if min_c is not None:
  43. set_cardinality("lower", min_c)
  44. if max_c is not None:
  45. set_cardinality("upper", min_c)
  46. def create_association(self, name: str, source: str, target: str,
  47. src_min_c: int = None, src_max_c: int = None,
  48. tgt_min_c: int = None, tgt_max_c: int = None):
  49. def set_cardinality(bound: str, value: int):
  50. _c_model = self.bottom.create_node()
  51. Integer(_c_model, self.bottom.state).create(value)
  52. _c_node = self.bottom.create_node(str(_c_model))
  53. self.bottom.create_edge(self.model, _c_node, f"{name}.{bound}_cardinality")
  54. _c_link = self.bottom.create_edge(assoc_edge, _c_node)
  55. self.bottom.create_edge(self.model, _c_link, f"{name}.{bound}_cardinality_link")
  56. _scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Integer")
  57. _scd_link, = self.bottom.read_outgoing_elements(self.scd_model, f"Class_{bound}_cardinality")
  58. self.bottom.create_edge(_c_node, _scd_node, "Morphism")
  59. self.bottom.create_edge(_c_link, _scd_link, "Morphism")
  60. # create class + attributes + morphism links
  61. assoc_edge = self.bottom.create_edge(
  62. *self.bottom.read_outgoing_elements(self.model, source),
  63. *self.bottom.read_outgoing_elements(self.model, target),
  64. ) # create assoc edge
  65. self.bottom.create_edge(self.model, assoc_edge, name) # attach to model
  66. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Association") # retrieve type
  67. self.bottom.create_edge(assoc_edge, scd_node, "Morphism") # create morphism link
  68. if src_min_c is not None:
  69. set_cardinality("source_lower", src_min_c)
  70. if src_max_c is not None:
  71. set_cardinality("source_upper", src_max_c)
  72. if tgt_min_c is not None:
  73. set_cardinality("target_lower", tgt_min_c)
  74. if tgt_max_c is not None:
  75. set_cardinality("target_upper", tgt_max_c)
  76. def create_global_constraint(self, name: str):
  77. # create element + morphism links
  78. element_node = self.bottom.create_node() # create element node
  79. self.bottom.create_edge(self.model, element_node, name) # attach to model
  80. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "GlobalConstraint") # retrieve type
  81. self.bottom.create_edge(element_node, scd_node, "Morphism") # create morphism link
  82. def create_attribute(self, name: str):
  83. # create element + morphism links
  84. element_node = self.bottom.create_node() # create element node
  85. self.bottom.create_edge(self.model, element_node, name) # attach to model
  86. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Attribute") # retrieve type
  87. self.bottom.create_edge(element_node, scd_node, "Morphism") # create morphism link
  88. def create_attribute_link(self, source: str, target: str, name: str, optional: bool):
  89. # create attribute link + morphism links
  90. assoc_edge = self.bottom.create_edge(
  91. *self.bottom.read_outgoing_elements(self.model, source),
  92. *self.bottom.read_outgoing_elements(self.model, target),
  93. ) # create inheritance edge
  94. self.bottom.create_edge(self.model, assoc_edge, f"{source}_{name}") # attach to model
  95. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "AttributeLink") # retrieve type
  96. self.bottom.create_edge(assoc_edge, scd_node, "Morphism") # create morphism link
  97. # name attribute
  98. name_model = self.bottom.create_node()
  99. String(name_model, self.bottom.state).create(name)
  100. name_node = self.bottom.create_node(str(name_model))
  101. self.bottom.create_edge(self.model, name_node, f"{source}_{name}.name")
  102. name_link = self.bottom.create_edge(assoc_edge, name_node)
  103. self.bottom.create_edge(self.model, name_link, f"{source}_{name}.name_link")
  104. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "String")
  105. scd_link, = self.bottom.read_outgoing_elements(self.scd_model, "AttributeLink_name")
  106. self.bottom.create_edge(name_node, scd_node, "Morphism")
  107. self.bottom.create_edge(name_link, scd_link, "Morphism")
  108. # optional attribute
  109. optional_model = self.bottom.create_node()
  110. Boolean(optional_model, self.bottom.state).create(optional)
  111. optional_node = self.bottom.create_node(str(optional_model))
  112. self.bottom.create_edge(self.model, optional_node, f"{source}_{name}.optional")
  113. optional_link = self.bottom.create_edge(assoc_edge, optional_node)
  114. self.bottom.create_edge(self.model, optional_link, f"{source}_{name}.optional_link")
  115. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Boolean")
  116. scd_link, = self.bottom.read_outgoing_elements(self.scd_model, "AttributeLink_optional")
  117. self.bottom.create_edge(optional_node, scd_node, "Morphism")
  118. self.bottom.create_edge(optional_link, scd_link, "Morphism")
  119. def create_model_ref(self, name: str, model: UUID):
  120. # create element + morphism links
  121. element_node = self.bottom.create_node(str(model)) # create element node
  122. self.bottom.create_edge(self.model, element_node, name) # attach to model
  123. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "ModelRef") # retrieve type
  124. self.bottom.create_edge(element_node, scd_node, "Morphism") # create morphism link
  125. def create_inheritance(self, child: str, parent: str):
  126. # create inheritance + morphism links
  127. assoc_edge = self.bottom.create_edge(
  128. *self.bottom.read_outgoing_elements(self.model, child),
  129. *self.bottom.read_outgoing_elements(self.model, parent),
  130. ) # create inheritance edge
  131. self.bottom.create_edge(self.model, assoc_edge, f"{child}_inh_{parent}") # attach to model
  132. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "Inheritance") # retrieve type
  133. self.bottom.create_edge(assoc_edge, scd_node, "Morphism") # create morphism link
  134. def add_constraint(self, element: str, code: str):
  135. element_node, = self.bottom.read_outgoing_elements(self.model, element) # retrieve element
  136. # code attribute
  137. code_node = self.bottom.create_node(code)
  138. self.bottom.create_edge(self.model, code_node, f"{element}.constraint")
  139. code_link = self.bottom.create_edge(element_node, code_node)
  140. self.bottom.create_edge(self.model, code_link, f"{element}.constraint_link")
  141. scd_node, = self.bottom.read_outgoing_elements(self.scd_model, "ActionCode")
  142. scd_link, = self.bottom.read_outgoing_elements(self.scd_model, "Element_constraint")
  143. self.bottom.create_edge(code_node, scd_node, "Morphism")
  144. self.bottom.create_edge(code_link, scd_link, "Morphism")
  145. def list_elements(self):
  146. scd_names = {}
  147. for key in self.bottom.read_keys(self.scd_model):
  148. element, = self.bottom.read_outgoing_elements(self.scd_model, key)
  149. scd_names[element] = key
  150. unsorted = []
  151. for key in self.bottom.read_keys(self.model):
  152. element, = self.bottom.read_outgoing_elements(self.model, key)
  153. element_types = self.bottom.read_outgoing_elements(element, "Morphism")
  154. type_model_elements = self.bottom.read_outgoing_elements(self.scd_model)
  155. element_type_node, = [e for e in element_types if e in type_model_elements]
  156. unsorted.append(f"{key} : {scd_names[element_type_node]}")
  157. return sorted(unsorted)
  158. def delete_element(self, name: str):
  159. keys = self.bottom.read_keys(self.model)
  160. r = re.compile(r"{}\..*".format(name))
  161. to_delete = list(filter(r.match, keys))
  162. for key in to_delete:
  163. # TODO: find way to solve memory leak, primitive models are not deleted this way
  164. node, = self.bottom.read_outgoing_elements(self.model, label=key)
  165. self.bottom.delete_element(node)
  166. def to_bottom(self):
  167. pass
  168. def from_bottom(self):
  169. pass
  170. if __name__ == '__main__':
  171. from state.devstate import DevState as State
  172. s = State()
  173. from bootstrap.scd import bootstrap_scd
  174. scd = bootstrap_scd(s)
  175. # Retrieve refs to primitive type models
  176. # # integer
  177. int_type_id = s.read_dict(s.read_root(), "Integer")
  178. int_type = UUID(s.read_value(int_type_id))
  179. print(f"Integer Model UUID: {int_type}") # 6
  180. # # string
  181. str_type_id = s.read_dict(s.read_root(), "String")
  182. str_type = UUID(s.read_value(str_type_id))
  183. print(f"String Model UUID: {str_type}") # 16
  184. # Create LTM_PN
  185. model_uuid = s.create_node()
  186. print(f"LTM_PN Model UUID: {model_uuid}") # 845
  187. service = SCD(model_uuid, s)
  188. # Create classes
  189. service.create_class("P")
  190. service.create_class("T")
  191. # Create associations
  192. service.create_association("P2T", "P", "T")
  193. service.create_association("T2P", "T", "P")
  194. # Create model refs
  195. service.create_model_ref("Integer", int_type)
  196. service.create_model_ref("String", int_type)
  197. # Create class attributes
  198. service.create_attribute_link("P", "Integer", "t", False)
  199. service.create_attribute_link("P", "String", "n", False)
  200. service.create_attribute_link("T", "String", "n", False)
  201. # Create association attributes
  202. service.create_attribute_link("P2T", "Integer", "w", False)
  203. service.create_attribute_link("T2P", "Integer", "w", False)