pyegeria 5.4.3.3__py3-none-any.whl → 5.4.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. commands/cat/debug_log.2025-09-02_07-44-39_567276.log.zip +0 -0
  2. commands/cat/debug_log.2025-09-03_07-45-21_986388.log.zip +0 -0
  3. commands/cat/debug_log.2025-09-04_08-21-58_788009.log.zip +0 -0
  4. commands/cat/debug_log.2025-09-05_09-37-53_062579.log.zip +0 -0
  5. commands/cat/list_format_set.py +5 -3
  6. commands/tech/list_information_supply_chains.py +1 -1
  7. commands/tech/list_solution_blueprints.py +1 -1
  8. commands/tech/list_solution_components.py +1 -1
  9. commands/tech/list_solution_roles.py +1 -1
  10. md_processing/__init__.py +9 -5
  11. md_processing/data/commands.json +7182 -1401
  12. md_processing/data/generated_format_sets.json +4137 -0
  13. md_processing/data/generated_format_sets.py +51 -0
  14. md_processing/dr_egeria.py +20 -11
  15. md_processing/md_commands/data_designer_commands.py +90 -425
  16. md_processing/md_commands/ext_ref_commands.py +543 -0
  17. md_processing/md_commands/old_solution_architect_commands.py +1139 -0
  18. md_processing/md_commands/solution_architect_commands.py +26 -59
  19. md_processing/md_processing_utils/common_md_utils.py +50 -1
  20. md_processing/md_processing_utils/debug_log +1 -3
  21. md_processing/md_processing_utils/dr-egeria-help-2025-09-09T11:10:03.md +3305 -0
  22. md_processing/md_processing_utils/extraction_utils.py +14 -7
  23. md_processing/md_processing_utils/gen_format_sets.py +422 -0
  24. md_processing/md_processing_utils/md_processing_constants.py +20 -2
  25. pyegeria/__init__.py +1 -1
  26. pyegeria/_client_new.py +9 -7
  27. pyegeria/_output_formats.py +278 -3
  28. pyegeria/collection_manager.py +20 -59
  29. pyegeria/config.py +10 -1
  30. pyegeria/data_designer.py +166 -117
  31. pyegeria/egeria_client.py +1 -1
  32. pyegeria/egeria_tech_client.py +4 -1
  33. pyegeria/external_references.py +1794 -0
  34. pyegeria/glossary_manager.py +71 -85
  35. pyegeria/governance_officer.py +26 -29
  36. pyegeria/output_formatter.py +127 -1
  37. pyegeria/project_manager.py +33 -36
  38. pyegeria/{solution_architect_omvs.py → solution_architect.py} +733 -873
  39. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/METADATA +1 -1
  40. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/RECORD +43 -219
  41. commands/.DS_Store +0 -0
  42. commands/cat/.DS_Store +0 -0
  43. commands/cat/.env +0 -8
  44. commands/cat/debug_log.2025-08-29_07-07-27_848189.log.zip +0 -0
  45. commands/cat/debug_log.2025-08-30_21-15-48_528443.log.zip +0 -0
  46. commands/cat/debug_log.log +0 -6102
  47. commands/cat/logs/pyegeria.log +0 -90
  48. commands/cli/debug_log.log +0 -0
  49. commands/doc/.DS_Store +0 -0
  50. commands/ops/logs/pyegeria.log +0 -0
  51. md_processing/.DS_Store +0 -0
  52. md_processing/.idea/.gitignore +0 -8
  53. md_processing/.idea/inspectionProfiles/Project_Default.xml +0 -59
  54. md_processing/.idea/md_processing.iml +0 -15
  55. md_processing/.idea/modules.xml +0 -8
  56. md_processing/.idea/sonarlint/issuestore/index.pb +0 -0
  57. md_processing/.idea/sonarlint/securityhotspotstore/index.pb +0 -0
  58. md_processing/.idea/vcs.xml +0 -6
  59. md_processing/.idea/workspace.xml +0 -107
  60. md_processing/dr_egeria_inbox/Derive-Dr-Gov-Defs.md +0 -8
  61. md_processing/dr_egeria_inbox/Dr.Egeria Templates.md +0 -873
  62. md_processing/dr_egeria_inbox/arch_test.md +0 -57
  63. md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
  64. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
  65. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
  66. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
  67. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
  68. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
  69. md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
  70. md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
  71. md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
  72. md_processing/dr_egeria_inbox/cat_test.md +0 -100
  73. md_processing/dr_egeria_inbox/collections.md +0 -39
  74. md_processing/dr_egeria_inbox/data_designer_debug.log +0 -6
  75. md_processing/dr_egeria_inbox/data_designer_out.md +0 -60
  76. md_processing/dr_egeria_inbox/data_designer_search_test.md +0 -11
  77. md_processing/dr_egeria_inbox/data_field.md +0 -54
  78. md_processing/dr_egeria_inbox/data_spec.md +0 -77
  79. md_processing/dr_egeria_inbox/data_spec_test.md +0 -2340
  80. md_processing/dr_egeria_inbox/data_test.md +0 -179
  81. md_processing/dr_egeria_inbox/data_test2.md +0 -429
  82. md_processing/dr_egeria_inbox/data_test3.md +0 -462
  83. md_processing/dr_egeria_inbox/dr_egeria_data_designer_1.md +0 -124
  84. md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
  85. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
  86. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -318
  87. md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
  88. md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
  89. md_processing/dr_egeria_inbox/generated_help_report.md +0 -9
  90. md_processing/dr_egeria_inbox/generated_help_terms.md +0 -842
  91. md_processing/dr_egeria_inbox/glossary_list.md +0 -5
  92. md_processing/dr_egeria_inbox/glossary_search_test.md +0 -40
  93. md_processing/dr_egeria_inbox/glossary_test1.md +0 -378
  94. md_processing/dr_egeria_inbox/gov_def.md +0 -718
  95. md_processing/dr_egeria_inbox/gov_def2.md +0 -447
  96. md_processing/dr_egeria_inbox/img.png +0 -0
  97. md_processing/dr_egeria_inbox/output_tests.md +0 -114
  98. md_processing/dr_egeria_inbox/product.md +0 -211
  99. md_processing/dr_egeria_inbox/rel.md +0 -8
  100. md_processing/dr_egeria_inbox/sb.md +0 -119
  101. md_processing/dr_egeria_inbox/solution-components.md +0 -136
  102. md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
  103. md_processing/dr_egeria_inbox/synonym_test.md +0 -42
  104. md_processing/dr_egeria_inbox/t2.md +0 -268
  105. md_processing/dr_egeria_outbox/.DS_Store +0 -0
  106. md_processing/dr_egeria_outbox/.obsidian/app.json +0 -1
  107. md_processing/dr_egeria_outbox/.obsidian/appearance.json +0 -1
  108. md_processing/dr_egeria_outbox/.obsidian/community-plugins.json +0 -7
  109. md_processing/dr_egeria_outbox/.obsidian/core-plugins.json +0 -33
  110. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/main.js +0 -5164
  111. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/manifest.json +0 -10
  112. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/styles.css +0 -624
  113. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/data.json +0 -10
  114. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/main.js +0 -4459
  115. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/manifest.json +0 -10
  116. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/data.json +0 -3
  117. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/main.js +0 -153
  118. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/manifest.json +0 -11
  119. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/styles.css +0 -1
  120. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/main.js +0 -500
  121. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +0 -12
  122. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/styles.css +0 -1
  123. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/data.json +0 -38
  124. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/main.js +0 -37
  125. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/manifest.json +0 -11
  126. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/styles.css +0 -220
  127. md_processing/dr_egeria_outbox/.obsidian/types.json +0 -28
  128. md_processing/dr_egeria_outbox/.obsidian/workspace.json +0 -270
  129. md_processing/dr_egeria_outbox/Button Test.md +0 -11
  130. md_processing/dr_egeria_outbox/Scripts/.DS_Store +0 -0
  131. md_processing/dr_egeria_outbox/Scripts/sendRest.js +0 -24
  132. md_processing/dr_egeria_outbox/Templates/sendToApi.md.md +0 -17
  133. md_processing/dr_egeria_outbox/Untitled.canvas +0 -1
  134. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 09:26-product.md +0 -210
  135. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:03-product.md +0 -209
  136. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:24-product.md +0 -263
  137. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:03-data_spec_test.md +0 -2374
  138. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:05-data_spec_test.md +0 -2374
  139. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:28-data_spec_test.md +0 -2321
  140. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:37-data_spec_test.md +0 -2304
  141. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:56-data_spec_test.md +0 -2324
  142. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 09:00-data_spec_test.md +0 -2324
  143. md_processing/dr_egeria_outbox/processed-2025-08-30 16:56-generated_help_terms.md +0 -795
  144. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 15:00-Derive-Dr-Gov-Defs.md +0 -719
  145. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:13-Derive-Dr-Gov-Defs.md +0 -41
  146. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:14-Derive-Dr-Gov-Defs.md +0 -33
  147. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:50-Derive-Dr-Gov-Defs.md +0 -192
  148. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:08-gov_def2.md +0 -486
  149. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:10-gov_def2.md +0 -486
  150. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:53-gov_def2.md +0 -486
  151. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:54-gov_def2.md +0 -486
  152. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:03-gov_def2.md +0 -486
  153. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:06-gov_def2.md +0 -486
  154. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:10-gov_def2.md +0 -486
  155. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:07-gov_def.md +0 -492
  156. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:25-gov_def.md +0 -520
  157. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:43-gov_def.md +0 -636
  158. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:46-gov_def.md +0 -636
  159. md_processing/family_docs/Data Designer/Create_Data_Class.md +0 -164
  160. md_processing/family_docs/Data Designer/Create_Data_Dictionary.md +0 -30
  161. md_processing/family_docs/Data Designer/Create_Data_Field.md +0 -162
  162. md_processing/family_docs/Data Designer/Create_Data_Specification.md +0 -36
  163. md_processing/family_docs/Data Designer/Create_Data_Structure.md +0 -38
  164. md_processing/family_docs/Data Designer/View_Data_Classes.md +0 -78
  165. md_processing/family_docs/Data Designer/View_Data_Dictionaries.md +0 -78
  166. md_processing/family_docs/Data Designer/View_Data_Fields.md +0 -78
  167. md_processing/family_docs/Data Designer/View_Data_Specifications.md +0 -78
  168. md_processing/family_docs/Data Designer/View_Data_Structures.md +0 -78
  169. md_processing/family_docs/Data Designer.md +0 -842
  170. md_processing/family_docs/Digital Product Manager/Add_Member->Collection.md +0 -42
  171. md_processing/family_docs/Digital Product Manager/Attach_Collection->Resource.md +0 -36
  172. md_processing/family_docs/Digital Product Manager/Create_Agreement.md +0 -96
  173. md_processing/family_docs/Digital Product Manager/Create_Data_Sharing_Agreement.md +0 -72
  174. md_processing/family_docs/Digital Product Manager/Create_DigitalSubscription.md +0 -102
  175. md_processing/family_docs/Digital Product Manager/Create_Digital_Product.md +0 -134
  176. md_processing/family_docs/Digital Product Manager/Link_Agreement_Items.md +0 -60
  177. md_processing/family_docs/Digital Product Manager/Link_Contracts.md +0 -26
  178. md_processing/family_docs/Digital Product Manager/Link_Digital_Product_-_Digital_Product.md +0 -30
  179. md_processing/family_docs/Digital Product Manager/Link_Subscribers.md +0 -48
  180. md_processing/family_docs/Digital Product Manager.md +0 -668
  181. md_processing/family_docs/Glossary/Attach_Category_Parent.md +0 -18
  182. md_processing/family_docs/Glossary/Attach_Term-Term_Relationship.md +0 -26
  183. md_processing/family_docs/Glossary/Create_Category.md +0 -38
  184. md_processing/family_docs/Glossary/Create_Glossary.md +0 -42
  185. md_processing/family_docs/Glossary/Create_Term.md +0 -70
  186. md_processing/family_docs/Glossary.md +0 -206
  187. md_processing/family_docs/Governance Officer/Create_Business_Imperative.md +0 -106
  188. md_processing/family_docs/Governance Officer/Create_Certification_Type.md +0 -112
  189. md_processing/family_docs/Governance Officer/Create_Governance_Approach.md +0 -114
  190. md_processing/family_docs/Governance Officer/Create_Governance_Obligation.md +0 -114
  191. md_processing/family_docs/Governance Officer/Create_Governance_Principle.md +0 -114
  192. md_processing/family_docs/Governance Officer/Create_Governance_Procedure.md +0 -128
  193. md_processing/family_docs/Governance Officer/Create_Governance_Process.md +0 -122
  194. md_processing/family_docs/Governance Officer/Create_Governance_Processing_Purpose.md +0 -106
  195. md_processing/family_docs/Governance Officer/Create_Governance_Responsibility.md +0 -122
  196. md_processing/family_docs/Governance Officer/Create_Governance_Rule.md +0 -122
  197. md_processing/family_docs/Governance Officer/Create_Governance_Strategy.md +0 -106
  198. md_processing/family_docs/Governance Officer/Create_License_Type.md +0 -112
  199. md_processing/family_docs/Governance Officer/Create_Naming_Standard_Rule.md +0 -122
  200. md_processing/family_docs/Governance Officer/Create_Regulation_Article.md +0 -106
  201. md_processing/family_docs/Governance Officer/Create_Regulation_Definition.md +0 -118
  202. md_processing/family_docs/Governance Officer/Create_Security_Access_Control.md +0 -114
  203. md_processing/family_docs/Governance Officer/Create_Security_Group.md +0 -120
  204. md_processing/family_docs/Governance Officer/Create_Service_Level_Objectives.md +0 -122
  205. md_processing/family_docs/Governance Officer/Create_Threat_Definition.md +0 -106
  206. md_processing/family_docs/Governance Officer/Link_Governance_Controls.md +0 -32
  207. md_processing/family_docs/Governance Officer/Link_Governance_Drivers.md +0 -32
  208. md_processing/family_docs/Governance Officer/Link_Governance_Policies.md +0 -32
  209. md_processing/family_docs/Governance Officer/View_Governance_Definitions.md +0 -82
  210. md_processing/family_docs/Governance Officer.md +0 -2412
  211. md_processing/family_docs/Solution Architect/Create_Information_Supply_Chain.md +0 -70
  212. md_processing/family_docs/Solution Architect/Create_Solution_Blueprint.md +0 -44
  213. md_processing/family_docs/Solution Architect/Create_Solution_Component.md +0 -96
  214. md_processing/family_docs/Solution Architect/Create_Solution_Role.md +0 -66
  215. md_processing/family_docs/Solution Architect/Link_Information_Supply_Chain_Peers.md +0 -32
  216. md_processing/family_docs/Solution Architect/Link_Solution_Component_Peers.md +0 -32
  217. md_processing/family_docs/Solution Architect/View_Information_Supply_Chains.md +0 -32
  218. md_processing/family_docs/Solution Architect/View_Solution_Blueprints.md +0 -32
  219. md_processing/family_docs/Solution Architect/View_Solution_Components.md +0 -32
  220. md_processing/family_docs/Solution Architect/View_Solution_Roles.md +0 -32
  221. md_processing/family_docs/Solution Architect.md +0 -490
  222. md_processing/md_commands/old_project_commands.py +0 -164
  223. md_processing/md_processing_utils/debug_log.log +0 -5580
  224. md_processing/md_processing_utils/generated_help_terms.md +0 -842
  225. md_processing/md_processing_utils/logs/pyegeria.log +0 -56
  226. pyegeria/.DS_Store +0 -0
  227. pyegeria/___external_references.py +0 -3267
  228. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/LICENSE +0 -0
  229. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/WHEEL +0 -0
  230. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1139 @@
