pyegeria 5.3.9.9.3__py3-none-any.whl → 5.5.3.3__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.

Potentially problematic release.


This version of pyegeria might be problematic. Click here for more details.

Files changed (272) hide show
  1. commands/__init__.py +24 -0
  2. commands/cat/Dr-Egeria_md-orig.py +2 -2
  3. commands/cat/__init__.py +1 -17
  4. commands/cat/collection_actions.py +197 -0
  5. commands/cat/dr_egeria_command_help.py +372 -0
  6. commands/cat/dr_egeria_jupyter.py +7 -7
  7. commands/cat/dr_egeria_md.py +27 -182
  8. commands/cat/exp_list_glossaries.py +11 -14
  9. commands/cat/get_asset_graph.py +37 -267
  10. commands/cat/{get_collection.py → get_collection_tree.py} +10 -18
  11. commands/cat/get_project_dependencies.py +14 -14
  12. commands/cat/get_project_structure.py +15 -14
  13. commands/cat/get_tech_type_elements.py +16 -116
  14. commands/cat/glossary_actions.py +145 -298
  15. commands/cat/list_assets.py +3 -11
  16. commands/cat/list_cert_types.py +17 -63
  17. commands/cat/list_collections.py +46 -138
  18. commands/cat/list_deployed_catalogs.py +15 -27
  19. commands/cat/list_deployed_database_schemas.py +27 -43
  20. commands/cat/list_deployed_databases.py +16 -31
  21. commands/cat/list_deployed_servers.py +35 -54
  22. commands/cat/list_glossaries.py +18 -17
  23. commands/cat/list_projects.py +10 -12
  24. commands/cat/list_tech_type_elements.py +21 -37
  25. commands/cat/list_tech_types.py +13 -25
  26. commands/cat/list_terms.py +38 -79
  27. commands/cat/list_todos.py +4 -11
  28. commands/cat/list_user_ids.py +3 -10
  29. commands/cat/my_reports.py +559 -0
  30. commands/cat/run_report.py +394 -0
  31. commands/cat/run_report_orig.py +528 -0
  32. commands/cli/egeria.py +222 -247
  33. commands/cli/egeria_cat.py +68 -81
  34. commands/cli/egeria_my.py +13 -0
  35. commands/cli/egeria_ops.py +69 -74
  36. commands/cli/egeria_tech.py +17 -93
  37. commands/cli/ops_config.py +3 -6
  38. commands/{cat/list_categories.py → deprecated/list_data_designer.py} +53 -64
  39. commands/{cat/list_data_structures.py → deprecated/list_data_structures_full.py} +3 -6
  40. commands/deprecated/old_get_asset_graph.py +315 -0
  41. commands/my/__init__.py +0 -2
  42. commands/my/list_my_profile.py +27 -34
  43. commands/my/list_my_roles.py +1 -7
  44. commands/my/monitor_my_todos.py +1 -7
  45. commands/my/monitor_open_todos.py +6 -7
  46. commands/my/todo_actions.py +4 -5
  47. commands/ops/__init__.py +0 -2
  48. commands/ops/gov_server_actions.py +17 -21
  49. commands/ops/list_archives.py +17 -38
  50. commands/ops/list_catalog_targets.py +33 -40
  51. commands/ops/load_archive.py +35 -26
  52. commands/ops/{monitor_engine_activity_c.py → monitor_active_engine_activity.py} +51 -82
  53. commands/ops/{monitor_integ_daemon_status.py → monitor_daemon_status.py} +35 -55
  54. commands/ops/monitor_engine_activity.py +79 -77
  55. commands/ops/{monitor_gov_eng_status.py → monitor_engine_status.py} +10 -7
  56. commands/ops/monitor_platform_status.py +38 -50
  57. commands/ops/monitor_server_startup.py +6 -11
  58. commands/ops/monitor_server_status.py +7 -11
  59. commands/ops/orig_monitor_server_list.py +8 -8
  60. commands/ops/orig_monitor_server_status.py +1 -5
  61. commands/ops/refresh_integration_daemon.py +5 -5
  62. commands/ops/restart_integration_daemon.py +5 -5
  63. commands/ops/table_integ_daemon_status.py +6 -6
  64. commands/ops/x_engine_actions.py +7 -7
  65. commands/tech/__init__.py +0 -2
  66. commands/tech/{generic_actions.py → element_actions.py} +6 -11
  67. commands/tech/get_element_info.py +20 -29
  68. commands/tech/get_guid_info.py +23 -42
  69. commands/tech/get_tech_details.py +20 -35
  70. commands/tech/get_tech_type_template.py +28 -39
  71. commands/tech/list_all_om_type_elements.py +24 -30
  72. commands/tech/list_all_om_type_elements_x.py +22 -28
  73. commands/tech/list_all_related_elements.py +19 -28
  74. commands/tech/list_anchored_elements.py +22 -30
  75. commands/tech/list_asset_types.py +19 -24
  76. commands/tech/list_elements_by_classification_by_property_value.py +26 -32
  77. commands/tech/list_elements_by_property_value.py +19 -25
  78. commands/tech/list_elements_by_property_value_x.py +20 -28
  79. commands/tech/list_elements_for_classification.py +28 -41
  80. commands/tech/list_gov_action_processes.py +16 -27
  81. commands/tech/list_information_supply_chains.py +22 -30
  82. commands/tech/list_registered_services.py +14 -26
  83. commands/tech/list_related_elements_with_prop_value.py +15 -25
  84. commands/tech/list_related_specification.py +1 -4
  85. commands/tech/list_relationship_types.py +15 -25
  86. commands/tech/list_relationships.py +20 -36
  87. commands/tech/list_solution_blueprints.py +28 -33
  88. commands/tech/list_solution_components.py +23 -29
  89. commands/tech/list_solution_roles.py +21 -32
  90. commands/tech/list_tech_templates.py +51 -54
  91. commands/tech/list_valid_metadata_values.py +5 -9
  92. commands/tech/table_tech_templates.py +2 -6
  93. commands/tech/x_list_related_elements.py +1 -4
  94. examples/GeoSpatial Products Example.py +524 -0
  95. examples/Jupyter Notebooks/P-egeria-server-config.ipynb +2137 -0
  96. examples/Jupyter Notebooks/README.md +2 -0
  97. examples/Jupyter Notebooks/common/P-environment-check.ipynb +115 -0
  98. examples/Jupyter Notebooks/common/__init__.py +14 -0
  99. examples/Jupyter Notebooks/common/common-functions.ipynb +4694 -0
  100. examples/Jupyter Notebooks/common/environment-check.ipynb +52 -0
  101. examples/Jupyter Notebooks/common/globals.ipynb +184 -0
  102. examples/Jupyter Notebooks/common/globals.py +154 -0
  103. examples/Jupyter Notebooks/common/orig_globals.py +152 -0
  104. examples/format_sets/all_format_sets.json +910 -0
  105. examples/format_sets/custom_format_sets.json +268 -0
  106. examples/format_sets/subset_format_sets.json +187 -0
  107. examples/format_sets_save_load_example.py +291 -0
  108. examples/jacquard_data_sets.py +129 -0
  109. examples/output_formats_example.py +193 -0
  110. examples/test_jacquard_data_sets.py +54 -0
  111. examples/test_jacquard_data_sets_scenarios.py +94 -0
  112. md_processing/__init__.py +90 -0
  113. md_processing/command_dispatcher.py +33 -0
  114. md_processing/command_mapping.py +221 -0
  115. md_processing/data/commands/commands_data_designer.json +537 -0
  116. md_processing/data/commands/commands_external_reference.json +733 -0
  117. md_processing/data/commands/commands_feedback.json +155 -0
  118. md_processing/data/commands/commands_general.json +204 -0
  119. md_processing/data/commands/commands_glossary.json +218 -0
  120. md_processing/data/commands/commands_governance.json +3678 -0
  121. md_processing/data/commands/commands_product_manager.json +865 -0
  122. md_processing/data/commands/commands_project.json +642 -0
  123. md_processing/data/commands/commands_solution_architect.json +366 -0
  124. md_processing/data/commands.json +17568 -0
  125. md_processing/data/commands_working.json +30641 -0
  126. md_processing/data/gened_report_specs.py +6584 -0
  127. md_processing/data/generated_format_sets.json +6533 -0
  128. md_processing/data/generated_format_sets_old.json +4137 -0
  129. md_processing/data/generated_format_sets_old.py +45 -0
  130. md_processing/dr_egeria.py +182 -0
  131. md_processing/md_commands/__init__.py +3 -0
  132. md_processing/md_commands/data_designer_commands.py +1276 -0
  133. md_processing/md_commands/ext_ref_commands.py +530 -0
  134. md_processing/md_commands/feedback_commands.py +726 -0
  135. md_processing/md_commands/glossary_commands.py +684 -0
  136. md_processing/md_commands/governance_officer_commands.py +600 -0
  137. md_processing/md_commands/product_manager_commands.py +1266 -0
  138. md_processing/md_commands/project_commands.py +383 -0
  139. md_processing/md_commands/solution_architect_commands.py +1184 -0
  140. md_processing/md_commands/view_commands.py +295 -0
  141. md_processing/md_processing_utils/__init__.py +4 -0
  142. md_processing/md_processing_utils/common_md_proc_utils.py +1249 -0
  143. md_processing/md_processing_utils/common_md_utils.py +578 -0
  144. md_processing/md_processing_utils/determine_width.py +103 -0
  145. md_processing/md_processing_utils/extraction_utils.py +547 -0
  146. md_processing/md_processing_utils/gen_report_specs.py +643 -0
  147. md_processing/md_processing_utils/generate_dr_help.py +193 -0
  148. md_processing/md_processing_utils/generate_md_cmd_templates.py +144 -0
  149. md_processing/md_processing_utils/generate_md_templates.py +83 -0
  150. md_processing/md_processing_utils/md_processing_constants.py +1228 -0
  151. md_processing/md_processing_utils/message_constants.py +19 -0
  152. pyegeria/__init__.py +201 -443
  153. pyegeria/core/__init__.py +40 -0
  154. pyegeria/core/_base_platform_client.py +574 -0
  155. pyegeria/core/_base_server_client.py +573 -0
  156. pyegeria/core/_exceptions.py +457 -0
  157. pyegeria/core/_globals.py +60 -0
  158. pyegeria/core/_server_client.py +6073 -0
  159. pyegeria/core/_validators.py +257 -0
  160. pyegeria/core/config.py +654 -0
  161. pyegeria/{create_tech_guid_lists.py → core/create_tech_guid_lists.py} +0 -1
  162. pyegeria/core/load_config.py +37 -0
  163. pyegeria/core/logging_configuration.py +207 -0
  164. pyegeria/core/mcp_adapter.py +144 -0
  165. pyegeria/core/mcp_server.py +212 -0
  166. pyegeria/core/utils.py +405 -0
  167. pyegeria/deprecated/__init__.py +0 -0
  168. pyegeria/{_client.py → deprecated/_client.py} +62 -24
  169. pyegeria/{_deprecated_gov_engine.py → deprecated/_deprecated_gov_engine.py} +16 -16
  170. pyegeria/{classification_manager_omvs.py → deprecated/classification_manager_omvs.py} +1988 -1878
  171. pyegeria/deprecated/output_formatter_with_machine_keys.py +1127 -0
  172. pyegeria/{runtime_manager_omvs.py → deprecated/runtime_manager_omvs.py} +216 -229
  173. pyegeria/{valid_metadata_omvs.py → deprecated/valid_metadata_omvs.py} +93 -93
  174. pyegeria/{x_action_author_omvs.py → deprecated/x_action_author_omvs.py} +2 -3
  175. pyegeria/egeria_cat_client.py +25 -51
  176. pyegeria/egeria_client.py +140 -98
  177. pyegeria/egeria_config_client.py +48 -24
  178. pyegeria/egeria_tech_client.py +170 -83
  179. pyegeria/models/__init__.py +150 -0
  180. pyegeria/models/collection_models.py +168 -0
  181. pyegeria/models/models.py +654 -0
  182. pyegeria/omvs/__init__.py +84 -0
  183. pyegeria/omvs/action_author.py +342 -0
  184. pyegeria/omvs/actor_manager.py +5980 -0
  185. pyegeria/omvs/asset_catalog.py +842 -0
  186. pyegeria/omvs/asset_maker.py +2736 -0
  187. pyegeria/omvs/automated_curation.py +4403 -0
  188. pyegeria/omvs/classification_manager.py +11213 -0
  189. pyegeria/omvs/collection_manager.py +5780 -0
  190. pyegeria/omvs/community_matters_omvs.py +468 -0
  191. pyegeria/{core_omag_server_config.py → omvs/core_omag_server_config.py} +157 -157
  192. pyegeria/{data_designer_omvs.py → omvs/data_designer.py} +1991 -1691
  193. pyegeria/omvs/data_discovery.py +869 -0
  194. pyegeria/omvs/data_engineer.py +372 -0
  195. pyegeria/omvs/digital_business.py +1133 -0
  196. pyegeria/omvs/external_links.py +1752 -0
  197. pyegeria/omvs/feedback_manager.py +834 -0
  198. pyegeria/{full_omag_server_config.py → omvs/full_omag_server_config.py} +73 -69
  199. pyegeria/omvs/glossary_manager.py +3231 -0
  200. pyegeria/omvs/governance_officer.py +3009 -0
  201. pyegeria/omvs/lineage_linker.py +314 -0
  202. pyegeria/omvs/location_arena.py +1525 -0
  203. pyegeria/omvs/metadata_expert.py +668 -0
  204. pyegeria/omvs/metadata_explorer_omvs.py +2943 -0
  205. pyegeria/omvs/my_profile.py +1042 -0
  206. pyegeria/omvs/notification_manager.py +358 -0
  207. pyegeria/omvs/people_organizer.py +394 -0
  208. pyegeria/{platform_services.py → omvs/platform_services.py} +113 -193
  209. pyegeria/omvs/product_manager.py +1825 -0
  210. pyegeria/omvs/project_manager.py +1907 -0
  211. pyegeria/omvs/reference_data.py +1140 -0
  212. pyegeria/omvs/registered_info.py +334 -0
  213. pyegeria/omvs/runtime_manager.py +2817 -0
  214. pyegeria/omvs/schema_maker.py +446 -0
  215. pyegeria/{server_operations.py → omvs/server_operations.py} +27 -26
  216. pyegeria/omvs/solution_architect.py +6490 -0
  217. pyegeria/omvs/specification_properties.py +37 -0
  218. pyegeria/omvs/subject_area.py +1042 -0
  219. pyegeria/omvs/template_manager_omvs.py +236 -0
  220. pyegeria/omvs/time_keeper.py +1761 -0
  221. pyegeria/omvs/valid_metadata.py +3221 -0
  222. pyegeria/omvs/valid_metadata_lists.py +37 -0
  223. pyegeria/omvs/valid_type_lists.py +37 -0
  224. pyegeria/view/__init__.py +28 -0
  225. pyegeria/view/_output_format_models.py +514 -0
  226. pyegeria/view/_output_formats.py +14 -0
  227. pyegeria/view/base_report_formats.py +2719 -0
  228. pyegeria/view/dr_egeria_reports.py +56 -0
  229. pyegeria/view/format_set_executor.py +397 -0
  230. pyegeria/{md_processing_utils.py → view/md_processing_utils.py} +5 -5
  231. pyegeria/{mermaid_utilities.py → view/mermaid_utilities.py} +2 -154
  232. pyegeria/view/output_formatter.py +1297 -0
  233. pyegeria-5.5.3.3.dist-info/METADATA +218 -0
  234. pyegeria-5.5.3.3.dist-info/RECORD +241 -0
  235. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info}/WHEEL +2 -1
  236. pyegeria-5.5.3.3.dist-info/entry_points.txt +103 -0
  237. pyegeria-5.5.3.3.dist-info/top_level.txt +4 -0
  238. commands/cat/.DS_Store +0 -0
  239. commands/cat/README.md +0 -16
  240. commands/cli/txt_custom_v2.tcss +0 -19
  241. commands/my/README.md +0 -17
  242. commands/ops/README.md +0 -24
  243. commands/ops/monitor_asset_events.py +0 -108
  244. commands/tech/README.md +0 -24
  245. pyegeria/.DS_Store +0 -0
  246. pyegeria/README.md +0 -35
  247. pyegeria/_globals.py +0 -47
  248. pyegeria/_validators.py +0 -385
  249. pyegeria/asset_catalog_omvs.py +0 -864
  250. pyegeria/automated_curation_omvs.py +0 -3765
  251. pyegeria/collection_manager_omvs.py +0 -2744
  252. pyegeria/dr.egeria spec.md +0 -9
  253. pyegeria/egeria_my_client.py +0 -56
  254. pyegeria/feedback_manager_omvs.py +0 -4573
  255. pyegeria/glossary_browser_omvs.py +0 -3728
  256. pyegeria/glossary_manager_omvs.py +0 -2440
  257. pyegeria/m_test.py +0 -118
  258. pyegeria/md_processing_helpers.py +0 -58
  259. pyegeria/md_processing_utils_orig.py +0 -1103
  260. pyegeria/metadata_explorer_omvs.py +0 -2326
  261. pyegeria/my_profile_omvs.py +0 -1022
  262. pyegeria/output_formatter.py +0 -389
  263. pyegeria/project_manager_omvs.py +0 -1933
  264. pyegeria/registered_info.py +0 -167
  265. pyegeria/solution_architect_omvs.py +0 -2156
  266. pyegeria/template_manager_omvs.py +0 -1414
  267. pyegeria/utils.py +0 -197
  268. pyegeria-5.3.9.9.3.dist-info/METADATA +0 -72
  269. pyegeria-5.3.9.9.3.dist-info/RECORD +0 -143
  270. pyegeria-5.3.9.9.3.dist-info/entry_points.txt +0 -99
  271. /pyegeria/{_exceptions.py → deprecated/_exceptions.py} +0 -0
  272. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,1184 @@