1
+ """
2
+ This file contains blueprint/solution-related object_action functions for processing Egeria Markdown
3
+ """
4
+ import json
5
+ import sys
6
+ from typing import Optional
7
+
8
+ from loguru import logger
9
+ from pygments.lexers import blueprint
10
+ from rich import print
11
+ from rich.console import Console
12
+ from rich.markdown import Markdown
13
+
14
+ from md_processing.md_processing_utils.common_md_proc_utils import (parse_upsert_command, parse_view_command)
15
+ from md_processing.md_processing_utils.common_md_utils import update_element_dictionary
16
+ from md_processing.md_processing_utils.extraction_utils import (extract_command_plus, update_a_command)
17
+ from md_processing.md_processing_utils.md_processing_constants import (load_commands)
18
+ from pyegeria import body_slimmer, EgeriaTech
19
+
20
+ load_commands('commands.json')
21
+
22
+ console = Console(width=int(200))
23
+
24
+
25
+ @logger.catch
26
+ def sync_chain_related_elements(egeria_client: EgeriaTech, guid:str, in_supply_chain_guids:list, display_name:str,
27
+ replace_all_props:bool):
28
+ if replace_all_props:
29
+ rel_el_list = egeria_client._get_supply_chain_rel_elements(guid)
30
+ if rel_el_list is None:
31
+ logger.warning("Unexpected -> the list was None - assigning empty list")
32
+ rel_el_list = {}
33
+
34
+ as_is_parent_guids = set(rel_el_list.get("parent_guids", []))
35
+
36
+ to_be_parent_guids = set(in_supply_chain_guids) if in_supply_chain_guids is not None else set()
37
+
38
+ logger.trace(
39
+ f"as_is_parent supply chains: {list(as_is_parent_guids)} to_be_parent supply chains: {list(to_be_parent_guids)}")
40
+
41
+
42
+ parent_guids_to_remove = as_is_parent_guids - to_be_parent_guids
43
+ logger.trace(f"parent_guids_to_remove: {list(parent_guids_to_remove)}")
44
+ if len(parent_guids_to_remove) > 0:
45
+ for parent_guid in parent_guids_to_remove:
46
+ egeria_client.decompose_info_supply_chains(parent_guid, guid, None)
47
+ msg = f"Removed `{display_name}` from supply chain parent `{parent_guid}`"
48
+ logger.trace(msg)
49
+
50
+ parent_guids_to_add = to_be_parent_guids - as_is_parent_guids
51
+ logger.trace(f"parent supply chains_to_add: {list(parent_guids_to_add)}")
52
+ if len(parent_guids_to_add) > 0:
53
+ for parent_guid in parent_guids_to_add:
54
+ egeria_client.compose_info_supply_chains(parent_guid, guid, None)
55
+ msg = f"Added `{display_name}` to supply chain parent `{parent_guid}`"
56
+ logger.trace(msg)
57
+
58
+ else: # merge - add supply chain to parents
59
+ if in_supply_chain_guids:
60
+ for parent_guid in in_supply_chain_guids:
61
+ egeria_client.compose_info_supply_chains(parent_guid, guid, None)
62
+ msg = f"Added `{display_name}` to supply chain `{parent_guid}`"
63
+ logger.trace(msg)
64
+
65
+
66
+
67
+ @logger.catch
68
+ def sync_component_related_elements(egeria_client: EgeriaTech, object_type: str,
69
+ supply_chain_guids: list, parent_component_guids: list,
70
+ actor_guids: list, in_blueprint_guids: list, guid: str, qualified_name: str,
71
+ display_name: str, merge_update: bool = True) -> None:
72
+ """Sync a components related elements.
73
+
74
+ """
75
+ if not merge_update:
76
+ rel_el_list = egeria_client.get_component_related_elements(guid)
77
+ # should I throw an exception if empty?
78
+
79
+ as_is_actors = set(rel_el_list.get("actor_guids", []))
80
+ as_is_blueprints = set(rel_el_list.get("blueprint_guids", []))
81
+ as_is_parent_components = set(rel_el_list.get("parent_component_guids", []))
82
+ as_is_supply_chains = set(rel_el_list.get("supply_chain_guids", []))
83
+
84
+
85
+ to_be_actors = set(actor_guids) if actor_guids is not None else set()
86
+ to_be_blueprints = set(in_blueprint_guids) if in_blueprint_guids is not None else set()
87
+ to_be_parent_components = set(parent_component_guids) if parent_component_guids is not None else set()
88
+ to_be_supply_chains = set(supply_chain_guids) if supply_chain_guids is not None else set()
89
+
90
+
91
+ logger.trace(
92
+ f"as_is_sub_components: {list(as_is_parent_components)} to_be_sub_components: {list(to_be_parent_components)}")
93
+ logger.trace(f"as_is_actors: {list(as_is_actors)} to_be_actors: {list(to_be_actors)}")
94
+ logger.trace(f"as_is_blueprints: {list(as_is_blueprints)} to_be_blueprints: {list(to_be_blueprints)}")
95
+
96
+ parent_components_to_remove = as_is_parent_components - to_be_parent_components
97
+ logger.trace(f"sub_components_to_remove: {list(parent_components_to_remove)}")
98
+ if len(parent_components_to_remove) > 0:
99
+ for ds in parent_components_to_remove:
100
+ egeria_client.detach_sub_component(ds, guid, None)
101
+ msg = f"Removed `{display_name}` from component `{ds}`"
102
+ logger.trace(msg)
103
+
104
+ parent_components_to_add = to_be_parent_components - as_is_parent_components
105
+ logger.trace(f"parent_components_to_add: {list(parent_components_to_add)}")
106
+ if len(parent_components_to_add) > 0:
107
+ for ds in parent_components_to_add:
108
+ egeria_client.link_subcomponent(ds, guid, None)
109
+ msg = f"Added `{display_name}` to component `{ds}`"
110
+ logger.trace(msg)
111
+
112
+ blueprints_to_remove = as_is_blueprints - to_be_blueprints
113
+ logger.trace(f"blueprints_to_remove: {list(blueprints_to_remove)}")
114
+ if len(blueprints_to_remove) > 0:
115
+ for bp in blueprints_to_remove:
116
+ egeria_client.detach_solution_component_from_blueprint(bp, guid, None)
117
+ msg = f"Removed `{display_name}` from blueprintt `{bp}`"
118
+ logger.trace(msg)
119
+
120
+ blueprints_to_add = to_be_blueprints - as_is_blueprints
121
+ logger.trace(f"blueprints_to_add: {list(blueprints_to_add)}")
122
+ if len(blueprints_to_add) > 0:
123
+ for bp in blueprints_to_add:
124
+ egeria_client.link_solution_component_to_blueprint(bp, guid, None)
125
+ msg = f"Added `{display_name}` to component `{bp}`"
126
+ logger.trace(msg)
127
+
128
+
129
+
130
+ actors_to_remove = to_be_actors - as_is_actors
131
+ logger.trace(f"actors_to_remove: {list(actors_to_remove)}")
132
+ if len(actors_to_remove) > 0:
133
+ for actor in actors_to_remove:
134
+ egeria_client.detach_component_actore(actor, guid, None)
135
+ msg = f"Removed actor `{actor}` from component `{display_name}`"
136
+ logger.trace(msg)
137
+
138
+ actors_to_add = to_be_actors - as_is_actors
139
+ logger.trace(f"actors_to_add: {list(actors_to_add)}")
140
+ if len(actors_to_add) > 0:
141
+ for actor in actors_to_add:
142
+ egeria_client.link_component_to_actor(actor, guid, None)
143
+ msg = f"Added `{display_name}` to role `{actor}`"
144
+ logger.trace(msg)
145
+
146
+ supply_chains_to_remove = as_is_supply_chains - to_be_supply_chains
147
+ logger.trace(f"supply_chains_to_remove: {list(supply_chains_to_remove)}")
148
+ if len(supply_chains_to_remove) > 0:
149
+ for isc in supply_chains_to_remove:
150
+ egeria_client.detach_design_from_implementation(isc, guid)
151
+ msg = f"Removed `{isc}` from `{display_name}`"
152
+ logger.trace(msg)
153
+ supply_chains_to_add = to_be_supply_chains - as_is_supply_chains
154
+ logger.trace(f"supply_chains_to_add: {list(supply_chains_to_add)}")
155
+ if len(supply_chains_to_add) > 0:
156
+ body = {
157
+ "class": "RelationshipRequestBody",
158
+ "properties": {
159
+ "class": "ImplementedByProperties",
160
+ "description": "a blank description to satisfy the Egeria gods"
161
+ }
162
+ }
163
+ for isc in supply_chains_to_add:
164
+ egeria_client.link_design_to_implementation(isc, guid, body)
165
+ msg = f"Added `{isc}` to`{display_name}`"
166
+ logger.trace(msg)
167
+ logger.info(f"Replaced the related elements in `{display_name}`")
168
+
169
+ else: # merge - add field to related elements
170
+ if parent_component_guids:
171
+ for comp in parent_component_guids:
172
+ egeria_client.link_subcomponent(guid, comp, None)
173
+ msg = f"Added `{parent_component_guids}` to `{display_name}`"
174
+ logger.trace(msg)
175
+
176
+ if actor_guids:
177
+ for actor in actor_guids:
178
+ egeria_client.link_component_to_actor(actor, guid, None)
179
+ msg = f"Added `{actor_guids}` to `{display_name}`"
180
+ logger.trace(msg)
181
+
182
+ if in_blueprint_guids:
183
+ for bp in in_blueprint_guids:
184
+ egeria_client.link_solution_component_to_blueprint(bp, guid, None)
185
+ msg = f"Added `{in_blueprint_guids}` to `{display_name}`"
186
+ logger.trace(msg)
187
+
188
+ if supply_chain_guids:
189
+ body = {
190
+ "class": "RelationshipRequestBody",
191
+ "properties": {
192
+ "class": "ImplementedByProperties",
193
+ "description": "a blank description to satisfy the Egeria gods"
194
+ }
195
+ }
196
+ for isc in supply_chain_guids:
197
+ egeria_client.link_design_to_implementation(isc, guid, body)
198
+ msg = f"Added `{display_name}` to `{isc}`"
199
+ logger.trace(msg)
200
+
201
+ logger.info(f"Merged related elements in `{display_name}`")
202
+
203
+
204
+ def sync_blueprint_related_elements(egeria_client: EgeriaTech, object_type: str, component_guids: list, guid: str,
205
+ qualified_name: str, display_name: str, replace_all_props: bool = True) -> None:
206
+ """Sync a blueprints related elements.
207
+
208
+ """
209
+ if replace_all_props:
210
+ bp_element = egeria_client.get_solution_blueprint_by_guid(guid)
211
+ solution_components = bp_element['solutionComponents']
212
+ as_is_components = {}
213
+ if len(solution_components) > 0:
214
+ for component in solution_components:
215
+ as_is_components.append(component['elementHeader']['guid'])
216
+
217
+ # should I throw an exception if empty?
218
+
219
+ to_be_components = set(component_guids) if component_guids is not None else set()
220
+
221
+ logger.trace(f"as_is_components: {list(as_is_components)} to_be_sub_components: {list(to_be_components)}")
222
+
223
+ components_to_remove = as_is_components - to_be_components
224
+ logger.trace(f"components_to_remove: {list(components_to_remove)}")
225
+ if len(components_to_remove) > 0:
226
+ for ds in components_to_remove:
227
+ egeria_client.detach_solution_component_from_blueprint(guid, ds, None)
228
+ msg = f"Removed `{ds}` from component `{display_name}`"
229
+ logger.trace(msg)
230
+ components_to_add = to_be_components - as_is_components
231
+ logger.trace(f"sub_components_to_add: {list(components_to_add)}")
232
+ if len(components_to_add) > 0:
233
+ for ds in components_to_add:
234
+ egeria_client.link_solution_component_to_blueprint(guid, ds, None)
235
+ msg = f"Added `{ds}` to component `{display_name}`"
236
+ logger.trace(msg)
237
+
238
+ logger.info(f"Replaced the related elements in `{display_name}`")
239
+
240
+ else: # merge - add field to related elements
241
+ if component_guids:
242
+ for comp in component_guids:
243
+ egeria_client.link_solution_component_to_blueprint(guid, comp, None)
244
+ msg = f"Added `{component_guids}` to `{display_name}`"
245
+ logger.trace(msg)
246
+
247
+ logger.info(f"Merged related elements in `{display_name}`")
248
+
249
+
250
+ @logger.catch
251
+ def process_blueprint_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
252
+ """
253
+ Processes a solution blueprint create or update object_action by extracting key attributes such as
254
+ blueprint name, description, and usage from the given text.
255
+
256
+ :param txt: A string representing the input cell to be processed for
257
+ extracting blueprint-related attributes.
258
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
259
+ :return: A string summarizing the outcome of the processing.
260
+ """
261
+ command, object_type, object_action = extract_command_plus(txt)
262
+ print(Markdown(f"# {command}\n"))
263
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
264
+
265
+ valid = parsed_output['valid']
266
+ exists = parsed_output['exists']
267
+
268
+ qualified_name = parsed_output.get('qualified_name', None)
269
+ guid = parsed_output.get('guid', None)
270
+
271
+ print(Markdown(parsed_output['display']))
272
+
273
+ logger.debug(json.dumps(parsed_output, indent=4))
274
+
275
+ attributes = parsed_output['attributes']
276
+ description = attributes.get('Description', {}).get('value', None)
277
+ display_name = attributes['Display Name'].get('value', None)
278
+ version_identifier = attributes.get('Version Identifier', {}).get('value', None)
279
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
280
+ effective_from = attributes.get('Effective From', {}).get('value', None)
281
+ effective_to = attributes.get('Effective To', {}).get('value', None)
282
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
283
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
284
+
285
+ anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
286
+ parent_guid = attributes.get('Parent ID', {}).get('guid', None)
287
+ parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
288
+ parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
289
+
290
+ anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
291
+ is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
292
+ if parent_guid is None:
293
+ is_own_anchor = True
294
+
295
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
296
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
297
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
298
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
299
+ component_guids = attributes.get('Solution Components', {}).get('guid_list', None)
300
+
301
+ initial_status = "ACTIVE"
302
+
303
+ replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
304
+
305
+ if directive == "display":
306
+
307
+ return None
308
+ elif directive == "validate":
309
+ if valid:
310
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
311
+ else:
312
+ msg = f"Validation failed for object_action `{command}`\n"
313
+ return valid
314
+
315
+ elif directive == "process":
316
+ try:
317
+ if object_action == "Update":
318
+ if not exists:
319
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
320
+ f"object_action\n")
321
+ logger.error(msg)
322
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
323
+ elif not valid:
324
+ return None
325
+ else:
326
+ print(Markdown(
327
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
328
+
329
+ body = body_slimmer({
330
+ "class": "UpdateSolutionBlueprintRequestBody", "externalSourceGUID": external_source_guid,
331
+ "externalSourceName": external_source_name, "effectiveTime": effective_time,
332
+ "forLineage": False, "forDuplicateProcessing": False, "properties": {
333
+ "class": "SolutionBlueprintProperties", "qualifiedName": qualified_name,
334
+ "displayName": display_name, "description": description, "version": version_identifier,
335
+ "additionalProperties": additional_properties, "extendedProperties": extended_properties,
336
+ "effectiveFrom": effective_from, "effectiveTo": effective_to
337
+ }
338
+ })
339
+
340
+ egeria_client.update_solution_blueprint(guid, body, replace_all_props)
341
+ logger.success(f"==> Updated {object_type} `{display_name}` with GUID {guid}\n\n")
342
+ update_element_dictionary(qualified_name, {
343
+ 'guid': guid, 'display_name': display_name
344
+ })
345
+ sync_blueprint_related_elements(egeria_client, object_type, component_guids, guid, qualified_name,
346
+ display_name, replace_all_props)
347
+ logger.success(f"===> Updated {object_type} `{display_name}` related elements\n\n")
348
+ return egeria_client.find_solution_blueprints(qualified_name, output_format='MD')
349
+
350
+
351
+ elif object_action == "Create":
352
+ print(f"valid: {valid}, type: {type(valid)}")
353
+ try:
354
+ if valid is False and exists:
355
+ msg = (f" Data Specification `{display_name}` already exists and result document updated changing "
356
+ f"`Create` to `Update` in processed output\n\n___")
357
+ logger.error(msg)
358
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
359
+
360
+ elif not valid:
361
+ msg = (f"==>{object_type} `{display_name}` is not valid and can't be created")
362
+ logger.error(msg)
363
+ return
364
+
365
+ else:
366
+ body = {
367
+ "class": "NewSolutionBlueprintRequestBody",
368
+ "externalSourceGUID": external_source_guid,
369
+ "externalSourceName": external_source_name,
370
+ "forLineage": False,
371
+ "forDuplicateProcessing": False,
372
+ "effectiveTime": effective_time,
373
+ "anchorGUID": anchor_guid,
374
+ "isOwnAnchor": is_own_anchor,
375
+ "anchorScopeGUID": anchor_scope_guid,
376
+ "parentGUID": parent_guid,
377
+ "parentRelationshipTypeName": parent_relationship_type_name,
378
+ "parentAtEnd1": parent_at_end1,
379
+ "properties": {
380
+ "class": "SolutionBlueprintProperties",
381
+ "effectiveFrom": effective_from,
382
+ "effectiveTo": effective_to, # "typeName": type_name,
383
+ "extendedProperties": extended_properties,
384
+ "qualifiedName": qualified_name,
385
+ "additionalProperties": additional_properties,
386
+ "displayName": display_name,
387
+ "description": description,
388
+ "versionIdentifier": version_identifier
389
+ },
390
+ "initialStatus": initial_status,
391
+ }
392
+ guid = egeria_client.create_solution_blueprint(body)
393
+ except Exception as e:
394
+ print(f"Unexpected error: {e}, {type(valid)}, {valid}")
395
+
396
+
397
+ if guid:
398
+ update_element_dictionary(qualified_name, {
399
+ 'guid': guid, 'display_name': display_name
400
+ })
401
+ msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
402
+ logger.success(msg)
403
+ return egeria_client.find_solution_blueprints(qualified_name, output_format='MD')
404
+ else:
405
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
406
+ logger.error(msg)
407
+ return None
408
+
409
+ except Exception as e:
410
+ print("why did I get here")
411
+ logger.error(f"Error performing {command}: {e}")
412
+ return None
413
+ else:
414
+ return None
415
+
416
+
417
+ @logger.catch
418
+ def process_solution_component_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> \
419
+ Optional[str]:
420
+ """
421
+ Processes a solution component create or update object_action by extracting key attributes such as
422
+ component name, description, and parent components from the given text.
423
+
424
+ :param txt: A string representing the input cell to be processed for
425
+ extracting component-related attributes.
426
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
427
+ :return: A string summarizing the outcome of the processing.
428
+ """
429
+ command, object_type, object_action = extract_command_plus(txt)
430
+ print(Markdown(f"# {command}\n"))
431
+
432
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
433
+
434
+ valid = parsed_output['valid']
435
+ exists = parsed_output['exists']
436
+
437
+ qualified_name = parsed_output.get('qualified_name', None)
438
+ guid = parsed_output.get('guid', None)
439
+
440
+ print(Markdown(parsed_output['display']))
441
+
442
+ logger.debug(json.dumps(parsed_output, indent=4))
443
+
444
+ attributes = parsed_output['attributes']
445
+
446
+ description = attributes.get('Description', {}).get('value', None)
447
+ display_name = attributes['Display Name'].get('value', None)
448
+ version_identifier = attributes.get('Version Identifier', {}).get('value', None)
449
+ solution_component_type = attributes.get('Solution Component Type', {}).get('value', None)
450
+ planned_deployed_impl_type = attributes.get('Planned Deployed Implementation Type', {}).get('value', None)
451
+ initial_status = attributes.get('Status', {}).get('value', None)
452
+ user_defined_status = attributes.get('User Defined Status', {}).get('value', None)
453
+ if initial_status != "OTHER":
454
+ user_defined_status = None
455
+
456
+ # sub_component_names = attributes.get('Solution SubComponents', {}).get('name_list', None)
457
+ # sub_component_guids = attributes.get('Solution SubComponents', {}).get('guid_list', None)
458
+ actor_names = attributes.get('Actors', {}).get('name_list', None)
459
+ actor_guids = attributes.get('Actors', {}).get('guid_list', None)
460
+ in_blueprint_names = attributes.get('In Solution Blueprints', {}).get('name_list', None)
461
+ in_blueprint_guids = attributes.get('In Solution Blueprints', {}).get('guid_list', None)
462
+ in_supply_chain_names = attributes.get('In Information Supply Chains', {}).get('name_list', None)
463
+ in_supply_chain_guids = attributes.get('In Information Supply Chains', {}).get('guid_list', None)
464
+ in_component_names = attributes.get('In Solution Components', {}).get('name_list', None)
465
+ in_component_guids = attributes.get('In Solution Components', {}).get('guid_list', None)
466
+ parent_component_guids = attributes.get('Parent Components', {}).get('guid_list', None)
467
+ parent_component_names = attributes.get('Parent Components', {}).get('name_list', None)
468
+
469
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
470
+ effective_from = attributes.get('Effective From', {}).get('value', None)
471
+ effective_to = attributes.get('Effective To', {}).get('value', None)
472
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
473
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
474
+
475
+ anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
476
+ parent_guid = attributes.get('Parent ID', {}).get('guid', None)
477
+ parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
478
+ parent_relationship_properties = attributes.get('Parent Relationship Properties', {}).get('value', None)
479
+ parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
480
+
481
+ anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
482
+ is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
483
+ if parent_guid is None:
484
+ is_own_anchor = True
485
+
486
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
487
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
488
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
489
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
490
+
491
+ merge_update = attributes.get('Merge Update', {}).get('value', True)
492
+
493
+
494
+
495
+ if directive == "display":
496
+
497
+ return None
498
+ elif directive == "validate":
499
+ if valid:
500
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
501
+ else:
502
+ msg = f"Validation failed for object_action `{command}`\n"
503
+ return valid
504
+
505
+ elif directive == "process":
506
+ try:
507
+ if object_action == "Update":
508
+ if not exists:
509
+ msg = (f"==> Element `{display_name}` does not exist! Updating result document with Create."
510
+ f"object_action\n")
511
+ logger.error(msg)
512
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
513
+ elif not valid:
514
+ logger.error(f"==> Element `{display_name}` entry is not valid. Please refer to the errors above.")
515
+ return None
516
+ else:
517
+ print(Markdown(
518
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
519
+
520
+ body = body_slimmer({
521
+ "class": "UpdateElementRequestBody",
522
+ "externalSourceGUID": external_source_guid,
523
+ "externalSourceName": external_source_name,
524
+ "effectiveTime": effective_time, "forLineage": False,
525
+ "forDuplicateProcessing": False,
526
+ "parentAtEnd1": parent_at_end1,
527
+ "properties": {
528
+ "class": "SolutionComponentProperties",
529
+ "qualifiedName": qualified_name,
530
+ "displayName": display_name,
531
+ "description": description,
532
+ "solutionComponentType": solution_component_type,
533
+ "plannedDeployedImplementationType": planned_deployed_impl_type,
534
+ "additionalProperties": additional_properties,
535
+ "extendedProperties": extended_properties,
536
+ "effectiveFrom": effective_from,
537
+ "effectiveTo": effective_to
538
+ }
539
+ })
540
+
541
+ egeria_client.update_solution_component(guid, body, not merge_update)
542
+ logger.success(f"==>Updated {object_type} `{display_name}` with GUID {guid}\n")
543
+ update_element_dictionary(qualified_name, {
544
+ 'guid': guid, 'display_name': display_name
545
+ })
546
+ # Sync Parent Components and Blueprints
547
+ sync_component_related_elements(egeria_client, object_type ,
548
+ in_supply_chain_guids,parent_component_guids,actor_guids,
549
+ in_blueprint_guids, guid, qualified_name,
550
+ display_name,
551
+ merge_update)
552
+ logger.success(f"==>Updated {object_type} `{display_name}` with related elements")
553
+ return egeria_client.get_solution_component_by_guid(guid, output_format='MD')
554
+
555
+
556
+ elif object_action == "Create":
557
+ if valid is False and exists:
558
+ msg = (f" {object_type} `{display_name}` already exists and result document updated changing "
559
+ f"`Create` to `Update` in processed output\n\n___")
560
+ logger.error(msg)
561
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
562
+
563
+ elif not valid:
564
+ msg = (f"==>{object_type} `{display_name}` is not valid and can't be created")
565
+ logger.error(msg)
566
+ return
567
+
568
+ else:
569
+ body = body_slimmer({
570
+ "class": "NewSolutionElementRequestBody",
571
+ "anchorGUID": anchor_guid,
572
+ "isOwnAnchor": is_own_anchor,
573
+ "parentGUID": parent_guid,
574
+ "parentRelationshipTypeName": parent_relationship_type_name,
575
+ "parentRelationshipProperties": parent_relationship_properties,
576
+ "parentAtEnd1": parent_at_end1,
577
+ "properties": {
578
+ "class": "SolutionComponentProperties",
579
+ "qualifiedName": qualified_name,
580
+ "displayName": display_name,
581
+ "description": description,
582
+ "solutionComponentType": solution_component_type,
583
+ "versionIdentifier" : version_identifier,
584
+ "plannedDeployedImplementationType": planned_deployed_impl_type,
585
+ "userDefinedStatus" : user_defined_status,
586
+ "additionalProperties": additional_properties,
587
+ "extendedProperties": extended_properties,
588
+ "effectiveFrom": effective_from,
589
+ "effectiveTo": effective_to
590
+ },
591
+ "initialStatus": initial_status,
592
+ "externalSourceGUID": external_source_guid,
593
+ "externalSourceName": external_source_name,
594
+ "effectiveTime": effective_time,
595
+ "forLineage": False,
596
+ "forDuplicateProcessing": False
597
+ })
598
+
599
+ guid = egeria_client.create_solution_component(body)
600
+ if guid:
601
+ update_element_dictionary(qualified_name, {
602
+ 'guid': guid, 'display_name': display_name
603
+ })
604
+ msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
605
+ logger.success(msg)
606
+ if in_component_guids:
607
+ for comp in in_component_guids:
608
+ egeria_client.link_subcomponent(comp, guid, None)
609
+ msg = f"Added to parent components `{in_component_names}` "
610
+ logger.trace(msg)
611
+
612
+ if actor_guids:
613
+ for actor in actor_guids:
614
+ egeria_client.link_component_to_actor(actor, guid, None)
615
+ msg = f"Added `{actor_guids}` to `{display_name}`"
616
+ logger.trace(msg)
617
+
618
+ if in_blueprint_guids:
619
+ for bp in in_blueprint_guids:
620
+ egeria_client.link_solution_component_to_blueprint(bp, guid, None)
621
+ msg = f"Added `{display_name}`to blueprints `{in_blueprint_names}`"
622
+ logger.trace(msg)
623
+
624
+ if in_supply_chain_guids:
625
+ for isc in in_supply_chain_guids:
626
+ egeria_client.link_design_to_implementation(isc, guid, None)
627
+ msg = f"Added `{display_name}`to supply chain `{in_supply_chain_names}`"
628
+ logger.trace(msg)
629
+
630
+ return egeria_client.get_solution_component_by_guid(guid, output_format='MD')
631
+ else:
632
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
633
+ logger.error(msg)
634
+ return None
635
+
636
+ except Exception as e:
637
+ logger.error(f"Error performing {command}: {e}")
638
+ return None
639
+ else:
640
+ return None
641
+
642
+
643
+ @logger.catch
644
+ def process_component_link_unlink_command(egeria_client: EgeriaTech, txt: str,
645
+ directive: str = "display") -> Optional[str]:
646
+ """
647
+ Processes a link or unlink command to wire solution components.
648
+
649
+ :param txt: A string representing the input cell to be processed for
650
+ extracting blueprint-related attributes.
651
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
652
+ :return: A string summarizing the outcome of the processing.
653
+ """
654
+ command, object_type, object_action = extract_command_plus(txt)
655
+ print(Markdown(f"# {command}\n"))
656
+
657
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
658
+
659
+ print(Markdown(parsed_output['display']))
660
+
661
+ logger.debug(json.dumps(parsed_output, indent=4))
662
+
663
+ attributes = parsed_output['attributes']
664
+
665
+ component1 = attributes.get('Component1', {}).get('guid', None)
666
+ component2 = attributes.get('Component2', {}).get('guid', None)
667
+ label = attributes.get('Wire Label', {}).get('value', None)
668
+ description = attributes.get('Description', {}).get('value', None)
669
+
670
+ valid = parsed_output['valid']
671
+ exists = component1 is not None and component2 is not None
672
+
673
+
674
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
675
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
676
+
677
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
678
+ effective_from = attributes.get('Effective From', {}).get('value', None)
679
+ effective_to = attributes.get('Effective To', {}).get('value', None)
680
+
681
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
682
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
683
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
684
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
685
+
686
+ if directive == "display":
687
+
688
+ return None
689
+ elif directive == "validate":
690
+ if valid:
691
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
692
+ else:
693
+ msg = f"Validation failed for object_action `{command}`\n"
694
+ return valid
695
+
696
+ elif directive == "process":
697
+ try:
698
+ if object_action == "Unlink":
699
+ if not exists:
700
+ msg = (f" Link `{label}` does not exist! Updating result document with Link "
701
+ f"object_action\n")
702
+ logger.error(msg)
703
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
704
+ return out
705
+ elif not valid:
706
+ return None
707
+ else:
708
+ print(Markdown(
709
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
710
+
711
+ body = body_slimmer({
712
+ "class": "MetadataSourceRequestBody",
713
+ "externalSourceGUID": external_source_guid,
714
+ "externalSourceName": external_source_name,
715
+ "effectiveTime": effective_time,
716
+ "forLineage": False,
717
+ "forDuplicateProcessing": False
718
+ })
719
+
720
+ egeria_client.detach_solution_linking_wire(component1, component2, body)
721
+
722
+ logger.success(f"===> Detached segment with {label} from `{component1}`to {component2}\n")
723
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
724
+
725
+ return (out)
726
+
727
+
728
+ elif object_action == "Link":
729
+ if valid is False and exists:
730
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
731
+ f"`Link` to `Detach` in processed output\n")
732
+ logger.error(msg)
733
+
734
+ elif valid is False:
735
+ msg = f"==>{object_type} Link with label `{label}` is not valid and can't be created"
736
+ logger.error(msg)
737
+ return
738
+ else:
739
+ body = {
740
+ "class": "RelationshipRequestBody",
741
+ "effectiveTime": effective_time,
742
+ "forLineage": False,
743
+ "forDuplicateProcessing": False,
744
+ "properties": {
745
+ "class": "SolutionLinkingWireProperties",
746
+ "label": label,
747
+ "description": description,
748
+ "effectiveFrom": effective_from,
749
+ "effectiveTo": effective_to
750
+ }
751
+ }
752
+
753
+ egeria_client.link_solution_linking_wire(component1, component2, None)
754
+ msg = f"==>Created {object_type} link named `{label}`\n"
755
+ logger.success(msg)
756
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
757
+ return out
758
+
759
+
760
+ except Exception as e:
761
+ logger.error(f"Error performing {command}: {e}")
762
+ return None
763
+ else:
764
+ return None
765
+
766
+
767
+
768
+ @logger.catch
769
+ def process_information_supply_chain_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") \
770
+ -> \
771
+ Optional[str]:
772
+ """
773
+ Processes a solution blueprint create or update object_action by extracting key attributes such as
774
+ blueprint name, description, and usage from the given text.
775
+
776
+ :param txt: A string representing the input cell to be processed for
777
+ extracting blueprint-related attributes.
778
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
779
+ :return: A string summarizing the outcome of the processing.
780
+ """
781
+ command, object_type, object_action = extract_command_plus(txt)
782
+ print(Markdown(f"# {command}\n"))
783
+
784
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
785
+
786
+ valid = parsed_output['valid']
787
+ exists = parsed_output['exists']
788
+
789
+ qualified_name = parsed_output.get('qualified_name', None)
790
+ guid = parsed_output.get('guid', None)
791
+
792
+ print(Markdown(parsed_output['display']))
793
+
794
+ logger.debug(json.dumps(parsed_output, indent=4))
795
+
796
+ attributes = parsed_output['attributes']
797
+ description = attributes.get('Description', {}).get('value', None)
798
+ display_name = attributes['Display Name'].get('value', None)
799
+ version_identifier = attributes.get('Version Identifier', {}).get('value', None)
800
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
801
+ effective_from = attributes.get('Effective From', {}).get('value', None)
802
+ effective_to = attributes.get('Effective To', {}).get('value', None)
803
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
804
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
805
+
806
+ anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
807
+ parent_guid = attributes.get('Parent ID', {}).get('guid', None)
808
+ parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
809
+ parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
810
+
811
+ anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
812
+ is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
813
+ if parent_guid is None:
814
+ is_own_anchor = True
815
+ nested_supply_chain_guids = attributes.get('Nested Supply Chain', {}).get('guids', None)
816
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
817
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
818
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
819
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
820
+
821
+ scope = attributes.get('Scope', {}).get('value', None)
822
+ purposes = attributes.get('Purposes', {}).get('value', None)
823
+ in_supply_chain_guids = attributes.get('In Information Supply Chain', {}).get('guid_list', None)
824
+
825
+ replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
826
+
827
+ if directive == "display":
828
+
829
+ return None
830
+ elif directive == "validate":
831
+ if valid:
832
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
833
+ else:
834
+ msg = f"Validation failed for object_action `{command}`\n"
835
+ return valid
836
+
837
+ elif directive == "process":
838
+ try:
839
+ if object_action == "Update":
840
+ if not exists:
841
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
842
+ f"object_action\n")
843
+ logger.error(msg)
844
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
845
+ elif not valid:
846
+ return None
847
+ else:
848
+ print(Markdown(
849
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
850
+
851
+ body = body_slimmer({
852
+ "class": "UpdateElementRequestBody",
853
+ "externalSourceGUID": external_source_guid,
854
+ "externalSourceName": external_source_name,
855
+ "effectiveTime": effective_time,
856
+ "forLineage": False,
857
+ "forDuplicateProcessing": False,
858
+ "properties": {
859
+ "class": "InformationSupplyChainProperties", "effectiveFrom": effective_from,
860
+ "effectiveTo": effective_to, "extendedProperties": extended_properties,
861
+ "qualifiedName": qualified_name, "additionalProperties": additional_properties,
862
+ "displayName": display_name, "description": description, "scope": scope,
863
+ "purposes": purposes, "version": version_identifier
864
+ }
865
+ })
866
+
867
+ egeria_client.update_info_supply_chain(guid, body, replace_all_props)
868
+
869
+ sync_chain_related_elements(egeria_client, guid, in_supply_chain_guids, display_name, replace_all_props)
870
+ logger.success(f"==> Updated {object_type} `{display_name}` with GUID {guid}\n\n")
871
+ update_element_dictionary(qualified_name, {
872
+ 'guid': guid, 'display_name': display_name
873
+ })
874
+
875
+ # logger.success(f"===> Updated {object_type} `{display_name}` related elements\n\n")
876
+ return egeria_client.get_info_supply_chain_by_guid(guid, output_format='MD')
877
+
878
+
879
+ elif object_action == "Create":
880
+ if valid is False and exists:
881
+ msg = (
882
+ f"--> Data Specification `{display_name}` already exists and result document updated changing "
883
+ f"`Create` to `Update` in processed output\n")
884
+ logger.error(msg)
885
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
886
+
887
+ elif valid is False:
888
+ msg = f"==>{object_type} `{display_name}` is not valid and can't be created"
889
+ logger.error(msg)
890
+ return
891
+ else:
892
+ body = {
893
+ "class": "NewElementRequestBody",
894
+ "externalSourceGUID": external_source_guid,
895
+ "externalSourceName": external_source_name,
896
+ "forLineage": False,
897
+ "forDuplicateProcessing": False,
898
+ "effectiveTime": effective_time,
899
+ "anchorGUID": anchor_guid,
900
+ "isOwnAnchor": is_own_anchor,
901
+ "anchorScopeGUID": anchor_scope_guid,
902
+ "parentGUID": parent_guid,
903
+ "parentRelationshipTypeName": parent_relationship_type_name,
904
+ "parentAtEnd1": parent_at_end1,
905
+ "properties": {
906
+ "class": "InformationSupplyChainProperties",
907
+ "effectiveFrom": effective_from,
908
+ "effectiveTo": effective_to,
909
+ "extendedProperties": extended_properties,
910
+ "qualifiedName": qualified_name,
911
+ "additionalProperties": additional_properties,
912
+ "displayName": display_name,
913
+ "description": description,
914
+ "scope": scope,
915
+ "purposes": purposes,
916
+ "version": version_identifier
917
+ }
918
+ }
919
+
920
+ guid = egeria_client.create_info_supply_chain(body)
921
+ if guid:
922
+ update_element_dictionary(qualified_name, {
923
+ 'guid': guid, 'display_name': display_name
924
+ })
925
+ if len(in_supply_chain_guids) > 0:
926
+ for nested_chain in in_supply_chain_guids:
927
+ egeria_client.compose_info_supply_chains(guid, nested_chain)
928
+
929
+ msg = f"==>Created Element `{display_name}` with GUID {guid}\n"
930
+ logger.success(msg)
931
+ return egeria_client.get_info_supply_chain_by_guid(guid, output_format='MD')
932
+ else:
933
+ msg = f"==>Failed to create element `{display_name}` with GUID {guid}\n"
934
+ logger.error(msg)
935
+ return None
936
+
937
+ except Exception as e:
938
+ logger.error(f"Error performing {command}: {e}")
939
+ return None
940
+ else:
941
+ return None
942
+
943
+
944
+
945
+ @logger.catch
946
+ def process_information_supply_chain_link_unlink_command(egeria_client: EgeriaTech, txt: str,
947
+ directive: str = "display") -> Optional[str]:
948
+ """
949
+ Processes a link or unlink command to associate or break up peer supply chains..
950
+
951
+ :param txt: A string representing the input cell to be processed for
952
+ extracting blueprint-related attributes.
953
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
954
+ :return: A string summarizing the outcome of the processing.
955
+ """
956
+ command, object_type, object_action = extract_command_plus(txt)
957
+ print(Markdown(f"# {command}\n"))
958
+
959
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
960
+
961
+ print(Markdown(parsed_output['display']))
962
+
963
+ logger.debug(json.dumps(parsed_output, indent=4))
964
+
965
+ attributes = parsed_output['attributes']
966
+
967
+ component1 = attributes.get('component1', {}).get('guid', None)
968
+ component2 = attributes.get('component2', {}).get('guid', None)
969
+ label = attributes.get('Link Label', {}).get('value', None)
970
+ description = attributes.get('Description', {}).get('value', None)
971
+
972
+ valid = parsed_output['valid']
973
+ exists = component1 is not None and component2 is not None
974
+
975
+
976
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
977
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
978
+
979
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
980
+ effective_from = attributes.get('Effective From', {}).get('value', None)
981
+ effective_to = attributes.get('Effective To', {}).get('value', None)
982
+
983
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
984
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
985
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
986
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
987
+
988
+ if directive == "display":
989
+
990
+ return None
991
+ elif directive == "validate":
992
+ if valid:
993
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
994
+ else:
995
+ msg = f"Validation failed for object_action `{command}`\n"
996
+ return valid
997
+
998
+ elif directive == "process":
999
+ try:
1000
+ if object_action == "Unlink":
1001
+ if not exists:
1002
+ msg = (f" Link `{label}` does not exist! Updating result document with Link "
1003
+ f"object_action\n")
1004
+ logger.error(msg)
1005
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1006
+ return out
1007
+ elif not valid:
1008
+ return None
1009
+ else:
1010
+ print(Markdown(
1011
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
1012
+
1013
+ body = body_slimmer({
1014
+ "class": "MetadataSourceRequestBody",
1015
+ "externalSourceGUID": external_source_guid,
1016
+ "externalSourceName": external_source_name,
1017
+ "effectiveTime": effective_time,
1018
+ "forLineage": False,
1019
+ "forDuplicateProcessing": False
1020
+ })
1021
+
1022
+ egeria_client.unlink_peer_info_supply_chains(component1, component2, body)
1023
+
1024
+ logger.success(f"===> Detached segment with {label} from `{component1}`to {component2}\n")
1025
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
1026
+
1027
+ return (out)
1028
+
1029
+
1030
+ elif object_action == "Link":
1031
+ if valid is False and exists:
1032
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
1033
+ f"`Link` to `Detach` in processed output\n")
1034
+ logger.error(msg)
1035
+
1036
+ elif valid is False:
1037
+ msg = f"==>{object_type} Link with label `{label}` is not valid and can't be created"
1038
+ logger.error(msg)
1039
+ return
1040
+ else:
1041
+ body = {
1042
+ "class": "RelationshipRequestBody",
1043
+ "effectiveTime": effective_time,
1044
+ "forLineage": False,
1045
+ "forDuplicateProcessing": False,
1046
+ "properties": {
1047
+ "class": "InformationSupplyChainLinkProperties",
1048
+ "label": label,
1049
+ "description": description,
1050
+ "effectiveFrom": effective_from,
1051
+ "effectiveTo": effective_to
1052
+ }
1053
+ }
1054
+
1055
+ egeria_client.link_peer_info_supply_chain(component1, component2, body)
1056
+ msg = f"==>Created {object_type} link named `{label}`\n"
1057
+ logger.success(msg)
1058
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1059
+ return out
1060
+
1061
+
1062
+ except Exception as e:
1063
+ logger.error(f"Error performing {command}: {e}")
1064
+ return None
1065
+ else:
1066
+ return None
1067
+
1068
+ @logger.catch
1069
+ def process_sol_arch_list_command(egeria_client: EgeriaTech, txt: str, kind:str, directive: str = "display" ) -> Optional[str]:
1070
+ """
1071
+ Processes Solution Blueprint list object_action by extracting key attributes such as
1072
+ search string from the given text.
1073
+
1074
+ :param txt: A string representing the input cell to be processed for
1075
+ extracting term-related attributes.
1076
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
1077
+ :return: A string summarizing the outcome of the processing.
1078
+ """
1079
+ command, object_type, object_action = extract_command_plus(txt)
1080
+ print(Markdown(f"# {command}\n"))
1081
+
1082
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
1083
+
1084
+ attributes = parsed_output['attributes']
1085
+
1086
+ valid = parsed_output['valid']
1087
+
1088
+ print(Markdown(parsed_output['display']))
1089
+
1090
+ if directive == "display":
1091
+ return None
1092
+ elif directive == "validate":
1093
+ if valid:
1094
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
1095
+ else:
1096
+ msg = f"Validation failed for object_action `{command}`\n"
1097
+ logger.error(msg)
1098
+ return valid
1099
+
1100
+ elif directive == "process":
1101
+ attributes = parsed_output['attributes']
1102
+ search_string = attributes.get('Search String', {}).get('value', '*')
1103
+ output_format = attributes.get('Output Format', {}).get('value', 'LIST')
1104
+ detailed = attributes.get('Detailed', {}).get('value', False)
1105
+
1106
+ match kind:
1107
+ case "Solution Blueprints":
1108
+ find_proc = egeria_client.find_solution_blueprints
1109
+ case "Information Supply Chains":
1110
+ find_proc = egeria_client.find_information_supply_chains
1111
+ case "Solution Components":
1112
+ find_proc = egeria_client.find_solution_components
1113
+ case "Solution Roles":
1114
+ find_proc = egeria_client.find_solution_roles
1115
+
1116
+ try:
1117
+ if not valid: # First validate the command before we process it
1118
+ msg = f"Validation failed for {object_action} `{object_type}`\n"
1119
+ logger.error(msg)
1120
+ return None
1121
+
1122
+ list_md = f"\n# {kind} with filter: `{search_string}`\n\n"
1123
+ if output_format == "DICT":
1124
+ struct = find_proc(search_string, output_format=output_format)
1125
+ list_md += f"```{json.dumps(struct, indent=4)}```\n"
1126
+ else:
1127
+ list_md += find_proc(search_string, output_format=output_format)
1128
+ logger.info(f"Wrote Output for search string: `{search_string}`")
1129
+
1130
+ return list_md
1131
+
1132
+ except Exception as e:
1133
+ logger.error(f"Error performing {command}: {e}")
1134
+ console.print_exception(show_locals=True)
1135
+ return None
1136
+ else:
1137
+ return None
1138
+
1139
+