1
+ """
2
+ This file contains blueprint/solution-related object_action functions for processing Egeria Markdown
3
+ """
4
+
5
+ import json
6
+ import sys
7
+ from datetime import datetime
8
+ from typing import Optional
9
+
10
+ from loguru import logger
11
+ from pygments.lexers import blueprint
12
+ from rich import print
13
+ from rich.console import Console
14
+ from rich.markdown import Markdown
15
+
16
+ from md_processing.md_processing_utils.common_md_proc_utils import (parse_upsert_command, parse_view_command)
17
+ from md_processing.md_processing_utils.common_md_utils import update_element_dictionary, set_element_prop_body, \
18
+ set_update_body, set_create_body, add_search_keywords, add_note_in_dr_e
19
+ from md_processing.md_processing_utils.extraction_utils import (extract_command_plus, update_a_command)
20
+ from md_processing.md_processing_utils.md_processing_constants import (load_commands)
21
+ from pyegeria import body_slimmer, EgeriaTech, PyegeriaException, print_basic_exception
22
+
23
+ load_commands('commands.json')
24
+
25
+ console = Console(width=int(200))
26
+
27
+
28
+ @logger.catch
29
+ def sync_chain_related_elements(egeria_client: EgeriaTech, guid:str, in_supply_chain_guids:list, display_name:str,
30
+ merge_update:bool):
31
+ if not merge_update:
32
+ rel_el_list = egeria_client._get_supply_chain_rel_elements(guid)
33
+ if rel_el_list is None:
34
+ logger.warning("Unexpected -> the list was None - assigning empty list")
35
+ rel_el_list = {}
36
+
37
+ as_is_parent_guids = set(rel_el_list.get("parent_guids", []))
38
+
39
+ to_be_parent_guids = set(in_supply_chain_guids) if in_supply_chain_guids is not None else set()
40
+
41
+ logger.trace(
42
+ f"as_is_parent supply chains: {list(as_is_parent_guids)} to_be_parent supply chains: {list(to_be_parent_guids)}")
43
+
44
+
45
+ parent_guids_to_remove = as_is_parent_guids - to_be_parent_guids
46
+ logger.trace(f"parent_guids_to_remove: {list(parent_guids_to_remove)}")
47
+ if len(parent_guids_to_remove) > 0:
48
+ for parent_guid in parent_guids_to_remove:
49
+ egeria_client.decompose_info_supply_chains(parent_guid, guid, None)
50
+ msg = f"Removed `{display_name}` from supply chain parent `{parent_guid}`"
51
+ logger.trace(msg)
52
+
53
+ parent_guids_to_add = to_be_parent_guids - as_is_parent_guids
54
+ logger.trace(f"parent supply chains_to_add: {list(parent_guids_to_add)}")
55
+ if len(parent_guids_to_add) > 0:
56
+ for parent_guid in parent_guids_to_add:
57
+ egeria_client.compose_info_supply_chains(parent_guid, guid, None)
58
+ msg = f"Added `{display_name}` to supply chain parent `{parent_guid}`"
59
+ logger.trace(msg)
60
+
61
+ else: # merge - add supply chain to parents
62
+ if in_supply_chain_guids:
63
+ for parent_guid in in_supply_chain_guids:
64
+ egeria_client.compose_info_supply_chains(parent_guid, guid, None)
65
+ msg = f"Added `{display_name}` to supply chain `{parent_guid}`"
66
+ logger.trace(msg)
67
+
68
+
69
+
70
+ @logger.catch
71
+ def sync_component_related_elements(egeria_client: EgeriaTech, object_type: str,
72
+ supply_chain_guids: list, parent_component_guids: list,
73
+ actor_guids: list, in_blueprint_guids: list, keywords: list[str], guid: str, qualified_name: str,
74
+ display_name: str, merge_update: bool = True) -> None:
75
+ """Sync a components related elements.
76
+
77
+ """
78
+ if not merge_update:
79
+ rel_el_list = egeria_client.get_component_related_elements(guid)
80
+ # should I throw an exception if empty?
81
+
82
+ as_is_actors = set(rel_el_list.get("actor_guids", []))
83
+ as_is_blueprints = set(rel_el_list.get("blueprint_guids", []))
84
+ as_is_parent_components = set(rel_el_list.get("parent_component_guids", []))
85
+ as_is_supply_chains = set(rel_el_list.get("supply_chain_guids", []))
86
+ as_is_keywords_list = set(rel_el_list.get("keywords_list", {}))
87
+ as_is_keywords = set(rel_el_list.get("keywords_list", {}).keys())
88
+
89
+
90
+ to_be_actors = set(actor_guids) if actor_guids is not None else set()
91
+ to_be_blueprints = set(in_blueprint_guids) if in_blueprint_guids is not None else set()
92
+ to_be_parent_components = set(parent_component_guids) if parent_component_guids is not None else set()
93
+ to_be_supply_chains = set(supply_chain_guids) if supply_chain_guids is not None else set()
94
+ to_be_keywords_list = set(keywords) if keywords is not None else set()
95
+
96
+
97
+ logger.trace(
98
+ f"as_is_sub_components: {list(as_is_parent_components)} to_be_sub_components: {list(to_be_parent_components)}")
99
+ logger.trace(f"as_is_actors: {list(as_is_actors)} to_be_actors: {list(to_be_actors)}")
100
+ logger.trace(f"as_is_blueprints: {list(as_is_blueprints)} to_be_blueprints: {list(to_be_blueprints)}")
101
+
102
+ keywords_to_add = to_be_keywords_list - as_is_keywords
103
+ logger.trace(f"keywords_to_add: {list(keywords_to_add)}")
104
+ if len(keywords_to_add) > 0:
105
+ for ds in keywords_to_add:
106
+ egeria_client.add_search_keyword_to_element(guid, ds)
107
+ msg = f"Added `{ds}` to component `{guid}`"
108
+ logger.trace(msg)
109
+
110
+ keywords_to_remove = as_is_keywords_list - to_be_keywords_list
111
+ logger.trace(f"keyword_to_remove: {list(keywords_to_remove)}")
112
+ if len(keywords_to_remove) > 0:
113
+ for ds in keywords_to_remove: ## change structure of get related elements to return pairs of keywords and guids
114
+ egeria_client.remove_search_keyword(rel_el_list['keywords_list'][ds])
115
+ msg = f"Removed `{ds}` from component `{guid}`"
116
+ logger.trace(msg)
117
+
118
+ parent_components_to_remove = as_is_parent_components - to_be_parent_components
119
+ logger.trace(f"sub_components_to_remove: {list(parent_components_to_remove)}")
120
+ if len(parent_components_to_remove) > 0:
121
+ for ds in parent_components_to_remove:
122
+ egeria_client.detach_sub_component(ds, guid, None)
123
+ msg = f"Removed `{display_name}` from component `{ds}`"
124
+ logger.trace(msg)
125
+
126
+
127
+
128
+ parent_components_to_add = to_be_parent_components - as_is_parent_components
129
+ logger.trace(f"parent_components_to_add: {list(parent_components_to_add)}")
130
+ if len(parent_components_to_add) > 0:
131
+ for ds in parent_components_to_add:
132
+ egeria_client.link_subcomponent(ds, guid, None)
133
+ msg = f"Added `{display_name}` to component `{ds}`"
134
+ logger.trace(msg)
135
+
136
+ blueprints_to_remove = as_is_blueprints - to_be_blueprints
137
+ logger.trace(f"blueprints_to_remove: {list(blueprints_to_remove)}")
138
+ if len(blueprints_to_remove) > 0:
139
+ for bp in blueprints_to_remove:
140
+ egeria_client.detach_solution_component_from_blueprint(bp, guid, None)
141
+ msg = f"Removed `{display_name}` from blueprintt `{bp}`"
142
+ logger.trace(msg)
143
+
144
+ blueprints_to_add = to_be_blueprints - as_is_blueprints
145
+ logger.trace(f"blueprints_to_add: {list(blueprints_to_add)}")
146
+ if len(blueprints_to_add) > 0:
147
+ for bp in blueprints_to_add:
148
+ egeria_client.link_solution_component_to_blueprint(bp, guid, None)
149
+ msg = f"Added `{display_name}` to component `{bp}`"
150
+ logger.trace(msg)
151
+
152
+
153
+
154
+ actors_to_remove = to_be_actors - as_is_actors
155
+ logger.trace(f"actors_to_remove: {list(actors_to_remove)}")
156
+ if len(actors_to_remove) > 0:
157
+ for actor in actors_to_remove:
158
+ egeria_client.detach_component_actore(actor, guid, None)
159
+ msg = f"Removed actor `{actor}` from component `{display_name}`"
160
+ logger.trace(msg)
161
+
162
+ actors_to_add = to_be_actors - as_is_actors
163
+ logger.trace(f"actors_to_add: {list(actors_to_add)}")
164
+ if len(actors_to_add) > 0:
165
+ for actor in actors_to_add:
166
+ egeria_client.link_component_to_actor(actor, guid, None)
167
+ msg = f"Added `{display_name}` to role `{actor}`"
168
+ logger.trace(msg)
169
+
170
+ supply_chains_to_remove = as_is_supply_chains - to_be_supply_chains
171
+ logger.trace(f"supply_chains_to_remove: {list(supply_chains_to_remove)}")
172
+ if len(supply_chains_to_remove) > 0:
173
+ for isc in supply_chains_to_remove:
174
+ egeria_client.detach_design_from_implementation(isc, guid)
175
+ msg = f"Removed `{isc}` from `{display_name}`"
176
+ logger.trace(msg)
177
+ supply_chains_to_add = to_be_supply_chains - as_is_supply_chains
178
+ logger.trace(f"supply_chains_to_add: {list(supply_chains_to_add)}")
179
+ if len(supply_chains_to_add) > 0:
180
+ body = {
181
+ "class": "NewRelationshipRequestBody",
182
+ "properties": {
183
+ "class": "ImplementedByProperties",
184
+ "description": "a blank description to satisfy the Egeria gods"
185
+ }
186
+ }
187
+ for isc in supply_chains_to_add:
188
+ egeria_client.link_design_to_implementation(isc, guid, body)
189
+ msg = f"Added `{isc}` to`{display_name}`"
190
+ logger.trace(msg)
191
+ logger.info(f"Replaced the related elements in `{display_name}`")
192
+
193
+ else: # merge - add field to related elements
194
+ if parent_component_guids:
195
+ for comp in parent_component_guids:
196
+ egeria_client.link_subcomponent(guid, comp, None)
197
+ msg = f"Added `{parent_component_guids}` to `{display_name}`"
198
+ logger.trace(msg)
199
+
200
+ if actor_guids:
201
+ for actor in actor_guids:
202
+ egeria_client.link_component_to_actor(actor, guid, None)
203
+ msg = f"Added `{actor_guids}` to `{display_name}`"
204
+ logger.trace(msg)
205
+
206
+ if in_blueprint_guids:
207
+ for bp in in_blueprint_guids:
208
+ egeria_client.link_solution_component_to_blueprint(bp, guid, None)
209
+ msg = f"Added `{in_blueprint_guids}` to `{display_name}`"
210
+ logger.trace(msg)
211
+
212
+ if keywords:
213
+ add_search_keywords(egeria_client, guid, keywords)
214
+
215
+ if supply_chain_guids:
216
+ body = {
217
+ "class": "NewRelationshipRequestBody",
218
+ "properties": {
219
+ "class": "ImplementedByProperties",
220
+ "description": "a blank description to satisfy the Egeria gods"
221
+ }
222
+ }
223
+ for isc in supply_chain_guids:
224
+ egeria_client.link_design_to_implementation(isc, guid, body)
225
+ msg = f"Added `{display_name}` to `{isc}`"
226
+ logger.trace(msg)
227
+
228
+ logger.info(f"Merged related elements in `{display_name}`")
229
+
230
+
231
+ def sync_blueprint_related_elements(egeria_client: EgeriaTech, object_type: str, component_guids: list, guid: str,
232
+ qualified_name: str, display_name: str, replace_all_props: bool = True) -> None:
233
+ """Sync a blueprints related elements.
234
+
235
+ """
236
+ if replace_all_props:
237
+ bp_element = egeria_client.get_solution_blueprint_by_guid(guid)
238
+ solution_components = bp_element['solutionComponents']
239
+ as_is_components = {}
240
+ if len(solution_components) > 0:
241
+ for component in solution_components:
242
+ as_is_components.append(component['elementHeader']['guid'])
243
+
244
+ # should I throw an exception if empty?
245
+
246
+ to_be_components = set(component_guids) if component_guids is not None else set()
247
+
248
+ logger.trace(f"as_is_components: {list(as_is_components)} to_be_sub_components: {list(to_be_components)}")
249
+
250
+ components_to_remove = as_is_components - to_be_components
251
+ logger.trace(f"components_to_remove: {list(components_to_remove)}")
252
+ if len(components_to_remove) > 0:
253
+ for ds in components_to_remove:
254
+ egeria_client.detach_solution_component_from_blueprint(guid, ds, None)
255
+ msg = f"Removed `{ds}` from component `{display_name}`"
256
+ logger.trace(msg)
257
+ components_to_add = to_be_components - as_is_components
258
+ logger.trace(f"sub_components_to_add: {list(components_to_add)}")
259
+ if len(components_to_add) > 0:
260
+ for ds in components_to_add:
261
+ egeria_client.link_solution_component_to_blueprint(guid, ds, None)
262
+ msg = f"Added `{ds}` to component `{display_name}`"
263
+ logger.trace(msg)
264
+
265
+ logger.info(f"Replaced the related elements in `{display_name}`")
266
+
267
+ else: # merge - add field to related elements
268
+ if component_guids:
269
+ for comp in component_guids:
270
+ egeria_client.link_solution_component_to_blueprint(guid, comp, None)
271
+ msg = f"Added `{component_guids}` to `{display_name}`"
272
+ logger.trace(msg)
273
+
274
+ logger.info(f"Merged related elements in `{display_name}`")
275
+
276
+
277
+ @logger.catch
278
+ def process_blueprint_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
279
+ """
280
+ Processes a solution blueprint create or update object_action by extracting key attributes such as
281
+ blueprint name, description, and usage from the given text.
282
+
283
+ :param txt: A string representing the input cell to be processed for
284
+ extracting blueprint-related attributes.
285
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
286
+ :return: A string summarizing the outcome of the processing.
287
+ """
288
+ command, object_type, object_action = extract_command_plus(txt)
289
+ print(Markdown(f"# {command}\n"))
290
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
291
+
292
+ valid = parsed_output['valid']
293
+ exists = parsed_output['exists']
294
+
295
+ qualified_name = parsed_output.get('qualified_name', None)
296
+ guid = parsed_output.get('guid', None)
297
+ journal_entry = parsed_output.get('Journey Entry', {}.get('value', None))
298
+ print(Markdown(parsed_output['display']))
299
+
300
+ logger.debug(json.dumps(parsed_output, indent=4))
301
+
302
+ attributes = parsed_output['attributes']
303
+ description = attributes.get('Description', {}).get('value', None)
304
+ display_name = attributes['Display Name'].get('value', None)
305
+ search_keywords = attributes['Search Keywords'].get('value', None)
306
+
307
+
308
+
309
+ component_guids = attributes.get('Solution Components', {}).get('guid_list', None)
310
+
311
+ status = attributes.get('Status', {}).get('value', None)
312
+ if status is None:
313
+ status = "ACTIVE"
314
+
315
+ replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
316
+
317
+ if directive == "display":
318
+
319
+ return None
320
+ elif directive == "validate":
321
+ if valid:
322
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
323
+ else:
324
+ msg = f"Validation failed for object_action `{command}`\n"
325
+ return valid
326
+
327
+ elif directive == "process":
328
+ prop_body = set_element_prop_body(object_type, qualified_name, attributes)
329
+
330
+ try:
331
+ if object_action == "Update":
332
+ if not exists:
333
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
334
+ f"object_action\n")
335
+ logger.error(msg)
336
+ print(Markdown(msg))
337
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
338
+ elif not valid:
339
+ return None
340
+ else:
341
+ print(Markdown(
342
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
343
+
344
+ body = set_update_body(object_type, attributes)
345
+ body['properties'] = prop_body
346
+ egeria_client.update_solution_blueprint(guid, body)
347
+ if status:
348
+ egeria_client.update_solution_element_status(guid, status)
349
+
350
+ msg = f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___"
351
+ update_element_dictionary(qualified_name, {
352
+ 'guid': guid, 'display_name': display_name
353
+ })
354
+ logger.success(msg)
355
+ sync_blueprint_related_elements(egeria_client, object_type, component_guids, guid, qualified_name,
356
+ display_name, replace_all_props)
357
+
358
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name, journal_entry)
359
+ logger.success(f"===> Updated {object_type} `{display_name}` related elements\n\n")
360
+ return egeria_client.get_solution_blueprints_by_name(qualified_name, output_format='MD', report_spec = "Solution-Blueprint-DrE")
361
+
362
+
363
+ elif object_action == "Create":
364
+ print(f"valid: {valid}, type: {type(valid)}")
365
+ try:
366
+ if valid is False and exists:
367
+ msg = (f" Data Specification `{display_name}` already exists and result document updated changing "
368
+ f"`Create` to `Update` in processed output\n\n___")
369
+ logger.error(msg)
370
+ print(Markdown(msg))
371
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
372
+
373
+ elif not valid:
374
+ msg = (f"==>{object_type} `{display_name}` is not valid and can't be created")
375
+ print(Markdown(msg))
376
+ logger.error(msg)
377
+ return
378
+
379
+ else:
380
+ body = set_create_body(object_type,attributes)
381
+ body['properties'] = prop_body
382
+ guid = egeria_client.create_solution_blueprint(body)
383
+ except Exception as e:
384
+ print(f"Unexpected error: {e}, {type(valid)}, {valid}")
385
+
386
+
387
+ if guid:
388
+ update_element_dictionary(qualified_name, {
389
+ 'guid': guid, 'display_name': display_name
390
+ })
391
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name, journal_entry)
392
+ msg = f"\n\nCreated Element `{display_name}` with GUID {guid}\n\n___"
393
+ print(Markdown(msg))
394
+ logger.success(msg)
395
+ return egeria_client.get_solution_blueprint_by_guid(guid, output_format='MD', report_spec = "Solution-Blueprint-DrE")
396
+ else:
397
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
398
+ print(Markdown(msg))
399
+ logger.error(msg)
400
+ return None
401
+
402
+ except PyegeriaException as e:
403
+ print_basic_exception(e)
404
+ logger.error(f"Error performing {command}: {e}")
405
+ return None
406
+ else:
407
+ return None
408
+
409
+
410
+ # TODO - I think this comes after (or part of) doing the Actors
411
+ @logger.catch
412
+ def process_solution_roles_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
413
+ """
414
+ Processes a solution role create or update object_action by extracting key attributes such as from the given text.
415
+
416
+ :param txt: A string representing the input cell to be processed for
417
+ extracting blueprint-related attributes.
418
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
419
+ :return: A string summarizing the outcome of the processing.
420
+ """
421
+ command, object_type, object_action = extract_command_plus(txt)
422
+ print(Markdown(f"# {command}\n"))
423
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
424
+
425
+ valid = parsed_output['valid']
426
+ exists = parsed_output['exists']
427
+
428
+ qualified_name = parsed_output.get('qualified_name', None)
429
+ guid = parsed_output.get('guid', None)
430
+ journal_entry = parsed_output.get('Journey Entry', {}.get('value', None))
431
+ print(Markdown(parsed_output['display']))
432
+
433
+ logger.debug(json.dumps(parsed_output, indent=4))
434
+
435
+ attributes = parsed_output['attributes']
436
+ description = attributes.get('Description', {}).get('value', None)
437
+ display_name = attributes['Display Name'].get('value', None)
438
+ search_keywords = attributes['Search Keywords'].get('value', None)
439
+
440
+
441
+
442
+ component_guids = attributes.get('Solution Components', {}).get('guid_list', None)
443
+
444
+ status = attributes.get('Status', {}).get('value', None)
445
+ if status is None:
446
+ status = "ACTIVE"
447
+
448
+ replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
449
+
450
+ if directive == "display":
451
+
452
+ return None
453
+ elif directive == "validate":
454
+ if valid:
455
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
456
+ else:
457
+ msg = f"Validation failed for object_action `{command}`\n"
458
+ return valid
459
+
460
+ elif directive == "process":
461
+ prop_body = set_element_prop_body(object_type, qualified_name, attributes)
462
+
463
+ try:
464
+ if object_action == "Update":
465
+ if not exists:
466
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
467
+ f"object_action\n")
468
+ logger.error(msg)
469
+ print(Markdown(msg))
470
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
471
+ elif not valid:
472
+ return None
473
+ else:
474
+ print(Markdown(
475
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
476
+
477
+ body = set_update_body(object_type, attributes)
478
+ body['properties'] = prop_body
479
+ egeria_client.update_solution_blueprint(guid, body)
480
+ if status:
481
+ egeria_client.update_solution_element_status(guid, status)
482
+
483
+ msg = f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___"
484
+ update_element_dictionary(qualified_name, {
485
+ 'guid': guid, 'display_name': display_name
486
+ })
487
+ logger.success(msg)
488
+ sync_blueprint_related_elements(egeria_client, object_type, component_guids, guid, qualified_name,
489
+ display_name, replace_all_props)
490
+
491
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name, journal_entry)
492
+ logger.success(f"===> Updated {object_type} `{display_name}` related elements\n\n")
493
+ return egeria_client.get_solution_blueprints_by_name(qualified_name, output_format='MD', report_spec = "Solution-Blueprint-DrE")
494
+
495
+
496
+ elif object_action == "Create":
497
+ print(f"valid: {valid}, type: {type(valid)}")
498
+ try:
499
+ if valid is False and exists:
500
+ msg = (f" Data Specification `{display_name}` already exists and result document updated changing "
501
+ f"`Create` to `Update` in processed output\n\n___")
502
+ logger.error(msg)
503
+ print(Markdown(msg))
504
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
505
+
506
+ elif not valid:
507
+ msg = (f"==>{object_type} `{display_name}` is not valid and can't be created")
508
+ print(Markdown(msg))
509
+ logger.error(msg)
510
+ return
511
+
512
+ else:
513
+ body = set_create_body(object_type,attributes)
514
+ body['properties'] = prop_body
515
+ guid = egeria_client.create_solution_blueprint(body)
516
+ except Exception as e:
517
+ print(f"Unexpected error: {e}, {type(valid)}, {valid}")
518
+
519
+
520
+ if guid:
521
+ update_element_dictionary(qualified_name, {
522
+ 'guid': guid, 'display_name': display_name
523
+ })
524
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name, journal_entry)
525
+ msg = f"\n\nCreated Element `{display_name}` with GUID {guid}\n\n___"
526
+ print(Markdown(msg))
527
+ logger.success(msg)
528
+ return egeria_client.get_solution_blueprint_by_guid(guid, output_format='MD', report_spec = "Solution-Blueprint-DrE")
529
+ else:
530
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
531
+ print(Markdown(msg))
532
+ logger.error(msg)
533
+ return None
534
+
535
+ except PyegeriaException as e:
536
+ print_basic_exception(e)
537
+ logger.error(f"Error performing {command}: {e}")
538
+ return None
539
+ else:
540
+ return None
541
+
542
+
543
+
544
+
545
+ @logger.catch
546
+ def process_solution_component_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> \
547
+ Optional[str]:
548
+ """
549
+ Processes a solution component create or update object_action by extracting key attributes such as
550
+ component name, description, and parent components from the given text.
551
+
552
+ :param txt: A string representing the input cell to be processed for
553
+ extracting component-related attributes.
554
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
555
+ :return: A string summarizing the outcome of the processing.
556
+ """
557
+ command, object_type, object_action = extract_command_plus(txt)
558
+ print(Markdown(f"# {command}\n"))
559
+
560
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
561
+
562
+ valid = parsed_output['valid']
563
+ exists = parsed_output['exists']
564
+
565
+ qualified_name = parsed_output.get('qualified_name', None)
566
+ guid = parsed_output.get('guid', None)
567
+
568
+ print(Markdown(parsed_output['display']))
569
+
570
+ logger.debug(json.dumps(parsed_output, indent=4))
571
+
572
+ attributes = parsed_output['attributes']
573
+
574
+ description = attributes.get('Description', {}).get('value', None)
575
+ display_name = attributes['Display Name'].get('value', None)
576
+ version_identifier = attributes.get('Version Identifier', {}).get('value', None)
577
+ solution_component_type = attributes.get('Solution Component Type', {}).get('value', None)
578
+ planned_deployed_impl_type = attributes.get('Planned Deployed Implementation Type', {}).get('value', None)
579
+ initial_status = attributes.get('Status', {}).get('value', None)
580
+ url = attributes.get('URL', {}).get('value', None)
581
+ search_keywords = attributes.get('Search Keywords', {}).get('value', None)
582
+ journal_entry = attributes.get('Journal Entry', {}).get('value', None)
583
+ user_defined_status = attributes.get('User Defined Status', {}).get('value', None)
584
+ if initial_status != "OTHER":
585
+ user_defined_status = None
586
+
587
+ # sub_component_names = attributes.get('Solution SubComponents', {}).get('name_list', None)
588
+ # sub_component_guids = attributes.get('Solution SubComponents', {}).get('guid_list', None)
589
+ actor_names = attributes.get('Actors', {}).get('name_list', None)
590
+ actor_guids = attributes.get('Actors', {}).get('guid_list', None)
591
+ in_blueprint_names = attributes.get('In Solution Blueprints', {}).get('name_list', None)
592
+ in_blueprint_guids = attributes.get('In Solution Blueprints', {}).get('guid_list', None)
593
+ in_supply_chain_names = attributes.get('In Information Supply Chains', {}).get('name_list', None)
594
+ in_supply_chain_guids = attributes.get('In Information Supply Chains', {}).get('guid_list', None)
595
+ in_component_names = attributes.get('In Solution Components', {}).get('name_list', None)
596
+ in_component_guids = attributes.get('In Solution Components', {}).get('guid_list', None)
597
+ parent_component_guids = attributes.get('Parent Components', {}).get('guid_list', None)
598
+ parent_component_names = attributes.get('Parent Components', {}).get('name_list', None)
599
+
600
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
601
+ effective_from = attributes.get('Effective From', {}).get('value', None)
602
+ effective_to = attributes.get('Effective To', {}).get('value', None)
603
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
604
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
605
+
606
+ anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
607
+ parent_guid = attributes.get('Parent ID', {}).get('guid', None)
608
+ parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
609
+ parent_relationship_properties = attributes.get('Parent Relationship Properties', {}).get('value', None)
610
+ parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
611
+
612
+ anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
613
+ is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
614
+ if parent_guid is None:
615
+ is_own_anchor = True
616
+
617
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
618
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
619
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
620
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
621
+
622
+ merge_update = attributes.get('Merge Update', {}).get('value', True)
623
+
624
+
625
+
626
+ if directive == "display":
627
+
628
+ return None
629
+ elif directive == "validate":
630
+ if valid:
631
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
632
+ else:
633
+ msg = f"Validation failed for object_action `{command}`\n"
634
+ return valid
635
+
636
+ elif directive == "process":
637
+ try:
638
+ if object_action == "Update":
639
+ if not exists:
640
+ msg = (f"==> Element `{display_name}` does not exist! Updating result document with Create."
641
+ f"object_action\n")
642
+ logger.error(msg)
643
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
644
+ elif not valid:
645
+ logger.error(f"==> Element `{display_name}` entry is not valid. Please refer to the errors above.")
646
+ return None
647
+ else:
648
+ print(Markdown(
649
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
650
+
651
+ body = body_slimmer({
652
+ "class": "UpdateElementRequestBody",
653
+ "externalSourceGUID": external_source_guid,
654
+ "externalSourceName": external_source_name,
655
+ "effectiveTime": effective_time,
656
+ "mergeUpdate": merge_update,
657
+ "forLineage": False,
658
+ "forDuplicateProcessing": False,
659
+ "properties": {
660
+ "class": "SolutionComponentProperties",
661
+ "qualifiedName": qualified_name,
662
+ "displayName": display_name,
663
+ "description": description,
664
+ "solutionComponentType": solution_component_type,
665
+ "plannedDeployedImplementationType": planned_deployed_impl_type,
666
+ "additionalProperties": additional_properties,
667
+ "extendedProperties": extended_properties,
668
+ "effectiveFrom": effective_from,
669
+ "effectiveTo": effective_to,
670
+ "URL": url
671
+ }
672
+ })
673
+
674
+ egeria_client.update_solution_component(guid, body)
675
+ msg = f"\n==>Updated {object_type} `{display_name}` with GUID {guid}\n"
676
+ logger.success(msg)
677
+ print(Markdown(msg))
678
+ update_element_dictionary(qualified_name, {
679
+ 'guid': guid, 'display_name': display_name
680
+ })
681
+ # Sync Parent Components and Blueprints
682
+ sync_component_related_elements(egeria_client, object_type ,
683
+ in_supply_chain_guids,parent_component_guids,actor_guids,
684
+ in_blueprint_guids, search_keywords, guid, qualified_name,
685
+ display_name,
686
+ merge_update)
687
+
688
+ if journal_entry:
689
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name, journal_entry)
690
+ return egeria_client.get_solution_component_by_guid(guid, output_format='MD', report_spec = "Solution-Component-DrE")
691
+
692
+
693
+ elif object_action == "Create":
694
+ if valid is False and exists:
695
+ msg = (f" {object_type} `{display_name}` already exists and result document updated changing "
696
+ f"`Create` to `Update` in processed output\n\n___")
697
+ logger.error(msg)
698
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
699
+
700
+ elif not valid:
701
+ msg = (f"==>{object_type} `{display_name}` is not valid and can't be created")
702
+ logger.error(msg)
703
+ return
704
+
705
+ else:
706
+ body = body_slimmer({
707
+ "class": "NewElementRequestBody",
708
+ "anchorGUID": anchor_guid,
709
+ "isOwnAnchor": is_own_anchor,
710
+ "parentGUID": parent_guid,
711
+ "parentRelationshipTypeName": parent_relationship_type_name,
712
+ "parentRelationshipProperties": parent_relationship_properties,
713
+ "parentAtEnd1": parent_at_end1,
714
+ "properties": {
715
+ "class": "SolutionComponentProperties",
716
+ "qualifiedName": qualified_name,
717
+ "displayName": display_name,
718
+ "description": description,
719
+ "solutionComponentType": solution_component_type,
720
+ "versionIdentifier" : version_identifier,
721
+ "plannedDeployedImplementationType": planned_deployed_impl_type,
722
+ "userDefinedStatus" : user_defined_status,
723
+ "additionalProperties": additional_properties,
724
+ "extendedProperties": extended_properties,
725
+ "effectiveFrom": effective_from,
726
+ "effectiveTo": effective_to,
727
+ "URL": url
728
+ },
729
+ "initialStatus": initial_status,
730
+ "externalSourceGUID": external_source_guid,
731
+ "externalSourceName": external_source_name,
732
+ "effectiveTime": effective_time,
733
+ "forLineage": False,
734
+ "forDuplicateProcessing": False
735
+ })
736
+
737
+ guid = egeria_client.create_solution_component(body)
738
+ if guid:
739
+ update_element_dictionary(qualified_name, {
740
+ 'guid': guid, 'display_name': display_name
741
+ })
742
+ msg = f"\n\n==> Created Element `{display_name}` with GUID {guid}\n\n___"
743
+ logger.success(msg)
744
+ print(Markdown(msg))
745
+
746
+ if search_keywords:
747
+ add_search_keywords(egeria_client, guid, search_keywords)
748
+
749
+ if in_component_guids:
750
+ for comp in in_component_guids:
751
+ egeria_client.link_subcomponent(comp, guid, None)
752
+ msg = f"Added to parent components `{in_component_names}` "
753
+ logger.trace(msg)
754
+
755
+ if actor_guids:
756
+ for actor in actor_guids:
757
+ egeria_client.link_component_to_actor(actor, guid, None)
758
+ msg = f"Added `{actor_guids}` to `{display_name}`"
759
+ logger.trace(msg)
760
+
761
+ if in_blueprint_guids:
762
+ for bp in in_blueprint_guids:
763
+ egeria_client.link_solution_component_to_blueprint(bp, guid, None)
764
+ msg = f"Added `{display_name}`to blueprints `{in_blueprint_names}`"
765
+ logger.trace(msg)
766
+
767
+ if in_supply_chain_guids:
768
+ for isc in in_supply_chain_guids:
769
+ egeria_client.link_design_to_implementation(isc, guid, None)
770
+ msg = f"Added `{display_name}`to supply chain `{in_supply_chain_names}`"
771
+ logger.trace(msg)
772
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name,
773
+ journal_entry)
774
+
775
+ return egeria_client.get_solution_component_by_guid(guid, output_format='MD')
776
+ else:
777
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
778
+ logger.error(msg)
779
+ return None
780
+
781
+ except Exception as e:
782
+ logger.error(f"Error performing {command}: {e}")
783
+ return None
784
+ else:
785
+ return None
786
+
787
+
788
+ @logger.catch
789
+ def process_component_link_unlink_command(egeria_client: EgeriaTech, txt: str,
790
+ directive: str = "display") -> Optional[str]:
791
+ """
792
+ Processes a link or unlink command to wire solution components.
793
+
794
+ :param txt: A string representing the input cell to be processed for
795
+ extracting blueprint-related attributes.
796
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
797
+ :return: A string summarizing the outcome of the processing.
798
+ """
799
+ command, object_type, object_action = extract_command_plus(txt)
800
+ print(Markdown(f"# {command}\n"))
801
+
802
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
803
+
804
+ print(Markdown(parsed_output['display']))
805
+
806
+ logger.debug(json.dumps(parsed_output, indent=4))
807
+
808
+ attributes = parsed_output['attributes']
809
+
810
+ component1 = attributes.get('Component1', {}).get('guid', None)
811
+ component2 = attributes.get('Component2', {}).get('guid', None)
812
+ label = attributes.get('Wire Label', {}).get('value', None)
813
+ description = attributes.get('Description', {}).get('value', None)
814
+
815
+ valid = parsed_output['valid']
816
+ exists = component1 is not None and component2 is not None
817
+
818
+
819
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
820
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
821
+
822
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
823
+ effective_from = attributes.get('Effective From', {}).get('value', None)
824
+ effective_to = attributes.get('Effective To', {}).get('value', None)
825
+
826
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
827
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
828
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
829
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
830
+
831
+ if directive == "display":
832
+
833
+ return None
834
+ elif directive == "validate":
835
+ if valid:
836
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
837
+ else:
838
+ msg = f"Validation failed for object_action `{command}`\n"
839
+ return valid
840
+
841
+ elif directive == "process":
842
+ try:
843
+ if object_action == "Unlink":
844
+ if not exists:
845
+ msg = (f" Link `{label}` does not exist! Updating result document with Link "
846
+ f"object_action\n")
847
+ logger.error(msg)
848
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
849
+ return out
850
+ elif not valid:
851
+ return None
852
+ else:
853
+ print(Markdown(
854
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
855
+
856
+ body = body_slimmer({
857
+ "class": "MetadataSourceRequestBody",
858
+ "externalSourceGUID": external_source_guid,
859
+ "externalSourceName": external_source_name,
860
+ "effectiveTime": effective_time,
861
+ "forLineage": False,
862
+ "forDuplicateProcessing": False
863
+ })
864
+
865
+ egeria_client.detach_solution_linking_wire(component1, component2, body)
866
+
867
+ logger.success(f"===> Detached segment with {label} from `{component1}`to {component2}\n")
868
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
869
+
870
+ return (out)
871
+
872
+
873
+ elif object_action == "Link":
874
+ if valid is False and exists:
875
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
876
+ f"`Link` to `Detach` in processed output\n")
877
+ logger.error(msg)
878
+
879
+ elif valid is False:
880
+ msg = f"==>{object_type} Link with label `{label}` is not valid and can't be created"
881
+ logger.error(msg)
882
+ return
883
+ else:
884
+ body = {
885
+ "class": "NewRelationshipRequestBody",
886
+ "effectiveTime": effective_time,
887
+ "forLineage": False,
888
+ "forDuplicateProcessing": False,
889
+ "properties": {
890
+ "class": "SolutionLinkingWireProperties",
891
+ "label": label,
892
+ "description": description,
893
+ "effectiveFrom": effective_from,
894
+ "effectiveTo": effective_to
895
+ }
896
+ }
897
+
898
+ egeria_client.link_solution_linking_wire(component1, component2, body)
899
+ msg = f"==>Created {object_type} link named `{label}`\n"
900
+ logger.success(msg)
901
+ print(Markdown(msg))
902
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
903
+ return out
904
+
905
+ except Exception as e:
906
+ logger.error(f"Error performing {command}: {e}")
907
+ return None
908
+ else:
909
+ return None
910
+
911
+
912
+
913
+ @logger.catch
914
+ def process_information_supply_chain_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") \
915
+ -> \
916
+ Optional[str]:
917
+ """
918
+ Processes a solution blueprint create or update object_action by extracting key attributes such as
919
+ blueprint name, description, and usage from the given text.
920
+
921
+ :param txt: A string representing the input cell to be processed for
922
+ extracting blueprint-related attributes.
923
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
924
+ :return: A string summarizing the outcome of the processing.
925
+ """
926
+ command, object_type, object_action = extract_command_plus(txt)
927
+ print(Markdown(f"# {command}\n"))
928
+
929
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
930
+
931
+ valid = parsed_output['valid']
932
+ exists = parsed_output['exists']
933
+
934
+ qualified_name = parsed_output.get('qualified_name', None)
935
+ guid = parsed_output.get('guid', None)
936
+
937
+ print(Markdown(parsed_output['display']))
938
+
939
+ logger.debug(json.dumps(parsed_output, indent=4))
940
+
941
+ attributes = parsed_output['attributes']
942
+ description = attributes.get('Description', {}).get('value', None)
943
+ display_name = attributes['Display Name'].get('value', None)
944
+ version_identifier = attributes.get('Version Identifier', {}).get('value', None)
945
+ journal_entry = attributes.get('Journal Entry', {}).get('value', None)
946
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
947
+ effective_from = attributes.get('Effective From', {}).get('value', None)
948
+ effective_to = attributes.get('Effective To', {}).get('value', None)
949
+
950
+ nested_supply_chain_guids = attributes.get('Nested Information Supply Chains', {}).get('guid_list', None)
951
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
952
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
953
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
954
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
955
+
956
+ scope = attributes.get('Scope', {}).get('value', None)
957
+ purposes = attributes.get('Purposes', {}).get('value', None)
958
+ in_supply_chain_guids = attributes.get('In Information Supply Chain', {}).get('guid_list', None)
959
+ merge_update = attributes.get('Merge Update', {}).get('value', True),
960
+
961
+
962
+ if directive == "display":
963
+
964
+ return None
965
+ elif directive == "validate":
966
+ if valid:
967
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
968
+ else:
969
+ msg = f"Validation failed for object_action `{command}`\n"
970
+ return valid
971
+
972
+ elif directive == "process":
973
+ try:
974
+ prop_body = {
975
+ "class": "InformationSupplyChainProperties", "effectiveFrom": effective_from,
976
+ "effectiveTo": effective_to, "extendedProperties": extended_properties,
977
+ "qualifiedName": qualified_name, "additionalProperties": additional_properties,
978
+ "displayName": display_name, "description": description, "scope": scope,
979
+ "purposes": purposes, "version": version_identifier
980
+ }
981
+
982
+ if object_action == "Update":
983
+ if not exists:
984
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
985
+ f"object_action\n")
986
+ logger.error(msg)
987
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
988
+ elif not valid:
989
+ return None
990
+ else:
991
+ print(Markdown(
992
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
993
+
994
+
995
+ body = set_update_body("InformationSupplyChain", attributes)
996
+ body['properties'] = prop_body
997
+ egeria_client.update_info_supply_chain(guid, body)
998
+
999
+ sync_chain_related_elements(egeria_client, guid, in_supply_chain_guids, display_name, merge_update)
1000
+ logger.success(f"==> Updated {object_type} `{display_name}` with GUID {guid}\n\n")
1001
+ update_element_dictionary(qualified_name, {
1002
+ 'guid': guid, 'display_name': display_name
1003
+ })
1004
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name, journal_entry)
1005
+
1006
+ logger.success(f"===> Updated {object_type} `{display_name}` related elements\n\n")
1007
+ return egeria_client.get_info_supply_chain_by_guid(guid, output_format='MD', report_spec = "Information-Supply-Chain-DrE")
1008
+
1009
+
1010
+ elif object_action == "Create":
1011
+ if valid is False and exists:
1012
+ msg = (
1013
+ f"--> Data Specification `{display_name}` already exists and result document updated changing "
1014
+ f"`Create` to `Update` in processed output\n")
1015
+ logger.error(msg)
1016
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
1017
+
1018
+ elif valid is False:
1019
+ msg = f"==>{object_type} `{display_name}` is not valid and can't be created"
1020
+ logger.error(msg)
1021
+ return
1022
+ else:
1023
+ body = set_create_body("InformationSupplyChain", attributes)
1024
+ body['properties'] = prop_body
1025
+
1026
+ guid = egeria_client.create_info_supply_chain(body)
1027
+ if guid:
1028
+ msg = f"==>Created Element `{display_name}` with GUID {guid}\n"
1029
+ logger.success(msg)
1030
+ print(Markdown(msg))
1031
+ update_element_dictionary(qualified_name, {
1032
+ 'guid': guid, 'display_name': display_name
1033
+ })
1034
+ if in_supply_chain_guids:
1035
+ for nested_chain in in_supply_chain_guids:
1036
+ egeria_client.compose_info_supply_chains(nested_chain, guid)
1037
+
1038
+ if journal_entry:
1039
+ journal_entry_guid = add_note_in_dr_e(egeria_client, qualified_name, display_name,
1040
+ journal_entry)
1041
+ if nested_supply_chain_guids:
1042
+ for nested_supply_chain in nested_supply_chain_guids:
1043
+ egeria_client.compose_info_supply_chains(guid, nested_supply_chain)
1044
+
1045
+ msg = f"==>Created Element `{display_name}` Relationships\n"
1046
+ logger.success(msg)
1047
+ print(Markdown(msg))
1048
+ return egeria_client.get_info_supply_chain_by_guid(guid, output_format='MD', report_spec="Information-Supply-Chain-DrE")
1049
+ else:
1050
+ msg = f"==>Failed to create element `{display_name}` with GUID {guid}\n"
1051
+ logger.error(msg)
1052
+ return None
1053
+
1054
+ except Exception as e:
1055
+ logger.error(f"Error performing {command}: {e}")
1056
+ return None
1057
+ else:
1058
+ return None
1059
+
1060
+
1061
+
1062
+ @logger.catch
1063
+ def process_information_supply_chain_link_unlink_command(egeria_client: EgeriaTech, txt: str,
1064
+ directive: str = "display") -> Optional[str]:
1065
+ """
1066
+ Processes a link or unlink command to associate or break up peer supply chains..
1067
+
1068
+ :param txt: A string representing the input cell to be processed for
1069
+ extracting blueprint-related attributes.
1070
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
1071
+ :return: A string summarizing the outcome of the processing.
1072
+ """
1073
+ command, object_type, object_action = extract_command_plus(txt)
1074
+ print(Markdown(f"# {command}\n"))
1075
+
1076
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
1077
+
1078
+ print(Markdown(parsed_output['display']))
1079
+
1080
+ logger.debug(json.dumps(parsed_output, indent=4))
1081
+
1082
+ attributes = parsed_output['attributes']
1083
+
1084
+ segment1 = attributes.get('Segment1', {}).get('guid', None)
1085
+ segment2 = attributes.get('Segment2', {}).get('guid', None)
1086
+ label = attributes.get('Link Label', {}).get('value', None)
1087
+ description = attributes.get('Description', {}).get('value', None)
1088
+
1089
+ valid = parsed_output['valid']
1090
+ exists = segment1 is not None and segment2 is not None
1091
+
1092
+
1093
+ external_source_guid = attributes.get('External Source GUID', {}).get('value', None)
1094
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
1095
+
1096
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
1097
+ effective_from = attributes.get('Effective From', {}).get('value', None)
1098
+ effective_to = attributes.get('Effective To', {}).get('value', None)
1099
+
1100
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
1101
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
1102
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
1103
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
1104
+
1105
+ if directive == "display":
1106
+
1107
+ return None
1108
+ elif directive == "validate":
1109
+ if valid:
1110
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
1111
+ else:
1112
+ msg = f"Validation failed for object_action `{command}`\n"
1113
+ return valid
1114
+
1115
+ elif directive == "process":
1116
+ try:
1117
+ if object_action == "Unlink":
1118
+ if not exists:
1119
+ msg = (f" Link `{label}` does not exist! Updating result document with Link "
1120
+ f"object_action\n")
1121
+ logger.error(msg)
1122
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1123
+ return out
1124
+ elif not valid:
1125
+ return None
1126
+ else:
1127
+ print(Markdown(
1128
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
1129
+
1130
+ body = body_slimmer({
1131
+ "class": "DeleteRelationshipRequestBody",
1132
+ "externalSourceGUID": external_source_guid,
1133
+ "externalSourceName": external_source_name,
1134
+ "effectiveTime": effective_time,
1135
+ "forLineage": False,
1136
+ "forDuplicateProcessing": False
1137
+ })
1138
+
1139
+ egeria_client.unlink_peer_info_supply_chains(segment1, segment2, body)
1140
+
1141
+ logger.success(f"===> Detached segment with {label} from `{segment1}`to {segment2}\n")
1142
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
1143
+
1144
+ return (out)
1145
+
1146
+
1147
+ elif object_action == "Link":
1148
+ if valid is False and exists:
1149
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
1150
+ f"`Link` to `Detach` in processed output\n")
1151
+ logger.error(msg)
1152
+
1153
+ elif valid is False:
1154
+ msg = f"==>{object_type} Link with label `{label}` is not valid and can't be created"
1155
+ logger.error(msg)
1156
+ return
1157
+ else:
1158
+ body = {
1159
+ "class": "NewRelationshipRequestBody",
1160
+ "effectiveTime": effective_time,
1161
+ "forLineage": False,
1162
+ "forDuplicateProcessing": False,
1163
+ "properties": {
1164
+ "class": "InformationSupplyChainLinkProperties",
1165
+ "label": label,
1166
+ "description": description,
1167
+ "effectiveFrom": effective_from,
1168
+ "effectiveTo": effective_to
1169
+ }
1170
+ }
1171
+
1172
+ egeria_client.link_peer_info_supply_chains(segment1, segment2, body)
1173
+ msg = f"==>Created {object_type} link named `{label}`\n"
1174
+ logger.success(msg)
1175
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1176
+ return out
1177
+
1178
+
1179
+ except Exception as e:
1180
+ logger.error(f"Error performing {command}: {e}")
1181
+ return None
1182
+ else:
1183
+ return None
1184
+