pyegeria 5.3.10__py3-none-any.whl → 5.4.0__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.
- commands/cat/debug_log +2806 -0
- commands/cat/debug_log.2025-07-15_14-28-38_087378.zip +0 -0
- commands/cat/debug_log.2025-07-16_15-48-50_037087.zip +0 -0
- commands/cat/dr_egeria_command_help.py +273 -0
- commands/cat/dr_egeria_md.py +90 -20
- commands/cat/glossary_actions.py +2 -2
- commands/cat/list_collections.py +24 -10
- commands/cat/list_data_designer.py +183 -0
- md_processing/__init__.py +28 -5
- md_processing/data/commands.json +31474 -1096
- md_processing/dr_egeria_outbox-pycharm/.obsidian/app.json +1 -0
- md_processing/dr_egeria_outbox-pycharm/.obsidian/appearance.json +1 -0
- md_processing/dr_egeria_outbox-pycharm/.obsidian/core-plugins.json +31 -0
- md_processing/dr_egeria_outbox-pycharm/.obsidian/workspace.json +177 -0
- md_processing/dr_egeria_outbox-pycharm/monday/processed-2025-07-14 12:38-data_designer_out.md +663 -0
- md_processing/dr_egeria_outbox-pycharm/thursday/processed-2025-07-17 15:00-Derive-Dr-Gov-Defs.md +719 -0
- md_processing/dr_egeria_outbox-pycharm/thursday/processed-2025-07-17 20:13-Derive-Dr-Gov-Defs.md +41 -0
- md_processing/dr_egeria_outbox-pycharm/thursday/processed-2025-07-17 20:14-Derive-Dr-Gov-Defs.md +33 -0
- md_processing/dr_egeria_outbox-pycharm/thursday/processed-2025-07-17 20:50-Derive-Dr-Gov-Defs.md +192 -0
- md_processing/dr_egeria_outbox-pycharm/tuesday/processed-2025-07-16 19:15-gov_def2.md +527 -0
- md_processing/dr_egeria_outbox-pycharm/tuesday/processed-2025-07-17 12:08-gov_def2.md +527 -0
- md_processing/dr_egeria_outbox-pycharm/tuesday/processed-2025-07-17 14:27-gov_def2.md +474 -0
- md_processing/family_docs/Data Designer/Create_Data_Class.md +164 -0
- md_processing/family_docs/Data Designer/Create_Data_Dictionary.md +30 -0
- md_processing/family_docs/Data Designer/Create_Data_Field.md +162 -0
- md_processing/family_docs/Data Designer/Create_Data_Specification.md +36 -0
- md_processing/family_docs/Data Designer/Create_Data_Structure.md +38 -0
- md_processing/family_docs/Data Designer/View_Data_Classes.md +78 -0
- md_processing/family_docs/Data Designer/View_Data_Dictionaries.md +78 -0
- md_processing/family_docs/Data Designer/View_Data_Fields.md +78 -0
- md_processing/family_docs/Data Designer/View_Data_Specifications.md +78 -0
- md_processing/family_docs/Data Designer/View_Data_Structures.md +78 -0
- md_processing/family_docs/Data Designer.md +842 -0
- md_processing/family_docs/Digital Product Manager/Add_Member->Collection.md +42 -0
- md_processing/family_docs/Digital Product Manager/Attach_Collection->Resource.md +36 -0
- md_processing/family_docs/Digital Product Manager/Create_Agreement.md +96 -0
- md_processing/family_docs/Digital Product Manager/Create_Data_Sharing_Agreement.md +72 -0
- md_processing/family_docs/Digital Product Manager/Create_DigitalSubscription.md +102 -0
- md_processing/family_docs/Digital Product Manager/Create_Digital_Product.md +134 -0
- md_processing/family_docs/Digital Product Manager/Link_Agreement_Items.md +60 -0
- md_processing/family_docs/Digital Product Manager/Link_Contracts.md +26 -0
- md_processing/family_docs/Digital Product Manager/Link_Digital_Product_-_Digital_Product.md +30 -0
- md_processing/family_docs/Digital Product Manager/Link_Subscribers.md +48 -0
- md_processing/family_docs/Digital Product Manager.md +668 -0
- md_processing/family_docs/Glossary/Attach_Category_Parent.md +18 -0
- md_processing/family_docs/Glossary/Attach_Term-Term_Relationship.md +26 -0
- md_processing/family_docs/Glossary/Create_Category.md +38 -0
- md_processing/family_docs/Glossary/Create_Glossary.md +42 -0
- md_processing/family_docs/Glossary/Create_Term.md +70 -0
- md_processing/family_docs/Glossary.md +206 -0
- md_processing/family_docs/Governance Officer/Create_Business_Imperative.md +106 -0
- md_processing/family_docs/Governance Officer/Create_Certification_Type.md +112 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Approach.md +114 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Obligation.md +114 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Principle.md +114 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Procedure.md +128 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Process.md +122 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Processing_Purpose.md +106 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Responsibility.md +122 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Rule.md +122 -0
- md_processing/family_docs/Governance Officer/Create_Governance_Strategy.md +106 -0
- md_processing/family_docs/Governance Officer/Create_License_Type.md +112 -0
- md_processing/family_docs/Governance Officer/Create_Naming_Standard_Rule.md +122 -0
- md_processing/family_docs/Governance Officer/Create_Regulation_Article.md +106 -0
- md_processing/family_docs/Governance Officer/Create_Regulation_Definition.md +118 -0
- md_processing/family_docs/Governance Officer/Create_Security_Access_Control.md +114 -0
- md_processing/family_docs/Governance Officer/Create_Security_Group.md +120 -0
- md_processing/family_docs/Governance Officer/Create_Service_Level_Objectives.md +122 -0
- md_processing/family_docs/Governance Officer/Create_Threat_Definition.md +106 -0
- md_processing/family_docs/Governance Officer/Link_Governance_Controls.md +32 -0
- md_processing/family_docs/Governance Officer/Link_Governance_Drivers.md +32 -0
- md_processing/family_docs/Governance Officer/Link_Governance_Policies.md +32 -0
- md_processing/family_docs/Governance Officer/View_Governance_Definitions.md +82 -0
- md_processing/family_docs/Governance Officer.md +2412 -0
- md_processing/family_docs/Solution Architect/Create_Information_Supply_Chain.md +70 -0
- md_processing/family_docs/Solution Architect/Create_Solution_Blueprint.md +44 -0
- md_processing/family_docs/Solution Architect/Create_Solution_Component.md +96 -0
- md_processing/family_docs/Solution Architect/Create_Solution_Role.md +66 -0
- md_processing/family_docs/Solution Architect/Link_Information_Supply_Chain_Peers.md +32 -0
- md_processing/family_docs/Solution Architect/Link_Solution_Component_Peers.md +32 -0
- md_processing/family_docs/Solution Architect/View_Information_Supply_Chains.md +32 -0
- md_processing/family_docs/Solution Architect/View_Solution_Blueprints.md +32 -0
- md_processing/family_docs/Solution Architect/View_Solution_Components.md +32 -0
- md_processing/family_docs/Solution Architect/View_Solution_Roles.md +32 -0
- md_processing/family_docs/Solution Architect.md +490 -0
- md_processing/md_commands/data_designer_commands.py +1192 -710
- md_processing/md_commands/glossary_commands.py +19 -32
- md_processing/md_commands/governance_officer_commands.py +420 -0
- md_processing/md_commands/product_manager_commands.py +1180 -0
- md_processing/md_commands/project_commands.py +5 -2
- md_processing/md_commands/solution_architect_commands.py +1140 -0
- md_processing/md_processing_utils/common_md_proc_utils.py +288 -96
- md_processing/md_processing_utils/common_md_utils.py +205 -6
- md_processing/md_processing_utils/debug_log +574 -0
- md_processing/md_processing_utils/dr-egeria-help-2025-07-17T17:22:09.md +2065 -0
- md_processing/md_processing_utils/extraction_utils.py +1 -1
- md_processing/md_processing_utils/generate_dr_help.py +165 -0
- md_processing/md_processing_utils/generate_md_cmd_templates.py +143 -0
- md_processing/md_processing_utils/generate_md_templates.py +92 -0
- md_processing/md_processing_utils/generated_help_terms.md +842 -0
- md_processing/md_processing_utils/md_processing_constants.py +94 -17
- pyegeria/__init__.py +1 -0
- pyegeria/_client.py +39 -1
- pyegeria/classification_manager_omvs.py +1 -1
- pyegeria/collection_manager_omvs.py +4667 -1178
- pyegeria/data_designer_omvs.py +348 -31
- pyegeria/egeria_tech_client.py +9 -25
- pyegeria/glossary_browser_omvs.py +5 -6
- pyegeria/glossary_manager_omvs.py +2 -2
- pyegeria/governance_officer_omvs.py +2367 -0
- pyegeria/output_formatter.py +157 -32
- pyegeria/solution_architect_omvs.py +5063 -1110
- pyegeria/utils.py +22 -2
- {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dist-info}/METADATA +3 -1
- pyegeria-5.4.0.dist-info/RECORD +243 -0
- {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dist-info}/entry_points.txt +5 -0
- commands/cat/.DS_Store +0 -0
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
- md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
- md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
- md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
- md_processing/dr_egeria_inbox/cat_test.md +0 -100
- md_processing/dr_egeria_inbox/data_field.md +0 -54
- md_processing/dr_egeria_inbox/data_spec.md +0 -77
- md_processing/dr_egeria_inbox/data_spec_test.md +0 -2406
- md_processing/dr_egeria_inbox/data_test.md +0 -86
- md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
- md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
- md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -313
- md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
- md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
- md_processing/dr_egeria_inbox/glossary_test1.md +0 -324
- md_processing/dr_egeria_inbox/rel.md +0 -8
- md_processing/dr_egeria_inbox/sb.md +0 -119
- md_processing/dr_egeria_inbox/search_test.md +0 -39
- md_processing/dr_egeria_inbox/solution-components.md +0 -154
- md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
- md_processing/dr_egeria_inbox/synonym_test.md +0 -42
- md_processing/dr_egeria_inbox/t1.md +0 -0
- md_processing/dr_egeria_inbox/t2.md +0 -268
- md_processing/dr_egeria_outbox/processed-2025-05-15 19:52-data_test.md +0 -94
- md_processing/dr_egeria_outbox/processed-2025-05-16 07:39-data_test.md +0 -88
- md_processing/dr_egeria_outbox/processed-2025-05-17 16:01-data_field.md +0 -56
- md_processing/dr_egeria_outbox/processed-2025-05-18 15:51-data_test.md +0 -103
- md_processing/dr_egeria_outbox/processed-2025-05-18 16:47-data_test.md +0 -94
- md_processing/dr_egeria_outbox/processed-2025-05-19 07:14-data_test.md +0 -96
- md_processing/dr_egeria_outbox/processed-2025-05-19 07:20-data_test.md +0 -100
- md_processing/dr_egeria_outbox/processed-2025-05-19 07:22-data_test.md +0 -88
- md_processing/dr_egeria_outbox/processed-2025-05-19 09:26-data_test.md +0 -91
- md_processing/dr_egeria_outbox/processed-2025-05-19 10:27-data_test.md +0 -91
- md_processing/dr_egeria_outbox/processed-2025-05-19 14:04-data_test.md +0 -91
- md_processing/md_commands/blueprint_commands.py +0 -303
- pyegeria/.DS_Store +0 -0
- pyegeria/m_test.py +0 -118
- pyegeria-5.3.10.dist-info/RECORD +0 -196
- /commands/cat/{list_data_structures.py → list_data_structures_full.py} +0 -0
- {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dist-info}/LICENSE +0 -0
- {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dist-info}/WHEEL +0 -0
@@ -3,100 +3,409 @@ This file contains term-related object_action functions for processing Egeria Ma
|
|
3
3
|
"""
|
4
4
|
import json
|
5
5
|
import os
|
6
|
+
import sys
|
6
7
|
from typing import Optional
|
7
8
|
|
9
|
+
from loguru import logger
|
8
10
|
from rich import print
|
9
11
|
from rich.console import Console
|
10
12
|
from rich.markdown import Markdown
|
11
13
|
|
12
|
-
from md_processing.md_processing_utils.common_md_proc_utils import (
|
13
|
-
|
14
|
-
|
15
|
-
from md_processing.md_processing_utils.common_md_utils import print_msg, update_element_dictionary
|
16
|
-
from md_processing.md_processing_utils.extraction_utils import (extract_command, extract_command_plus, update_a_command)
|
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, setup_log
|
16
|
+
from md_processing.md_processing_utils.extraction_utils import (extract_command_plus, update_a_command)
|
17
17
|
from md_processing.md_processing_utils.md_processing_constants import (load_commands, ERROR)
|
18
18
|
from pyegeria import DEBUG_LEVEL, body_slimmer
|
19
19
|
from pyegeria.egeria_tech_client import EgeriaTech
|
20
|
-
from pyegeria.md_processing_utils import ALWAYS, INFO
|
21
20
|
|
21
|
+
GERIA_METADATA_STORE = os.environ.get("EGERIA_METADATA_STORE", "active-metadata-store")
|
22
|
+
EGERIA_KAFKA_ENDPOINT = os.environ.get("KAFKA_ENDPOINT", "localhost:9092")
|
23
|
+
EGERIA_PLATFORM_URL = os.environ.get("EGERIA_PLATFORM_URL", "https://localhost:9443")
|
24
|
+
EGERIA_VIEW_SERVER = os.environ.get("EGERIA_VIEW_SERVER", "view-server")
|
25
|
+
EGERIA_VIEW_SERVER_URL = os.environ.get("EGERIA_VIEW_SERVER_URL", "https://localhost:9443")
|
26
|
+
EGERIA_INTEGRATION_DAEMON = os.environ.get("EGERIA_INTEGRATION_DAEMON", "integration-daemon")
|
27
|
+
EGERIA_INTEGRATION_DAEMON_URL = os.environ.get("EGERIA_INTEGRATION_DAEMON_URL", "https://localhost:9443")
|
28
|
+
EGERIA_ADMIN_USER = os.environ.get("ADMIN_USER", "garygeeke")
|
29
|
+
EGERIA_ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "secret")
|
30
|
+
EGERIA_USER = os.environ.get("EGERIA_USER", "erinoverview")
|
31
|
+
EGERIA_USER_PASSWORD = os.environ.get("EGERIA_USER_PASSWORD", "secret")
|
32
|
+
EGERIA_WIDTH = os.environ.get("EGERIA_WIDTH", 220)
|
33
|
+
EGERIA_JUPYTER = os.environ.get("EGERIA_JUPYTER", False)
|
34
|
+
EGERIA_HOME_GLOSSARY_GUID = os.environ.get("EGERIA_HOME_GLOSSARY_GUID", None)
|
35
|
+
EGERIA_GLOSSARY_PATH = os.environ.get("EGERIA_GLOSSARY_PATH", None)
|
36
|
+
EGERIA_ROOT_PATH = os.environ.get("EGERIA_ROOT_PATH", "../../")
|
37
|
+
EGERIA_INBOX_PATH = os.environ.get("EGERIA_INBOX_PATH", "md_processing/dr_egeria_inbox")
|
38
|
+
EGERIA_OUTBOX_PATH = os.environ.get("EGERIA_OUTBOX_PATH", "md_processing/dr_egeria_outbox")
|
22
39
|
|
23
40
|
load_commands('commands.json')
|
24
41
|
debug_level = DEBUG_LEVEL
|
25
42
|
|
26
43
|
console = Console(width=int(200))
|
44
|
+
setup_log()
|
45
|
+
|
27
46
|
|
28
|
-
|
47
|
+
#
|
48
|
+
# Helper functions for the data designer commands
|
49
|
+
#
|
50
|
+
@logger.catch
|
51
|
+
def add_member_to_data_collections(egeria_client: EgeriaTech, collection_list: list, display_name: str,
|
52
|
+
guid: str) -> None:
|
29
53
|
"""
|
30
54
|
Add member to data dictionaries and data specifications.
|
31
55
|
"""
|
56
|
+
body = {
|
57
|
+
"class": "RelationshipRequestBody", "properties": {
|
58
|
+
"class": "CollectionMembershipProperties", "membershipRationale": "User Specified",
|
59
|
+
"notes": "Added by Dr.Egeria"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
try:
|
63
|
+
if collection_list is not None:
|
64
|
+
for collection in collection_list:
|
65
|
+
egeria_client.add_to_collection(collection, guid, body)
|
66
|
+
msg = f"Added `{display_name}` member to `{collection}`"
|
67
|
+
logger.info(msg)
|
68
|
+
else:
|
69
|
+
logger.info("There were no data collections to add.")
|
70
|
+
return
|
71
|
+
|
72
|
+
except Exception as e:
|
73
|
+
console.print_exception()
|
74
|
+
|
75
|
+
|
76
|
+
@logger.catch
|
77
|
+
def remove_member_from_data_collections(egeria_client: EgeriaTech, collection_list: list, display_name: str,
|
78
|
+
guid: str) -> None:
|
32
79
|
try:
|
33
|
-
for collection in
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
egeria_client.add_to_collection(collection_guid, guid)
|
39
|
-
msg = f"Added `{display_name}` member to `{collection_name}`"
|
40
|
-
print_msg(INFO, msg, debug_level)
|
41
|
-
return True
|
80
|
+
for collection in collection_list:
|
81
|
+
egeria_client.remove_from_collection(collection, guid)
|
82
|
+
msg = f"Removed `{display_name}` member from `{collection}`"
|
83
|
+
logger.info(msg)
|
84
|
+
return
|
42
85
|
|
43
86
|
except Exception as e:
|
44
87
|
console.print_exception()
|
45
88
|
|
46
89
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
if coll_type:
|
57
|
-
if coll_type == collection_type:
|
58
|
-
collection_guid_list.append(related_el_guid)
|
59
|
-
print(collection_guid_list)
|
60
|
-
return collection_guid_list
|
90
|
+
@logger.catch
|
91
|
+
def update_data_collection_memberships(egeria_client: EgeriaTech, entity_type: str, guid_list: list,
|
92
|
+
collection_class: str, guid: str, display_name: str,
|
93
|
+
replace_all_props: bool = True) -> None:
|
94
|
+
""" update the collection membership of the element
|
95
|
+
|
96
|
+
If replace_all_props is set to True, all existing memberships are removed and new memberships are added.
|
97
|
+
If replace_all_props is set to False, only the new memberships are added.
|
98
|
+
"""
|
61
99
|
|
100
|
+
if replace_all_props:
|
101
|
+
match entity_type:
|
102
|
+
case "Data Specification":
|
103
|
+
get_command = egeria_client.get_collection_by_guid
|
104
|
+
case "Data Structure":
|
105
|
+
get_command = egeria_client.get_data_structure_by_guid
|
106
|
+
case "Data Field":
|
107
|
+
get_command = egeria_client.get_data_field_by_guid
|
108
|
+
case "Data Class":
|
109
|
+
get_command = egeria_client.get_data_class_by_guid
|
110
|
+
|
111
|
+
coll_list = egeria_client.get_data_memberships(get_command, guid)
|
112
|
+
if coll_list is None:
|
113
|
+
logger.warning("Unexpected -> the collection list was None - assigning empty dict")
|
114
|
+
coll_list = {}
|
115
|
+
# compare the existing collections to desired collections
|
116
|
+
if collection_class == "DataDictionary":
|
117
|
+
as_is = set(coll_list.get("DictList", {}))
|
118
|
+
elif collection_class == "DataSpec":
|
119
|
+
as_is = set(coll_list.get("SpecList", {}))
|
120
|
+
|
121
|
+
dict_set = set(coll_list.get("DictList", {}))
|
122
|
+
spec_set = set(coll_list.get("SpecList", {}))
|
123
|
+
to_be_set = set(guid_list) if guid_list is not None else set()
|
124
|
+
logger.debug(f"as_is: {as_is}")
|
125
|
+
logger.debug(f"to_be_set: {to_be_set}")
|
126
|
+
|
127
|
+
# Remove membership for collections that are in the as-is but not in the to-be
|
128
|
+
to_remove = as_is - to_be_set
|
129
|
+
logger.debug(f"to_remove: {to_remove}")
|
130
|
+
if len(to_remove) > 0:
|
131
|
+
remove_member_from_data_collections(egeria_client, to_remove, display_name, guid)
|
132
|
+
|
133
|
+
# add membership for collections that are in the to-be but are not in the as-is
|
134
|
+
to_add = to_be_set - as_is
|
135
|
+
logger.debug(f"to_add: {to_add}")
|
136
|
+
if len(to_add) > 0:
|
137
|
+
add_member_to_data_collections(egeria_client, to_add, display_name, guid)
|
138
|
+
else:
|
139
|
+
add_member_to_data_collections(egeria_client, guid_list, display_name, guid)
|
62
140
|
|
63
141
|
|
142
|
+
# @logger.catch
|
64
143
|
|
65
|
-
def update_data_collection_memberships(egeria_client: EgeriaTech, in_data_collection:dict, guid: str, replace_all_props:bool = False) -> bool:
|
66
|
-
""" update the collection membership of the element """
|
67
|
-
pass
|
68
144
|
|
145
|
+
@logger.catch
|
146
|
+
def add_field_to_data_structures(egeria_client: EgeriaTech, display_name: str, struct_list: list, guid) -> None:
|
147
|
+
"""
|
148
|
+
Add data field to data structures.
|
149
|
+
"""
|
69
150
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
151
|
+
try:
|
152
|
+
for structure_guid in struct_list:
|
153
|
+
egeria_client.link_member_data_field(structure_guid, guid, None)
|
154
|
+
msg = f"Added `{display_name}` to structure `{structure_guid}`"
|
155
|
+
logger.info(msg)
|
156
|
+
return
|
157
|
+
|
158
|
+
except Exception as e:
|
159
|
+
console.print_exception()
|
160
|
+
|
161
|
+
|
162
|
+
@logger.catch
|
163
|
+
def remove_field_from_data_structures(egeria_client: EgeriaTech, display_name: str, struct_list: list,
|
164
|
+
guid: str) -> None:
|
165
|
+
"""Remove a data field from a list of data structures."""
|
166
|
+
try:
|
167
|
+
for structure_guid in struct_list:
|
168
|
+
egeria_client.detach_member_data_field(structure_guid, guid, None)
|
169
|
+
msg = f"Removed `{display_name}` from structure `{structure_guid}`"
|
170
|
+
logger.info(msg)
|
171
|
+
return
|
172
|
+
|
173
|
+
except Exception as e:
|
174
|
+
console.print_exception()
|
175
|
+
|
176
|
+
|
177
|
+
@logger.catch
|
178
|
+
def sync_data_field_rel_elements(egeria_client: EgeriaTech, structure_list: list, parent_field_list: list, terms: list,
|
179
|
+
data_class_guid: str, guid: str, display_name: str,
|
180
|
+
replace_all_props: bool = True) -> None:
|
181
|
+
"""Sync a field's related elements.
|
98
182
|
|
183
|
+
TODO: Need to add data class support when ready and may need to revisit bodies.
|
184
|
+
|
185
|
+
"""
|
186
|
+
if terms:
|
187
|
+
terms = [terms]
|
188
|
+
|
189
|
+
if replace_all_props:
|
190
|
+
rel_el_list = egeria_client.get_data_field_rel_elements(guid)
|
191
|
+
# should I throw an exception if empty?
|
192
|
+
if rel_el_list is None:
|
193
|
+
logger.warning("Unexpected -> the list was None - assigning empty list")
|
194
|
+
rel_el_list = {}
|
195
|
+
|
196
|
+
as_is_data_structs = set(rel_el_list.get("data_structure_guids", []))
|
197
|
+
as_is_parent_fields = set(rel_el_list.get("parent_guids", []))
|
198
|
+
as_is_assigned_meanings = set(rel_el_list.get("assigned_meanings_guids", []))
|
199
|
+
as_is_data_classes = set(rel_el_list.get("data_class_guids", []))
|
200
|
+
|
201
|
+
to_be_data_structs = set(structure_list) if structure_list is not None else set()
|
202
|
+
to_be_parent_fields = set(parent_field_list) if parent_field_list is not None else set()
|
203
|
+
to_be_assigned_meanings = set(terms) if terms is not None else set()
|
204
|
+
to_be_data_classes = set([data_class_guid]) if data_class_guid is not None else set()
|
205
|
+
|
206
|
+
logger.trace(f"as_is_data_structs: {list(as_is_data_structs)} to_be_data_struct: {list(to_be_data_structs)}")
|
207
|
+
logger.trace(
|
208
|
+
f"as_is_parent_fields: {list(as_is_parent_fields)} to_be_parent_fields: {list(to_be_parent_fields)}")
|
209
|
+
logger.trace(f"as_is_assigned_meanings: {list(as_is_assigned_meanings)} to_be_assigned_meanings: "
|
210
|
+
f"{list(to_be_assigned_meanings)}")
|
211
|
+
logger.trace(f"as_is_data_classes: {list(as_is_data_classes)} to_be_assigned_data_classes: "
|
212
|
+
f"{list(to_be_data_classes)}")
|
213
|
+
|
214
|
+
data_struct_to_remove = as_is_data_structs - to_be_data_structs
|
215
|
+
logger.trace(f"data_struct_to_remove: {list(data_struct_to_remove)}")
|
216
|
+
if len(data_struct_to_remove) > 0:
|
217
|
+
for ds in data_struct_to_remove:
|
218
|
+
egeria_client.detach_member_data_field(ds, guid, None)
|
219
|
+
msg = f"Removed `{display_name}` from structure `{ds}`"
|
220
|
+
logger.trace(msg)
|
221
|
+
data_struct_to_add = to_be_data_structs - as_is_data_structs
|
222
|
+
logger.trace(f"data_struct_to_add: {list(data_struct_to_add)}")
|
223
|
+
if len(data_struct_to_add) > 0:
|
224
|
+
for ds in data_struct_to_add:
|
225
|
+
egeria_client.link_member_data_field(ds, guid, None)
|
226
|
+
msg = f"Added `{display_name}` to structure `{ds}`"
|
227
|
+
logger.trace(msg)
|
228
|
+
|
229
|
+
parent_field_to_remove = to_be_parent_fields - as_is_parent_fields
|
230
|
+
logger.trace(f"parent_field_to_remove: {list(parent_field_to_remove)}")
|
231
|
+
if len(parent_field_to_remove) > 0:
|
232
|
+
for field in parent_field_to_remove:
|
233
|
+
egeria_client.detach_nested_data_field(field, guid, None)
|
234
|
+
msg = f"Removed `{display_name}` from field `{field}`"
|
235
|
+
logger.trace(msg)
|
236
|
+
parent_field_to_add = to_be_parent_fields - as_is_parent_fields
|
237
|
+
logger.trace(f"parent_field_to_add: {list(parent_field_to_add)}")
|
238
|
+
if len(parent_field_to_add) > 0:
|
239
|
+
for field in parent_field_to_add:
|
240
|
+
egeria_client.link_nested_data_field(field, guid, None)
|
241
|
+
msg = f"Added `{display_name}` to field `{field}`"
|
242
|
+
logger.trace(msg)
|
243
|
+
|
244
|
+
terms_to_remove = as_is_assigned_meanings - to_be_assigned_meanings
|
245
|
+
logger.trace(f"terms_to_remove: {list(terms_to_remove)}")
|
246
|
+
if terms:
|
247
|
+
for term in terms_to_remove:
|
248
|
+
egeria_client.detach_semantic_definition(guid, term, None)
|
249
|
+
msg = f"Removed `{term}` from `{display_name}`"
|
250
|
+
logger.trace(msg)
|
251
|
+
terms_to_add = to_be_assigned_meanings - as_is_assigned_meanings
|
252
|
+
logger.trace(f"terms_to_add: {list(terms_to_add)}")
|
253
|
+
if len(terms_to_add) > 0:
|
254
|
+
for term in terms_to_add:
|
255
|
+
egeria_client.link_semantic_definition(guid, term, None)
|
256
|
+
msg = f"Added `{term}` to`{display_name}`"
|
257
|
+
logger.trace(msg)
|
258
|
+
|
259
|
+
classes_to_remove = as_is_data_classes - to_be_data_classes
|
260
|
+
logger.trace(f"classes_to_remove: {list(classes_to_remove)}")
|
261
|
+
if len(terms_to_remove) > 0:
|
262
|
+
for dc in classes_to_remove:
|
263
|
+
body = {
|
264
|
+
"class": "MetadataSourceRequestBody", "forLineage": False, "forDuplicateProcessing": False
|
265
|
+
}
|
266
|
+
egeria_client.detach_data_class_definition(guid, dc, body)
|
267
|
+
msg = f"Removed `{dc}` from `{display_name}`"
|
268
|
+
logger.trace(msg)
|
269
|
+
classes_to_add = to_be_data_classes - as_is_data_classes
|
270
|
+
logger.trace(f"classes_to_add: {list(classes_to_add)}")
|
271
|
+
if len(terms_to_add) > 0:
|
272
|
+
for dc in classes_to_add:
|
273
|
+
body = {
|
274
|
+
"class": "RelationshipRequestBody", "forLineage": False, "forDuplicateProcessing": False
|
275
|
+
}
|
276
|
+
egeria_client.link_data_class_definition(guid, dc, body)
|
277
|
+
msg = f"Added `{dc}` to`{display_name}`"
|
278
|
+
logger.trace(msg)
|
279
|
+
|
280
|
+
|
281
|
+
else: # merge - add field to related elements
|
282
|
+
if structure_list:
|
283
|
+
add_field_to_data_structures(egeria_client, display_name, structure_list, guid)
|
284
|
+
msg = f"Added `{display_name}` to `{structure_list}`"
|
285
|
+
logger.trace(msg)
|
286
|
+
|
287
|
+
if parent_field_list:
|
288
|
+
for field in parent_field_list:
|
289
|
+
egeria_client.link_nested_data_field(field, guid, None)
|
290
|
+
msg = f"Added `{display_name}` to `{field}`"
|
291
|
+
logger.trace(msg)
|
292
|
+
if terms:
|
293
|
+
for term in terms:
|
294
|
+
egeria_client.link_semantic_definition(guid, term, None)
|
295
|
+
msg = f"Added `{term}` to `{display_name}`"
|
296
|
+
logger.trace(msg)
|
297
|
+
|
298
|
+
if data_class_guid:
|
299
|
+
egeria_client.link_data_class_definition(guid, data_class_guid)
|
300
|
+
msg = f"Added `{data_class_guid}` to `{display_name}`"
|
301
|
+
logger.trace(msg)
|
302
|
+
|
303
|
+
|
304
|
+
@logger.catch
|
305
|
+
def sync_data_class_rel_elements(egeria_client: EgeriaTech, containing_data_class_guids: list, terms: list,
|
306
|
+
specializes_data_classes: list, guid: str, display_name: str,
|
307
|
+
replace_all_props: bool = True) -> None:
|
308
|
+
"""Sync a data class' related elements.
|
99
309
|
|
310
|
+
"""
|
311
|
+
if terms:
|
312
|
+
terms = [terms]
|
313
|
+
|
314
|
+
if replace_all_props:
|
315
|
+
rel_el_list = egeria_client.get_data_class_rel_elements(guid)
|
316
|
+
if rel_el_list is None:
|
317
|
+
logger.warning("Unexpected -> the list was None - assigning empty list")
|
318
|
+
rel_el_list = {}
|
319
|
+
if terms:
|
320
|
+
terms = [terms]
|
321
|
+
|
322
|
+
as_is_nested_classes = set(rel_el_list.get("nested_data_class_guids", []))
|
323
|
+
as_is_assigned_meanings = set(rel_el_list.get("assigned_meanings_guids", []))
|
324
|
+
as_is_specialized_classes = set(rel_el_list.get("specialized_data_class_guids", []))
|
325
|
+
|
326
|
+
to_be_nested_classes = set(containing_data_class_guids) if containing_data_class_guids is not None else set()
|
327
|
+
to_be_assigned_meanings = set(terms) if terms is not None else set()
|
328
|
+
to_be_specialized_classes = set([specializes_data_classes]) if specializes_data_classes is not None else set()
|
329
|
+
|
330
|
+
logger.trace(
|
331
|
+
f"as_is_nested_classes: {list(as_is_nested_classes)} to_be_nested_classes: {list(to_be_nested_classes)}")
|
332
|
+
logger.trace(f"as_is_assigned_meanings: {list(as_is_assigned_meanings)} to_be_assigned_meanings: "
|
333
|
+
f"{list(to_be_assigned_meanings)}")
|
334
|
+
logger.trace(f"as_is_specialized_classes: {list(as_is_specialized_classes)} to_be_specizialized_data_classes: "
|
335
|
+
f"{list(to_be_specialized_classes)}")
|
336
|
+
|
337
|
+
nested_classes_to_remove = to_be_nested_classes - as_is_nested_classes
|
338
|
+
logger.trace(f"nested_classes_to_remove: {list(nested_classes_to_remove)}")
|
339
|
+
if len(nested_classes_to_remove) > 0:
|
340
|
+
for field in nested_classes_to_remove:
|
341
|
+
egeria_client.detach_nested_data_class(field, guid, None)
|
342
|
+
msg = f"Removed `{display_name}` from field `{field}`"
|
343
|
+
logger.trace(msg)
|
344
|
+
nested_classes_to_add = to_be_nested_classes - as_is_nested_classes
|
345
|
+
logger.trace(f"nested_classes_to_add: {list(nested_classes_to_add)}")
|
346
|
+
if len(nested_classes_to_add) > 0:
|
347
|
+
for field in nested_classes_to_add:
|
348
|
+
egeria_client.link_nested_data_class(field, guid, None)
|
349
|
+
msg = f"Added `{display_name}` to field `{field}`"
|
350
|
+
logger.trace(msg)
|
351
|
+
|
352
|
+
terms_to_remove = as_is_assigned_meanings - to_be_assigned_meanings
|
353
|
+
logger.trace(f"terms_to_remove: {list(terms_to_remove)}")
|
354
|
+
if len(terms_to_remove) > 0:
|
355
|
+
for term in terms_to_remove:
|
356
|
+
egeria_client.detach_semantic_definition(guid, term, None)
|
357
|
+
msg = f"Removed `{term}` from `{display_name}`"
|
358
|
+
logger.trace(msg)
|
359
|
+
terms_to_add = to_be_assigned_meanings - as_is_assigned_meanings
|
360
|
+
logger.trace(f"terms_to_add: {list(terms_to_add)}")
|
361
|
+
if len(terms_to_add) > 0:
|
362
|
+
for term in terms_to_add:
|
363
|
+
egeria_client.link_semantic_definition(guid, term, None)
|
364
|
+
msg = f"Added `{term}` to`{display_name}`"
|
365
|
+
logger.trace(msg)
|
366
|
+
|
367
|
+
specialized_classes_to_remove = as_is_specialized_classes - to_be_specialized_classes
|
368
|
+
logger.trace(f"classes_to_remove: {list(specialized_classes_to_remove)}")
|
369
|
+
if len(terms_to_remove) > 0:
|
370
|
+
for dc in specialized_classes_to_remove:
|
371
|
+
body = {
|
372
|
+
"class": "MetadataSourceRequestBody", "forLineage": False, "forDuplicateProcessing": False
|
373
|
+
}
|
374
|
+
egeria_client.detach_specialist_data_class(guid, dc, body)
|
375
|
+
msg = f"Removed `{dc}` from `{display_name}`"
|
376
|
+
logger.trace(msg)
|
377
|
+
specialized_classes_to_add = to_be_specialized_classes - as_is_specialized_classes
|
378
|
+
logger.trace(f"classes_to_add: {list(specialized_classes_to_add)}")
|
379
|
+
if len(specialized_classes_to_add) > 0:
|
380
|
+
for dc in specialized_classes_to_add:
|
381
|
+
body = {
|
382
|
+
"class": "RelationshipRequestBody", "forLineage": False, "forDuplicateProcessing": False
|
383
|
+
}
|
384
|
+
egeria_client.link_specialist_data_class(guid, dc, body)
|
385
|
+
msg = f"Added `{dc}` to`{display_name}`"
|
386
|
+
logger.trace(msg)
|
387
|
+
|
388
|
+
|
389
|
+
else: # merge - add field to related elements
|
390
|
+
if containing_data_class_guids:
|
391
|
+
for field in containing_data_class_guids:
|
392
|
+
egeria_client.link_nested_data_class(field, guid, None)
|
393
|
+
msg = f"Added `{display_name}` to `{field}`"
|
394
|
+
logger.trace(msg)
|
395
|
+
|
396
|
+
if terms:
|
397
|
+
for term in terms:
|
398
|
+
egeria_client.link_semantic_definition(guid, term, None)
|
399
|
+
msg = f"Added `{term}` to `{display_name}`"
|
400
|
+
logger.trace(msg)
|
401
|
+
if specializes_data_classes:
|
402
|
+
for el in specializes_data_classes:
|
403
|
+
egeria_client.link_specialist_data_class(guid, el)
|
404
|
+
msg = f"Linked `{el}` to `{display_name}`"
|
405
|
+
logger.trace(msg)
|
406
|
+
|
407
|
+
|
408
|
+
@logger.catch
|
100
409
|
def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
101
410
|
"""
|
102
411
|
Processes a data specification create or update object_action by extracting key attributes such as
|
@@ -107,13 +416,10 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
|
|
107
416
|
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
108
417
|
:return: A string summarizing the outcome of the processing.
|
109
418
|
"""
|
110
|
-
from md_processing.md_processing_utils.common_md_utils import set_debug_level
|
111
|
-
|
112
|
-
set_debug_level(directive)
|
113
419
|
|
114
420
|
command, object_type, object_action = extract_command_plus(txt)
|
115
421
|
|
116
|
-
parsed_output =
|
422
|
+
parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
|
117
423
|
|
118
424
|
valid = parsed_output['valid']
|
119
425
|
exists = parsed_output['exists']
|
@@ -123,21 +429,31 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
|
|
123
429
|
|
124
430
|
print(Markdown(parsed_output['display']))
|
125
431
|
|
126
|
-
|
432
|
+
logger.debug(json.dumps(parsed_output, indent=4))
|
127
433
|
|
128
434
|
attributes = parsed_output['attributes']
|
129
435
|
description = attributes['Description'].get('value', None)
|
130
436
|
display_name = attributes['Display Name'].get('value', None)
|
131
437
|
anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
|
132
438
|
parent_guid = attributes.get('Parent ID', {}).get('guid', None)
|
133
|
-
parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value',
|
439
|
+
parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value',
|
440
|
+
"CollectionMembership")
|
134
441
|
parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
|
135
442
|
|
136
443
|
anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
|
137
444
|
is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
|
138
|
-
|
139
|
-
|
140
|
-
|
445
|
+
if parent_guid is None:
|
446
|
+
is_own_anchor = True
|
447
|
+
|
448
|
+
collection_type = attributes.get('Collection Type', {}).get('value', None)
|
449
|
+
|
450
|
+
replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
|
451
|
+
|
452
|
+
additional_prop = attributes.get('Additional Properties', {}).get('value', None)
|
453
|
+
additional_properties = json.loads(additional_prop) if additional_prop is not None else None
|
454
|
+
extended_prop = attributes.get('Extended Properties', {}).get('value', None)
|
455
|
+
extended_properties = json.loads(extended_prop) if extended_prop is not None else None
|
456
|
+
|
141
457
|
replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
|
142
458
|
in_data_spec_list = attributes.get('In Data Specification', {}).get('value', None)
|
143
459
|
in_data_spec_valid = attributes.get('In Data Specification', {}).get('valid', None)
|
@@ -154,16 +470,12 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
|
|
154
470
|
return valid
|
155
471
|
|
156
472
|
elif directive == "process":
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
473
|
try:
|
162
474
|
if object_action == "Update":
|
163
475
|
if not exists:
|
164
476
|
msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
|
165
|
-
|
166
|
-
|
477
|
+
f"object_action\n")
|
478
|
+
logger.error(msg)
|
167
479
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
168
480
|
elif not valid:
|
169
481
|
return None
|
@@ -172,48 +484,54 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
|
|
172
484
|
f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
|
173
485
|
|
174
486
|
egeria_client.update_collection(guid, qualified_name, display_name, description, collection_type,
|
175
|
-
|
176
|
-
|
487
|
+
additional_properties,
|
488
|
+
extended_properties, replace_all_props)
|
489
|
+
logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
|
177
490
|
update_element_dictionary(qualified_name, {
|
178
491
|
'guid': guid, 'display_name': display_name
|
179
492
|
})
|
180
|
-
return egeria_client.get_collection_by_guid(guid,
|
493
|
+
return egeria_client.get_collection_by_guid(guid, collection_type='Data Specification',
|
494
|
+
output_format='MD')
|
181
495
|
|
182
496
|
|
183
497
|
elif object_action == "Create":
|
184
498
|
if valid is False and exists:
|
185
499
|
msg = (f" Data Specification `{display_name}` already exists and result document updated changing "
|
186
|
-
|
187
|
-
|
500
|
+
f"`Create` to `Update` in processed output\n\n___")
|
501
|
+
logger.error(msg)
|
188
502
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
189
503
|
elif valid is False and in_data_spec_valid is False:
|
190
504
|
msg = (f" Invalid data specification(s) `{in_data_spec_list}` "
|
191
|
-
f"
|
192
|
-
|
505
|
+
f" invalid data? - Correct and try again\n\n___")
|
506
|
+
logger.error(msg)
|
507
|
+
return None
|
193
508
|
else:
|
194
|
-
guid = egeria_client.create_data_spec_collection(
|
509
|
+
guid = egeria_client.create_data_spec_collection(display_name, description, qualified_name,
|
510
|
+
is_own_anchor, anchor_guid, parent_guid,
|
195
511
|
parent_relationship_type_name, parent_at_end1,
|
196
|
-
|
197
|
-
|
198
|
-
collection_ordering, order_property_name,
|
199
|
-
qualified_name)
|
512
|
+
collection_type, anchor_scope_guid,
|
513
|
+
additional_properties, extended_properties)
|
200
514
|
if guid:
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
515
|
+
update_element_dictionary(qualified_name, {
|
516
|
+
'guid': guid, 'display_name': display_name
|
517
|
+
})
|
518
|
+
msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
|
519
|
+
logger.success(msg)
|
520
|
+
return egeria_client.get_collection_by_guid(guid, collection_type='Data Specification',
|
521
|
+
output_format='MD')
|
205
522
|
else:
|
206
|
-
|
523
|
+
msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
|
524
|
+
logger.error(msg)
|
207
525
|
return None
|
208
526
|
|
209
527
|
except Exception as e:
|
210
|
-
|
211
|
-
Console().print_exception(show_locals=True)
|
528
|
+
logger.error(f"Error performing {command}: {e}")
|
212
529
|
return None
|
213
530
|
else:
|
214
531
|
return None
|
215
532
|
|
216
533
|
|
534
|
+
@logger.catch
|
217
535
|
def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
218
536
|
"""
|
219
537
|
Processes a data dictionary create or update object_action by extracting key attributes such as
|
@@ -224,13 +542,10 @@ def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, direct
|
|
224
542
|
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
225
543
|
:return: A string summarizing the outcome of the processing.
|
226
544
|
"""
|
227
|
-
from md_processing.md_processing_utils.common_md_utils import set_debug_level
|
228
|
-
|
229
|
-
set_debug_level(directive)
|
230
545
|
|
231
546
|
command, object_type, object_action = extract_command_plus(txt)
|
232
547
|
|
233
|
-
parsed_output =
|
548
|
+
parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
|
234
549
|
|
235
550
|
valid = parsed_output['valid']
|
236
551
|
exists = parsed_output['exists']
|
@@ -239,9 +554,31 @@ def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, direct
|
|
239
554
|
guid = parsed_output.get('guid', None)
|
240
555
|
|
241
556
|
print(Markdown(parsed_output['display']))
|
557
|
+
logger.debug(json.dumps(parsed_output, indent=4))
|
242
558
|
|
243
|
-
|
559
|
+
attributes = parsed_output['attributes']
|
560
|
+
description = attributes['Description'].get('value', None)
|
561
|
+
display_name = attributes.get('Display Name', {}).get('value', "None Found")
|
562
|
+
display_name = display_name if display_name is not None else "None Found"
|
563
|
+
anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
|
564
|
+
parent_guid = attributes.get('Parent ID', {}).get('guid', None)
|
565
|
+
parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value',
|
566
|
+
"CollectionMembership")
|
567
|
+
parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
|
568
|
+
|
569
|
+
anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
|
570
|
+
is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
|
571
|
+
if parent_guid is None:
|
572
|
+
is_own_anchor = True
|
573
|
+
collection_type = attributes.get('Collection Type', {}).get('value', None)
|
574
|
+
replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
|
575
|
+
|
576
|
+
additional_prop = attributes.get('Additional Properties', {}).get('value', None)
|
577
|
+
additional_properties = json.loads(additional_prop) if additional_prop is not None else None
|
578
|
+
extended_prop = attributes.get('Extended Properties', {}).get('value', None)
|
579
|
+
extended_properties = json.loads(extended_prop) if extended_prop is not None else None
|
244
580
|
|
581
|
+
if directive == "display":
|
245
582
|
return None
|
246
583
|
elif directive == "validate":
|
247
584
|
if valid:
|
@@ -251,79 +588,67 @@ def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, direct
|
|
251
588
|
return valid
|
252
589
|
|
253
590
|
elif directive == "process":
|
254
|
-
print(json.dumps(parsed_output, indent=4))
|
255
|
-
|
256
|
-
attributes = parsed_output['attributes']
|
257
|
-
description = attributes['Description'].get('value', None)
|
258
|
-
display_name = attributes['Display Name'].get('value', None)
|
259
|
-
anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
|
260
|
-
parent_guid = attributes.get('Parent ID', {}).get('guid', None)
|
261
|
-
parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value',
|
262
|
-
"CollectionMembership")
|
263
|
-
parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
|
264
|
-
|
265
|
-
anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
|
266
|
-
is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
|
267
|
-
if parent_guid is None:
|
268
|
-
is_own_anchor = True
|
269
|
-
collection_ordering = "NAME"
|
270
|
-
order_property_name = "Something"
|
271
|
-
collection_type = object_type
|
272
|
-
replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
|
273
|
-
|
274
591
|
|
275
592
|
try:
|
276
593
|
if object_action == "Update":
|
277
594
|
|
278
595
|
if not exists:
|
279
|
-
|
280
|
-
|
596
|
+
logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
|
597
|
+
f"object_action\n\n___")
|
281
598
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
282
599
|
elif not valid:
|
600
|
+
logger.error(f"Element `{display_name}` does not have a valid specification? Review..\n\n___ ")
|
283
601
|
return None
|
284
602
|
else:
|
285
603
|
print(Markdown(
|
286
|
-
f"==> Validation of {command} completed successfully! Proceeding to apply the changes
|
604
|
+
f"==> Validation of {command} completed successfully! Proceeding to apply the changes."))
|
287
605
|
|
288
606
|
egeria_client.update_collection(guid, qualified_name, display_name, description, collection_type,
|
289
|
-
|
290
|
-
|
607
|
+
additional_properties,
|
608
|
+
extended_properties, replace_all_props)
|
609
|
+
logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
|
291
610
|
update_element_dictionary(qualified_name, {
|
292
611
|
'guid': guid, 'display_name': display_name
|
293
612
|
})
|
294
|
-
return egeria_client.get_collection_by_guid(guid, output_format='
|
613
|
+
return egeria_client.get_collection_by_guid(guid, collection_type='Data Dictionary', output_format='MD')
|
295
614
|
|
296
615
|
elif object_action == "Create":
|
297
616
|
if valid is False and exists:
|
298
|
-
|
299
|
-
|
617
|
+
logger.error(f"\nElement `{display_name}` already exists and result document updated changing "
|
618
|
+
f"`Create` to `Update` in processed output\n\n___")
|
300
619
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
301
620
|
else:
|
302
|
-
guid = egeria_client.create_data_dictionary_collection(
|
621
|
+
guid = egeria_client.create_data_dictionary_collection(display_name, description, qualified_name,
|
622
|
+
is_own_anchor, anchor_guid, parent_guid,
|
303
623
|
parent_relationship_type_name,
|
304
|
-
parent_at_end1,
|
305
|
-
|
306
|
-
|
307
|
-
order_property_name, qualified_name)
|
624
|
+
parent_at_end1, collection_type,
|
625
|
+
anchor_scope_guid, additional_properties,
|
626
|
+
extended_properties)
|
308
627
|
if guid:
|
309
|
-
|
628
|
+
update_element_dictionary(qualified_name, {
|
629
|
+
'guid': guid, 'display_name': display_name
|
630
|
+
})
|
631
|
+
logger.success(f"Created Element `{display_name}` with GUID {guid}\n\n___")
|
310
632
|
|
311
|
-
return egeria_client.get_collection_by_guid(guid,
|
633
|
+
return egeria_client.get_collection_by_guid(guid, collection_type='Data Dictionary',
|
634
|
+
output_format='MD')
|
312
635
|
else:
|
313
|
-
|
636
|
+
logger.error(f"Failed to create Term `{display_name}`\n\n___")
|
314
637
|
return None
|
315
638
|
|
316
639
|
except Exception as e:
|
317
|
-
|
640
|
+
logger.error(f"{ERROR}Error performing {command}: {e}")
|
318
641
|
Console().print_exception(show_locals=True)
|
319
642
|
return None
|
320
643
|
else:
|
321
644
|
return None
|
322
645
|
|
323
646
|
|
324
|
-
|
647
|
+
@logger.catch
|
648
|
+
def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
|
649
|
+
str]:
|
325
650
|
"""
|
326
|
-
Processes a data
|
651
|
+
Processes a data structure create or update object_action by extracting key attributes such as
|
327
652
|
spec name, parent_guid, parent_relationship_type, parent_at_end_1, collection_type
|
328
653
|
|
329
654
|
:param txt: A string representing the input cell to be processed for
|
@@ -336,8 +661,9 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
|
|
336
661
|
set_debug_level(directive)
|
337
662
|
|
338
663
|
command, object_type, object_action = extract_command_plus(txt)
|
664
|
+
print(Markdown(f"# {command}\n"))
|
339
665
|
|
340
|
-
parsed_output =
|
666
|
+
parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
|
341
667
|
|
342
668
|
valid = parsed_output['valid']
|
343
669
|
exists = parsed_output['exists']
|
@@ -348,8 +674,8 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
|
|
348
674
|
print(Markdown(parsed_output['display']))
|
349
675
|
|
350
676
|
if directive == "display":
|
351
|
-
|
352
677
|
return None
|
678
|
+
|
353
679
|
elif directive == "validate":
|
354
680
|
if valid:
|
355
681
|
print(Markdown(f"==> Validation of {command} completed successfully!\n"))
|
@@ -358,7 +684,7 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
|
|
358
684
|
return valid
|
359
685
|
|
360
686
|
elif directive == "process":
|
361
|
-
|
687
|
+
logger.debug(json.dumps(parsed_output, indent=4))
|
362
688
|
attributes = parsed_output['attributes']
|
363
689
|
|
364
690
|
external_source_guid = attributes.get('External Source Name', {}).get('guid', None)
|
@@ -368,16 +694,16 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
|
|
368
694
|
for_duplicate_processing = attributes.get('For Duplicate Processing', {}).get('value', None)
|
369
695
|
anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
|
370
696
|
is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', None)
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
697
|
+
parent_id = attributes.get('Parent ID', {}).get('value', None)
|
698
|
+
parent_guid = attributes.get('Parent ID', {}).get('guid', None)
|
699
|
+
parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
|
700
|
+
parent_relationship_properties = attributes.get('Parent Relationship Properties', {}).get('value', None)
|
701
|
+
parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
|
376
702
|
|
377
703
|
display_name = attributes['Display Name'].get('value', None)
|
378
704
|
|
379
|
-
namespace = attributes.get('Namespace',{}).get('value', None)
|
380
|
-
description = attributes.get('Description',{}).get('value', None)
|
705
|
+
namespace = attributes.get('Namespace', {}).get('value', None)
|
706
|
+
description = attributes.get('Description', {}).get('value', None)
|
381
707
|
version_id = attributes.get('Version Identifier', {}).get('value', None)
|
382
708
|
aliases = attributes.get('Aliases', {}).get('value', None)
|
383
709
|
name_patterns = attributes.get('Name Patterns', {}).get('value', None)
|
@@ -396,215 +722,131 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
|
|
396
722
|
position = attributes.get('Position', {}).get('value', None)
|
397
723
|
min_cardinality = attributes.get('Minimum Cardinality', {}).get('value', None)
|
398
724
|
max_cardinality = attributes.get('Maximum Cardinality', {}).get('value', None)
|
399
|
-
|
400
725
|
in_data_structure = attributes.get('In Data Structure', {}).get('value', None)
|
401
|
-
|
726
|
+
data_class = attributes.get('Data Class', {}).get('value', None)
|
727
|
+
glossary_term = attributes.get('Glossary Term', {}).get('value', None)
|
728
|
+
glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
|
402
729
|
|
403
|
-
|
730
|
+
# name_details_list = attributes.get("dict_list", None)
|
404
731
|
|
405
|
-
|
406
|
-
|
732
|
+
data_spec_name_list = attributes.get("In Data Specification", {}).get("name_list", "")
|
733
|
+
data_spec_value = attributes.get("In Data Specification", {}).get("value", None)
|
734
|
+
data_spec_guid_list = attributes.get("In Data Specification", {}).get("guid_list", None)
|
407
735
|
|
408
|
-
in_data_dictionary = attributes.get('In Data Dictionary', {}).get('
|
409
|
-
|
736
|
+
in_data_dictionary = attributes.get('In Data Dictionary', {}).get('dict_list', None)
|
737
|
+
data_dict_name_list = attributes.get('In Data Dictionary', {}).get('name_list', "")
|
738
|
+
data_dict_value_list = attributes.get('In Data Dictionary', {}).get('value', None)
|
739
|
+
data_dict_guid_list = attributes.get("In Data Dictionary", {}).get("guid_list", None)
|
410
740
|
|
411
741
|
parent_data_field = attributes.get('Parent Data Field', {}).get('value', None)
|
412
742
|
parent_data_field_guid = attributes.get('Parent Data Field', {}).get('guid', None)
|
413
743
|
|
414
744
|
anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
|
415
745
|
|
416
|
-
merge_update = attributes.get('Merge Update', {}).get('value', None)
|
417
|
-
|
418
|
-
|
419
|
-
collection_ordering = "NAME"
|
420
|
-
order_property_name = "Something"
|
421
746
|
collection_type = object_type
|
422
747
|
replace_all_props = True
|
423
|
-
|
424
748
|
if not valid:
|
425
749
|
if exists and object_action == "Create":
|
426
750
|
msg = (f"Create failed because Element `{display_name}` exists - changing `Create` to `Update` in "
|
427
|
-
f"processed output \n")
|
428
|
-
|
751
|
+
f"processed output \n\n___")
|
752
|
+
logger.error(msg)
|
429
753
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
430
754
|
else:
|
431
755
|
return None
|
756
|
+
elif object_action == "Update" and not exists:
|
757
|
+
logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
|
758
|
+
f"object_action\n\n___")
|
759
|
+
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
760
|
+
|
432
761
|
else:
|
433
762
|
print(Markdown(f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
|
434
763
|
|
435
764
|
try:
|
436
765
|
if object_action == "Update":
|
437
|
-
if not exists:
|
438
|
-
print(f"\n{ERROR}Element `{display_name}` does not exist! Updating result document with Create "
|
439
|
-
f"object_action\n")
|
440
|
-
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
441
|
-
|
442
766
|
body = {
|
443
|
-
"class": "
|
444
|
-
"
|
445
|
-
"
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
"class": "DataFieldProperties",
|
451
|
-
"qualifiedName": qualified_name,
|
452
|
-
"displayName": display_name,
|
453
|
-
"namespace": namespace,
|
454
|
-
"description": description,
|
455
|
-
"versionIdentifier": version_id,
|
456
|
-
"aliases": aliases,
|
457
|
-
"namePatterns": name_patterns,
|
458
|
-
"isDeprecated": False,
|
459
|
-
"isNullable": is_nullable,
|
460
|
-
"defaultValue": default_value,
|
461
|
-
"dataType": data_type,
|
462
|
-
"minimumLength": min_length,
|
463
|
-
"length": length,
|
464
|
-
"precision": precision,
|
465
|
-
"orderedValues": ordered_values,
|
466
|
-
"sortOrder": sort_order,
|
467
|
-
"additionalProperties": additional_properties,
|
468
|
-
"effectiveFrom": effective_from,
|
469
|
-
"effectiveTo": effective_to
|
767
|
+
"class": "UpdateElementRequestBody", "externalSourceGUID": external_source_guid,
|
768
|
+
"externalSourceName": external_source_name, "effectiveTime": effective_time,
|
769
|
+
"forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing, "properties": {
|
770
|
+
"class": "DataStructureProperties", "qualifiedName": qualified_name,
|
771
|
+
"displayName": display_name, "description": description, "namespace": namespace,
|
772
|
+
"versionIdentifier": version_id, "additionalProperties": additional_properties,
|
773
|
+
"effectiveFrom": effective_from, "effectiveTo": effective_to
|
470
774
|
}
|
471
775
|
}
|
776
|
+
egeria_client.update_data_structure_w_body(guid, body, replace_all_props)
|
777
|
+
logger.info(f"Updated element `{display_name}` with GUID {guid}")
|
778
|
+
core_props = egeria_client.get_data_structure_by_guid(guid, output_format='MD')
|
472
779
|
|
473
|
-
egeria_client.update_data_field(guid, body, not merge_update)
|
474
|
-
print_msg(ALWAYS, f"Updated {object_type} `{display_name}` with GUID {guid}", debug_level)
|
475
|
-
# Update data dictionary membership
|
476
780
|
update_element_dictionary(qualified_name, {
|
477
781
|
'guid': guid, 'display_name': display_name
|
478
782
|
})
|
479
|
-
core_props = egeria_client.get_data_field_by_guid(guid, output_format='MD')
|
480
|
-
|
481
|
-
existing_data_field = egeria_client.get_data_field_by_guid(guid, output_format='JSON')
|
482
|
-
existing_data_field_dicts = 3
|
483
|
-
|
484
|
-
# Sync membership in data dictionaries
|
485
|
-
result = sync_data_dict_membership(egeria_client, in_data_dictionary_names, in_data_dictionary, guid, object_type)
|
486
|
-
print_msg(ALWAYS, f"Will update data dictionary `{in_data_dictionary}`", debug_level)
|
487
|
-
core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary}\n\n"
|
488
|
-
|
489
|
-
# Update data spec membership
|
490
|
-
result = sync_data_spec_membership(egeria_client, in_data_dictionary_names, in_data_dictionary, guid,
|
491
|
-
object_type)
|
492
|
-
print_msg(ALWAYS, f"Will update data dictionary `{in_data_dictionary}`", debug_level)
|
493
|
-
core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary}\n\n"
|
494
|
-
|
495
|
-
# Sync membership in data structuress
|
496
|
-
result = sync_data_structure_membership(egeria_client, in_data_dictionary_names, in_data_dictionary, guid,
|
497
|
-
object_type)
|
498
|
-
core_props += f"\n\n## In Data Structure {in_data_structure}\n\n"
|
499
|
-
|
500
|
-
# Update glossary links
|
501
|
-
result = sync_term_links(egeria_client, glossary_term, glossary_term_guid, guid, object_type)
|
502
|
-
print_msg(ALWAYS, f"Updating glossary term to `{glossary_term}`", debug_level)
|
503
|
-
|
504
|
-
core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
|
505
|
-
# Update parent field
|
506
|
-
result = sync_parent_data_field(egeria_client, parent_data_field, parent_data_field_guid, guid, object_type)
|
507
|
-
|
508
|
-
core_props += f"\n\n## Parent Data Field\n\n{parent_data_field}\n\n"
|
509
|
-
|
510
|
-
# Update data classes
|
511
|
-
print_msg(ALWAYS, f"Created Element `{display_name}` ", debug_level)
|
512
|
-
|
513
783
|
|
784
|
+
update_data_collection_memberships(egeria_client, object_type, data_spec_guid_list, "DataSpec", guid,
|
785
|
+
display_name, replace_all_props)
|
786
|
+
core_props += f"## In Data Dictionary\n\n{data_dict_name_list}\n\n"
|
787
|
+
core_props += f"## In Data Specification\n\n{data_spec_name_list}\n\n"
|
788
|
+
logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
|
514
789
|
return core_props
|
515
790
|
|
516
|
-
|
517
791
|
elif object_action == "Create":
|
518
|
-
if
|
519
|
-
|
520
|
-
f"to `Update` in processed output\n")
|
792
|
+
if exists:
|
793
|
+
logger.warning(f"\nTerm `{display_name}` already exists and result document updated\n\n___")
|
521
794
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
522
795
|
else:
|
523
|
-
|
796
|
+
|
524
797
|
body = {
|
798
|
+
"class": "NewElementRequestBody", "externalSourceGUID": external_source_guid,
|
799
|
+
"externalSourceName": external_source_name, "effectiveTime": effective_time,
|
800
|
+
"forLineage": False, "forDuplicateProcessing": False, "anchorGUID": anchor_guid,
|
801
|
+
"isOwnAnchor": is_own_anchor, "parentGUID": parent_guid,
|
802
|
+
"parentRelationshipTypeName": parent_relationship_type_name,
|
803
|
+
"parentRelationshipProperties": parent_relationship_properties, "parentAtEnd1": parent_at_end1,
|
525
804
|
"properties": {
|
526
|
-
"class": "
|
527
|
-
"displayName": display_name, "
|
528
|
-
"versionIdentifier": version_id, "
|
529
|
-
"
|
530
|
-
"dataType": data_type, "minimumLength": min_length, "length": length,
|
531
|
-
"precision": precision, "orderedValues": ordered_values, "sortOrder": sort_order,
|
532
|
-
"additionalProperties": additional_properties
|
805
|
+
"class": "DataStructureProperties", "qualifiedName": qualified_name,
|
806
|
+
"displayName": display_name, "description": description, "namespace": namespace,
|
807
|
+
"versionIdentifier": version_id, "additionalProperties": additional_properties,
|
808
|
+
"effectiveFrom": effective_from, "effectiveTo": effective_to
|
533
809
|
}
|
534
810
|
}
|
535
|
-
|
811
|
+
|
812
|
+
guid = egeria_client.create_data_structure_w_body(body_slimmer(body))
|
536
813
|
if guid:
|
537
|
-
# Now update our element dictionary with the new information
|
538
814
|
update_element_dictionary(qualified_name, {
|
539
815
|
'guid': guid, 'display_name': display_name
|
540
816
|
})
|
541
|
-
# Start assembling the information we will present back out
|
542
|
-
core_props = egeria_client.get_data_field_by_guid(guid, output_format='MD')
|
543
|
-
|
544
|
-
# Add the field to any data dictionaries
|
545
|
-
if in_data_dictionary:
|
546
|
-
print_msg(ALWAYS, f"Will add to data dictionary `{in_data_dictionary}`", debug_level)
|
547
|
-
core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
|
548
|
-
# Add the field to any data structures
|
549
|
-
if in_data_structure:
|
550
|
-
core_props += f"\n\n## In Data Structure\n\n{in_data_structure_names}\n\n"
|
551
|
-
for key in in_data_structure.keys():
|
552
|
-
ds_qname = in_data_structure[key].get('known_q_name', None)
|
553
|
-
ds_guid = in_data_structure[key].get('known_guid', None)
|
554
|
-
if ds_guid is not None:
|
555
|
-
df_body = {
|
556
|
-
"class": "MemberDataFieldRequestBody", "properties": {
|
557
|
-
"class": "MemberDataFieldProperties", "dataFieldPosition": 0,
|
558
|
-
"minCardinality": 0, "maxCardinality": -1,
|
559
|
-
}
|
560
|
-
}
|
561
817
|
|
562
|
-
|
563
|
-
print_msg(INFO, msg, debug_level)
|
564
|
-
egeria_client.link_member_data_field(ds_guid, guid, df_body)
|
565
|
-
core_props += f"\n\n## In Data Structure {in_data_structure}\n\n"
|
818
|
+
core_props = egeria_client.get_data_structure_by_guid(guid, output_format='MD')
|
566
819
|
|
567
|
-
if
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
"forDuplicateProcessing": False
|
573
|
-
}
|
574
|
-
|
575
|
-
core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
|
576
|
-
egeria_client.link_semantic_definition(guid, glossary_term_guid, glossary_body)
|
820
|
+
if in_data_dictionary:
|
821
|
+
logger.info(f"Will add to data dictionary(s) `{in_data_dictionary}`")
|
822
|
+
result = add_member_to_data_collections(egeria_client, in_data_dictionary, display_name,
|
823
|
+
guid)
|
824
|
+
core_props += f"## In Data Dictionary\n\n{data_dict_name_list}\n\n"
|
577
825
|
|
578
|
-
if
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
"forDuplicateProcessing": False
|
583
|
-
}
|
826
|
+
if data_spec_guid_list:
|
827
|
+
result = add_member_to_data_collections(egeria_client, data_spec_guid_list, display_name,
|
828
|
+
guid)
|
829
|
+
core_props += f"## In Data Specifications\n\n`{data_spec_name_list}`\n\n"
|
584
830
|
|
585
|
-
|
586
|
-
core_props += f"\n\n## Parent Data Field\n\n{parent_data_field}\n\n"
|
831
|
+
logger.info(f"Created Element `{display_name}` with GUID {guid}\n\n___")
|
587
832
|
|
588
|
-
# Link data class
|
589
|
-
print_msg(ALWAYS, f"Created Element `{display_name}` ", debug_level)
|
590
833
|
return core_props
|
591
|
-
|
592
834
|
else:
|
593
|
-
|
835
|
+
logger.error(f"Failed to create Data Structure `{display_name}`\n\n___")
|
594
836
|
return None
|
595
837
|
|
838
|
+
|
596
839
|
except Exception as e:
|
597
|
-
|
598
|
-
Console().print_exception(show_locals=True)
|
840
|
+
logger.error(f"Error performing {object_action}: {e}\n\n___")
|
599
841
|
return None
|
600
842
|
else:
|
601
843
|
return None
|
602
844
|
|
603
845
|
|
604
|
-
|
605
|
-
|
846
|
+
@logger.catch
|
847
|
+
def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
606
848
|
"""
|
607
|
-
Processes a data
|
849
|
+
Processes a data field create or update object_action by extracting key attributes such as
|
608
850
|
spec name, parent_guid, parent_relationship_type, parent_at_end_1, collection_type
|
609
851
|
|
610
852
|
:param txt: A string representing the input cell to be processed for
|
@@ -617,30 +859,31 @@ def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, d
|
|
617
859
|
set_debug_level(directive)
|
618
860
|
|
619
861
|
command, object_type, object_action = extract_command_plus(txt)
|
862
|
+
print(Markdown(f"# {command}\n"))
|
620
863
|
|
621
|
-
parsed_output =
|
622
|
-
|
623
|
-
|
624
|
-
exists = parsed_output['exists']
|
625
|
-
|
864
|
+
parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
|
865
|
+
attributes = parsed_output['attributes']
|
866
|
+
display_name = attributes['Display Name'].get('value', None)
|
626
867
|
qualified_name = parsed_output.get('qualified_name', None)
|
627
868
|
guid = parsed_output.get('guid', None)
|
869
|
+
valid = parsed_output['valid']
|
870
|
+
exists = parsed_output['exists']
|
628
871
|
|
629
872
|
print(Markdown(parsed_output['display']))
|
630
873
|
|
631
874
|
if directive == "display":
|
632
|
-
return None
|
633
875
|
|
876
|
+
return None
|
634
877
|
elif directive == "validate":
|
635
878
|
if valid:
|
636
879
|
print(Markdown(f"==> Validation of {command} completed successfully!\n"))
|
637
880
|
else:
|
638
881
|
msg = f"Validation failed for object_action `{command}`\n"
|
882
|
+
logger.error(msg)
|
639
883
|
return valid
|
640
884
|
|
641
885
|
elif directive == "process":
|
642
|
-
|
643
|
-
attributes = parsed_output['attributes']
|
886
|
+
logger.debug(json.dumps(parsed_output, indent=4))
|
644
887
|
|
645
888
|
external_source_guid = attributes.get('External Source Name', {}).get('guid', None)
|
646
889
|
external_source_name = attributes.get('External Source Name', {}).get('value', None)
|
@@ -649,13 +892,11 @@ def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, d
|
|
649
892
|
for_duplicate_processing = attributes.get('For Duplicate Processing', {}).get('value', None)
|
650
893
|
anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
|
651
894
|
is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', None)
|
652
|
-
parent_id = attributes.get('Parent ID', {}).get('value', None)
|
653
|
-
parent_guid = attributes
|
654
|
-
parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
|
655
|
-
parent_relationship_properties = attributes.get('Parent Relationship Properties',
|
656
|
-
parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
|
657
|
-
|
658
|
-
display_name = attributes['Display Name'].get('value', None)
|
895
|
+
# parent_id = attributes.get('Parent ID', {}).get('value', None)
|
896
|
+
# parent_guid = attributes['Parent ID'].get('guid', None)
|
897
|
+
# parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
|
898
|
+
# parent_relationship_properties = attributes.get('Parent Relationship Properties',{}).get('value', None)
|
899
|
+
# parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
|
659
900
|
|
660
901
|
namespace = attributes.get('Namespace', {}).get('value', None)
|
661
902
|
description = attributes.get('Description', {}).get('value', None)
|
@@ -674,309 +915,468 @@ def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, d
|
|
674
915
|
effective_from = attributes.get('Effective From', {}).get('value', None)
|
675
916
|
effective_to = attributes.get('Effective To', {}).get('value', None)
|
676
917
|
|
918
|
+
glossary_term = attributes['Glossary Term'].get('value', None)
|
919
|
+
glossary_term_guid = attributes['Glossary Term'].get('guid', None)
|
920
|
+
|
921
|
+
merge_update = attributes.get('Merge Update', {}).get('value', None)
|
922
|
+
|
677
923
|
position = attributes.get('Position', {}).get('value', None)
|
678
924
|
min_cardinality = attributes.get('Minimum Cardinality', {}).get('value', None)
|
679
925
|
max_cardinality = attributes.get('Maximum Cardinality', {}).get('value', None)
|
926
|
+
|
680
927
|
in_data_structure = attributes.get('In Data Structure', {}).get('value', None)
|
928
|
+
data_structure_guid_list = attributes.get('In Data Structure', {}).get('guid_list', None)
|
929
|
+
in_data_structure_names = attributes.get('In Data Structure Names', {}).get('name_list', None)
|
930
|
+
|
681
931
|
data_class = attributes.get('Data Class', {}).get('value', None)
|
682
|
-
|
932
|
+
data_class_guid = attributes.get('Data Class', {}).get('guid', None)
|
933
|
+
|
934
|
+
glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
|
935
|
+
if glossary_term_guid:
|
936
|
+
glossary_term_guid = [glossary_term_guid]
|
937
|
+
|
683
938
|
glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
|
684
939
|
|
685
940
|
# name_details_list = attributes.get("dict_list", None)
|
686
941
|
|
687
|
-
in_data_spec = attributes.get("In Data Specification", {}).get("
|
942
|
+
in_data_spec = attributes.get("In Data Specification", {}).get("value", None) # this is a [dict]
|
688
943
|
data_spec_name_list = attributes.get("In Data Specification", {}).get("name_list", None)
|
689
|
-
|
944
|
+
data_spec_guid_list = attributes.get("In Data Specification", {}).get("guid_list", None)
|
690
945
|
|
691
|
-
in_data_dictionary = attributes.get('In Data Dictionary', {}).get('
|
692
|
-
|
693
|
-
|
946
|
+
in_data_dictionary = attributes.get('In Data Dictionary', {}).get('value', None)
|
947
|
+
in_data_dictionary_names = attributes.get('In Data Dictionary', {}).get('name_list', None)
|
948
|
+
data_dict_guid_list = attributes.get("In Data Dictionary", {}).get("guid_list", None)
|
694
949
|
|
695
950
|
parent_data_field = attributes.get('Parent Data Field', {}).get('value', None)
|
696
|
-
|
951
|
+
parent_data_field_guids = attributes.get('Parent Data Field', {}).get('guid_list', None)
|
952
|
+
parent_data_field_names = attributes.get('Parent Data Field', {}).get('name_list', None)
|
697
953
|
|
698
954
|
anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
|
699
955
|
|
700
|
-
|
701
|
-
|
702
|
-
collection_type = object_type
|
703
|
-
replace_all_props = True
|
956
|
+
replace_all_props = not merge_update
|
957
|
+
|
704
958
|
if not valid:
|
705
959
|
if exists and object_action == "Create":
|
706
960
|
msg = (f"Create failed because Element `{display_name}` exists - changing `Create` to `Update` in "
|
707
|
-
f"processed output
|
708
|
-
|
961
|
+
f"processed output\n\n___")
|
962
|
+
logger.error(msg)
|
709
963
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
710
964
|
else:
|
965
|
+
msg = f"Invalid specification - please review\n\n___"
|
966
|
+
logger.error(msg)
|
711
967
|
return None
|
712
|
-
elif object_action == "Update" and not exists:
|
713
|
-
print(f"\n{ERROR}Element `{display_name}` does not exist! Updating result document with Create "
|
714
|
-
f"object_action\n")
|
715
|
-
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
716
|
-
|
717
968
|
else:
|
718
969
|
print(Markdown(f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
|
719
970
|
|
720
971
|
try:
|
721
972
|
if object_action == "Update":
|
973
|
+
if not exists:
|
974
|
+
logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
|
975
|
+
f"object_action\n\n___")
|
976
|
+
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
977
|
+
|
978
|
+
# first update the base data field
|
722
979
|
body = {
|
723
|
-
"class": "
|
724
|
-
"
|
725
|
-
"
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
"
|
731
|
-
"
|
732
|
-
"
|
733
|
-
"description": description,
|
734
|
-
"namespace": namespace,
|
735
|
-
"versionIdentifier": version_id,
|
736
|
-
"additionalProperties": additional_properties,
|
737
|
-
"effectiveFrom": effective_from,
|
980
|
+
"class": "UpdateElementRequestBody", "externalSourceGUID": external_source_guid,
|
981
|
+
"externalSourceName": external_source_name, "effectiveTime": effective_time,
|
982
|
+
"forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing, "properties": {
|
983
|
+
"class": "DataFieldProperties", "qualifiedName": qualified_name, "displayName": display_name,
|
984
|
+
"namespace": namespace, "description": description, "versionIdentifier": version_id,
|
985
|
+
"aliases": aliases, "namePatterns": name_patterns, "isDeprecated": False,
|
986
|
+
"isNullable": is_nullable, "defaultValue": default_value, "dataType": data_type,
|
987
|
+
"minimumLength": min_length, "length": length, "precision": precision,
|
988
|
+
"orderedValues": ordered_values, "sortOrder": sort_order,
|
989
|
+
"additionalProperties": additional_properties, "effectiveFrom": effective_from,
|
738
990
|
"effectiveTo": effective_to
|
739
991
|
}
|
740
992
|
}
|
741
|
-
egeria_client.update_data_structure_w_body(guid, body, replace_all_props)
|
742
|
-
print_msg(ALWAYS, f"Updated element `{display_name}` with GUID {guid}", debug_level)
|
743
|
-
core_props = egeria_client.get_data_structure_by_guid(guid, output_format='FORM')
|
744
993
|
|
994
|
+
egeria_client.update_data_field(guid, body, not merge_update)
|
995
|
+
logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}")
|
996
|
+
# Update data dictionary membership
|
745
997
|
update_element_dictionary(qualified_name, {
|
746
998
|
'guid': guid, 'display_name': display_name
|
747
999
|
})
|
748
|
-
|
1000
|
+
core_props = egeria_client.find_data_fields(qualified_name,
|
1001
|
+
output_format='MD') ## update back to by_guid?
|
1002
|
+
|
1003
|
+
# existing_data_field = egeria_client.get_data_field_by_guid(guid, output_format='JSON')
|
749
1004
|
|
750
|
-
|
1005
|
+
# Sync membership in data dictionaries
|
1006
|
+
update_data_collection_memberships(egeria_client, object_type, data_dict_guid_list, "DataDictionary",
|
1007
|
+
guid, display_name, replace_all_props)
|
1008
|
+
logger.success(f"Updating data dictionaries `{in_data_dictionary_names}`")
|
1009
|
+
core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
|
1010
|
+
|
1011
|
+
# Sync data field related elements (data structure, parent data fields, terms, data classes
|
1012
|
+
sync_data_field_rel_elements(egeria_client, data_structure_guid_list, parent_data_field_guids,
|
1013
|
+
glossary_term_guid, data_class_guid, guid, display_name, replace_all_props)
|
1014
|
+
core_props += f"\n\n## In Data Structure {in_data_structure_names}\n\n"
|
1015
|
+
core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
|
1016
|
+
core_props += f"\n\n## Parent Data Field\n\n{parent_data_field_names}\n\n"
|
1017
|
+
core_props += f"\n\n## Data Class\n\n{data_class}\n\n"
|
1018
|
+
core_props += "\n_______________________________________________________________________________\n\n"
|
1019
|
+
|
1020
|
+
# Update data classes
|
1021
|
+
logger.success(f"Updated Element `{display_name}`\n\n___")
|
1022
|
+
return core_props
|
751
1023
|
|
752
1024
|
elif object_action == "Create":
|
753
|
-
if exists:
|
754
|
-
|
1025
|
+
if valid is False and exists:
|
1026
|
+
logger.error(
|
1027
|
+
f"\nData Field `{display_name}` already exists and result document updated changing `Create` "
|
1028
|
+
f"to `Update` in processed output\n\n___")
|
755
1029
|
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
756
1030
|
else:
|
757
|
-
|
1031
|
+
# First lets create the data field
|
758
1032
|
body = {
|
759
|
-
"class": "
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
"
|
767
|
-
"displayName": display_name, "description": description, "namespace": namespace,
|
768
|
-
"versionIdentifier": version_id, "additionalProperties": additional_properties,
|
769
|
-
"effectiveFrom": effective_from, "effectiveTo": effective_to
|
1033
|
+
"class": "NewElementRequestBody", "properties": {
|
1034
|
+
"class": "DataFieldProperties", "qualifiedName": qualified_name,
|
1035
|
+
"displayName": display_name, "namespace": namespace, "description": description,
|
1036
|
+
"versionIdentifier": version_id, "aliases": aliases, "namePatterns": name_patterns,
|
1037
|
+
"isDeprecated": False, "isNullable": is_nullable, "defaultValue": default_value,
|
1038
|
+
"dataType": data_type, "minimumLength": min_length, "length": length,
|
1039
|
+
"precision": precision, "orderedValues": ordered_values, "sortOrder": sort_order,
|
1040
|
+
"additionalProperties": additional_properties
|
770
1041
|
}
|
771
1042
|
}
|
772
|
-
|
773
|
-
guid = egeria_client.create_data_structure_w_body(body_slimmer(body))
|
1043
|
+
guid = egeria_client.create_data_field(body)
|
774
1044
|
if guid:
|
1045
|
+
# Now update our element dictionary with the new information
|
775
1046
|
update_element_dictionary(qualified_name, {
|
776
1047
|
'guid': guid, 'display_name': display_name
|
777
1048
|
})
|
1049
|
+
# Start assembling the information we will present back out
|
1050
|
+
core_props = egeria_client.get_data_field_by_guid(guid, None, 'MD')
|
778
1051
|
|
779
|
-
|
780
|
-
|
1052
|
+
# Add the field to any data dictionaries
|
781
1053
|
if in_data_dictionary:
|
782
|
-
|
783
|
-
|
784
|
-
core_props += f"\n\n## In Data Dictionary\n\n{
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
1054
|
+
logger.info(f"Will add to data dictionary `{in_data_dictionary}`")
|
1055
|
+
add_member_to_data_collections(egeria_client, data_dict_guid_list, display_name, guid)
|
1056
|
+
core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
|
1057
|
+
|
1058
|
+
# Add the field to any data structures
|
1059
|
+
if in_data_structure:
|
1060
|
+
core_props += f"\n\n## In Data Structure\n\n{in_data_structure_names}\n\n"
|
1061
|
+
for ds_guid in data_structure_guid_list:
|
1062
|
+
# todo This is too naive? - need to better accommodate the relationship
|
1063
|
+
df_body = {
|
1064
|
+
"class": "RelationshipRequestBody", "properties": {
|
1065
|
+
"class": "MemberDataFieldProperties", "dataFieldPosition": position,
|
1066
|
+
"minCardinality": min_cardinality, "maxCardinality": max_cardinality,
|
1067
|
+
}
|
1068
|
+
}
|
1069
|
+
|
1070
|
+
msg = f"Adding field to structure {ds_guid}"
|
1071
|
+
logger.info(msg)
|
1072
|
+
egeria_client.link_member_data_field(ds_guid, guid, df_body)
|
1073
|
+
core_props += f"\n\n## In Data Structure {in_data_structure_names}\n\n"
|
1074
|
+
|
1075
|
+
if glossary_term:
|
1076
|
+
if glossary_term_guid:
|
1077
|
+
glossary_body = {
|
1078
|
+
"class": "RelationshipRequestBody", "externalSourceGUID": external_source_guid,
|
1079
|
+
"externalSourceName": external_source_name, "effectiveTime": effective_time,
|
1080
|
+
"forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing
|
1081
|
+
}
|
1082
|
+
core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
|
1083
|
+
egeria_client.link_semantic_definition(guid, glossary_term_guid, glossary_body)
|
1084
|
+
|
1085
|
+
if parent_data_field_guids:
|
1086
|
+
# parent_df_body = {
|
1087
|
+
# "class": "MetadataSourceRequestBody", "externalSourceGUID": external_source_guid,
|
1088
|
+
# "externalSourceName": external_source_name, "effectiveTime": effective_time,
|
1089
|
+
# "forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing
|
793
1090
|
# }
|
794
|
-
#
|
795
|
-
# if data_spec_name_list is not None:
|
796
|
-
# for el in data_spec_value_list:
|
797
|
-
# for key in el:
|
798
|
-
# ds = el[key]
|
799
|
-
# ds_qname = ds.get('known_q_name', None)
|
800
|
-
# ds_guid = ds.get('known_guid', None)
|
801
|
-
# if ds_guid is not None:
|
802
|
-
# msg = f"Adding field to Data Specification `{ds_qname}`"
|
803
|
-
# egeria_client.add_to_collection(ds_guid, guid, member_body)
|
804
|
-
# print_msg(INFO, msg, debug_level)
|
805
|
-
result = add_member_to_data_collections(egeria_client, in_data_spec, display_name,guid )
|
806
|
-
|
807
|
-
core_props += f"\n\n## In Data Specifications\n\n`{data_spec_name_list}`\n\n"
|
808
|
-
|
809
|
-
print_msg(ALWAYS, f"Created Element `{display_name}` with GUID {guid}", debug_level)
|
810
1091
|
|
1092
|
+
# egeria_client.link_nested_data_field(parent_data_field_guid, guid, parent_df_body)
|
1093
|
+
for parent_guid in parent_data_field_guids:
|
1094
|
+
egeria_client.link_nested_data_field(parent_guid, guid)
|
1095
|
+
core_props += f"\n\n## Parent Data Field\n\n{parent_data_field_names}\n\n"
|
1096
|
+
|
1097
|
+
# Link data class
|
1098
|
+
if data_class:
|
1099
|
+
body = {
|
1100
|
+
"class": "RelationshipRequestBody", "externalSourceGUID": external_source_guid,
|
1101
|
+
"externalSourceName": external_source_name, "effectiveTime": effective_time,
|
1102
|
+
"forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing
|
1103
|
+
}
|
1104
|
+
egeria_client.link_data_class_definition(guid, data_class_guid, body)
|
1105
|
+
msg = f"Adding data class `{data_class}` to data field {display_name}"
|
1106
|
+
logger.info(msg)
|
1107
|
+
|
1108
|
+
logger.success(f"Created Element `{display_name}` with guid `{guid}`")
|
1109
|
+
logger.success("=====================================================\n\n")
|
1110
|
+
core_props += "\n___\n\n"
|
811
1111
|
return core_props
|
1112
|
+
|
812
1113
|
else:
|
813
|
-
|
1114
|
+
logger.error(f"Failed to create Term `{display_name}`\n\n___")
|
814
1115
|
return None
|
815
1116
|
|
816
|
-
|
817
1117
|
except Exception as e:
|
818
|
-
|
819
|
-
Console().print_exception(show_locals=True)
|
1118
|
+
logger.error(f"Error performing {command}: {e}\n\n___")
|
820
1119
|
return None
|
821
1120
|
else:
|
822
1121
|
return None
|
823
1122
|
|
824
1123
|
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
#
|
831
|
-
# :param txt: A string representing the input cell to be processed for
|
832
|
-
# extracting glossary-related attributes.
|
833
|
-
# :param directive: an optional string indicating the directive to be used - display, validate or execute
|
834
|
-
# :return: A string summarizing the outcome of the processing.
|
835
|
-
# """
|
836
|
-
#
|
837
|
-
# from md_processing.md_processing_utils.common_md_utils import set_debug_level
|
838
|
-
#
|
839
|
-
# valid = True
|
840
|
-
#
|
841
|
-
# set_debug_level(directive)
|
842
|
-
# known_q_name = None
|
843
|
-
# command, object_type, object_action = extract_command_plus(txt)
|
1124
|
+
@logger.catch
|
1125
|
+
def process_data_class_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1126
|
+
"""
|
1127
|
+
Processes a data class create or update object_action by extracting key attributes such as
|
1128
|
+
spec name, parent_guid, parent_relationship_type, parent_at_end_1, collection_type
|
844
1129
|
|
845
|
-
|
846
|
-
|
847
|
-
|
1130
|
+
:param txt: A string representing the input cell to be processed for
|
1131
|
+
extracting glossary-related attributes.
|
1132
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
1133
|
+
:return: A string summarizing the outcome of the processing.
|
1134
|
+
"""
|
848
1135
|
|
849
|
-
|
1136
|
+
command, object_type, object_action = extract_command_plus(txt)
|
1137
|
+
print(Markdown(f"# {command}\n"))
|
850
1138
|
|
1139
|
+
parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
|
851
1140
|
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
#
|
883
|
-
#
|
884
|
-
#
|
885
|
-
#
|
886
|
-
#
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
#
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
1141
|
+
attributes = parsed_output['attributes']
|
1142
|
+
display_name = attributes['Display Name'].get('value', None)
|
1143
|
+
qualified_name = parsed_output.get('qualified_name', None)
|
1144
|
+
guid = parsed_output.get('guid', None)
|
1145
|
+
valid = parsed_output['valid']
|
1146
|
+
exists = parsed_output['exists']
|
1147
|
+
|
1148
|
+
print(Markdown(parsed_output['display']))
|
1149
|
+
|
1150
|
+
if directive == "display":
|
1151
|
+
|
1152
|
+
return None
|
1153
|
+
elif directive == "validate":
|
1154
|
+
if valid:
|
1155
|
+
print(Markdown(f"==> Validation of {command} completed successfully!\n"))
|
1156
|
+
else:
|
1157
|
+
msg = f"Validation failed for object_action `{command}`\n"
|
1158
|
+
logger.error(msg)
|
1159
|
+
return valid
|
1160
|
+
|
1161
|
+
elif directive == "process":
|
1162
|
+
logger.debug(json.dumps(parsed_output, indent=4))
|
1163
|
+
|
1164
|
+
external_source_guid = attributes.get('External Source Name', {}).get('guid', None)
|
1165
|
+
external_source_name = attributes.get('External Source Name', {}).get('value', None)
|
1166
|
+
effective_time = attributes.get('Effective Time', {}).get('value', None)
|
1167
|
+
for_lineage = attributes.get('For Lineage', {}).get('value', False)
|
1168
|
+
for_duplicate_processing = attributes.get('For Duplicate Processing', {}).get('value', False)
|
1169
|
+
anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
|
1170
|
+
is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', None)
|
1171
|
+
# parent_id = attributes.get('Parent ID', {}).get('value', None)
|
1172
|
+
# parent_guid = attributes['Parent ID'].get('guid', None)
|
1173
|
+
# parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
|
1174
|
+
# parent_relationship_properties = attributes.get('Parent Relationship Properties',{}).get('value', None)
|
1175
|
+
# parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
|
1176
|
+
|
1177
|
+
namespace = attributes.get('Namespace', {}).get('value', None)
|
1178
|
+
description = attributes.get('Description', {}).get('value', None)
|
1179
|
+
version_id = attributes.get('Version Identifier', {}).get('value', None)
|
1180
|
+
|
1181
|
+
###############
|
1182
|
+
match_property_names = attributes.get('Match Property Names', {}).get('value', [])
|
1183
|
+
specification_details = attributes.get('Specification Details', {}).get('value', {})
|
1184
|
+
match_threshold = attributes.get('Match Threshold', {}).get('value', 0)
|
1185
|
+
specification = attributes.get('Specification', {}).get('value', None)
|
1186
|
+
data_type = attributes.get('Data Type', {}).get('value', None)
|
1187
|
+
is_nullable = attributes.get('Is Nullable', {}).get('value', True)
|
1188
|
+
allow_duplicates = attributes.get('Allow Duplicates', {}).get('value', True)
|
1189
|
+
default_value = attributes.get('Default Value', {}).get('value', None)
|
1190
|
+
average_value = attributes.get('Average Value', {}).get('value', None)
|
1191
|
+
value_list = attributes.get('Value List', {}).get('value', None)
|
1192
|
+
value_range_from = attributes.get('Value Range From', {}).get('value', None)
|
1193
|
+
value_range_to = attributes.get('Value Range To', {}).get('value', None)
|
1194
|
+
sample_values = attributes.get('Sample Values', {}).get('value', [])
|
1195
|
+
data_patterns = attributes.get('Data Patterns', {}).get('value', [])
|
1196
|
+
additional_properties = attributes.get('Additional Properties', {}).get('value', {})
|
1197
|
+
|
1198
|
+
###############
|
1199
|
+
aliases = attributes.get('Aliases', {}).get('value', None)
|
1200
|
+
name_patterns = attributes.get('Name Patterns', {}).get('value', None)
|
1201
|
+
|
1202
|
+
min_length = attributes.get('Minimum Length', {}).get('value', None)
|
1203
|
+
length = attributes.get('Length', {}).get('value', None)
|
1204
|
+
precision = attributes.get('Precision', {}).get('value', None)
|
1205
|
+
ordered_values = attributes.get('Ordered Values', {}).get('value', None)
|
1206
|
+
sort_order = attributes.get('Sort Order', {}).get('value', None)
|
1207
|
+
effective_from = attributes.get('Effective From', {}).get('value', None)
|
1208
|
+
effective_to = attributes.get('Effective To', {}).get('value', None)
|
1209
|
+
|
1210
|
+
glossary_term = attributes.get('Glossary Term', {}).get('value', None)
|
1211
|
+
glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
|
1212
|
+
|
1213
|
+
merge_update = attributes.get('Merge Update', {}).get('value', True)
|
1214
|
+
|
1215
|
+
position = attributes.get('Position', {}).get('value', None)
|
1216
|
+
min_cardinality = attributes.get('Minimum Cardinality', {}).get('value', None)
|
1217
|
+
max_cardinality = attributes.get('Maximum Cardinality', {}).get('value', None)
|
1218
|
+
|
1219
|
+
in_data_structure = attributes.get('In Data Structure', {}).get('value', None)
|
1220
|
+
data_structure_guid_list = attributes.get('In Data Structure', {}).get('guid_list', None)
|
1221
|
+
in_data_structure_names = attributes.get('In Data Structure Names', {}).get('name_list', None)
|
1222
|
+
|
1223
|
+
data_class = attributes.get('Data Class', {}).get('value', None)
|
1224
|
+
glossary_term = attributes.get('Glossary Term', {}).get('value', None)
|
1225
|
+
|
1226
|
+
glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
|
1227
|
+
|
1228
|
+
in_data_dictionary = attributes.get('In Data Dictionary', {}).get('value', None)
|
1229
|
+
in_data_dictionary_names = attributes.get('In Data Dictionary', {}).get('name_list', None)
|
1230
|
+
data_dict_guid_list = attributes.get("In Data Dictionary", {}).get("guid_list", None)
|
1231
|
+
|
1232
|
+
containing_data_class = attributes.get('Containing Data Class', {}).get('value', None)
|
1233
|
+
containing_data_class_guids = attributes.get('Containing Data Class', {}).get('guid_list', None)
|
1234
|
+
containing_data_class_names = attributes.get('Containing Data Class', {}).get('name_list', None)
|
1235
|
+
|
1236
|
+
specializes_data_class = attributes.get('Specializes Data Class', {}).get('value', None)
|
1237
|
+
specializes_data_class_guid = attributes.get('Specializes Data Class', {}).get('guid', None)
|
1238
|
+
specializes_data_class_name = attributes.get('Specializes Data Class', {}).get('name', None)
|
1239
|
+
|
1240
|
+
anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
|
1241
|
+
|
1242
|
+
replace_all_props = not merge_update
|
1243
|
+
|
1244
|
+
if not valid:
|
1245
|
+
if exists and object_action == "Create":
|
1246
|
+
msg = (f"Create failed because Element `{display_name}` exists - changing `Create` to `Update` in "
|
1247
|
+
f"processed output\n\n___")
|
1248
|
+
logger.error(msg)
|
1249
|
+
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
1250
|
+
else:
|
1251
|
+
msg = f"Invalid specification - please review\n\n___"
|
1252
|
+
return None
|
1253
|
+
else:
|
1254
|
+
print(Markdown(f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
|
1255
|
+
|
1256
|
+
try:
|
1257
|
+
if object_action == "Update":
|
1258
|
+
if not exists:
|
1259
|
+
logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
|
1260
|
+
f"object_action\n\n___")
|
1261
|
+
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
1262
|
+
|
1263
|
+
# first update the base data class
|
1264
|
+
body = {
|
1265
|
+
"class": "UpdateElementRequestBody", "externalSourceGUID": external_source_guid,
|
1266
|
+
"externalSourceName": external_source_name, "effectiveTime": effective_time,
|
1267
|
+
"forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing, "properties": {
|
1268
|
+
"class": "DataClassProperties", "qualifiedName": qualified_name, "displayName": display_name,
|
1269
|
+
"description": description, "namespace": namespace, "matchPropertyNames": match_property_names,
|
1270
|
+
"matchThreshold": match_threshold, "specification": specification,
|
1271
|
+
"specificationDetails": specification_details, "dataType": data_type,
|
1272
|
+
"allowsDuplicateValues": allow_duplicates, "isNullable": is_nullable,
|
1273
|
+
"defaultValue": default_value, "averageValue": average_value, "valueList": value_list,
|
1274
|
+
"valueRangeFrom": value_range_from, "valueRangeTo": value_range_to,
|
1275
|
+
"sampleValues": sample_values, "dataPatterns": data_patterns,
|
1276
|
+
"additionalProperties": additional_properties
|
1277
|
+
}
|
1278
|
+
}
|
1279
|
+
|
1280
|
+
egeria_client.update_data_class(guid, body, not merge_update)
|
1281
|
+
logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}")
|
1282
|
+
# Update data dictionary membership
|
1283
|
+
update_element_dictionary(qualified_name, {
|
1284
|
+
'guid': guid, 'display_name': display_name
|
1285
|
+
})
|
1286
|
+
core_props = egeria_client.get_data_class_by_guid(guid, None, 'MD')
|
1287
|
+
|
1288
|
+
# Sync membership in data dictionaries
|
1289
|
+
update_data_collection_memberships(egeria_client, object_type, data_dict_guid_list, "DataDictionary",
|
1290
|
+
guid, display_name, replace_all_props)
|
1291
|
+
logger.success(f"Updating data dictionaries `{in_data_dictionary_names}`")
|
1292
|
+
core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
|
1293
|
+
|
1294
|
+
# Sync data field related elements (data structure, parent data fields, terms, data classes
|
1295
|
+
sync_data_class_rel_elements(egeria_client, containing_data_class_guids, glossary_term_guid,
|
1296
|
+
specializes_data_class_guid, guid, display_name, replace_all_props)
|
1297
|
+
|
1298
|
+
core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
|
1299
|
+
core_props += f"\n\n## Containing Data Class\n\n{containing_data_class_names}\n\n"
|
1300
|
+
core_props += "\n___\n\n"
|
1301
|
+
|
1302
|
+
# Update data classes
|
1303
|
+
logger.success(f"Updated Element `{display_name}`\n\n___")
|
1304
|
+
return core_props
|
1305
|
+
|
1306
|
+
elif object_action == "Create":
|
1307
|
+
if valid is False and exists:
|
1308
|
+
logger.error(
|
1309
|
+
f"\nData Class `{display_name}` already exists and result document updated changing `Create` "
|
1310
|
+
f"to `Update` in processed output\n\n___")
|
1311
|
+
return update_a_command(txt, object_action, object_type, qualified_name, guid)
|
1312
|
+
else:
|
1313
|
+
# First lets create the data class
|
1314
|
+
body = {
|
1315
|
+
"class": "NewElementRequestBody", "properties": {
|
1316
|
+
"class": "DataClassProperties", "qualifiedName": qualified_name,
|
1317
|
+
"displayName": display_name, "description": description, "namespace": namespace,
|
1318
|
+
"matchPropertyNames": match_property_names, "matchThreshold": match_threshold,
|
1319
|
+
"specification": specification, "specificationDetails": specification_details,
|
1320
|
+
"dataType": data_type, "allowsDuplicateValues": allow_duplicates, "isNullable": is_nullable,
|
1321
|
+
"defaultValue": default_value, "averageValue": average_value, "valueList": value_list,
|
1322
|
+
"valueRangeFrom": value_range_from, "valueRangeTo": value_range_to,
|
1323
|
+
"sampleValues": sample_values, "dataPatterns": data_patterns,
|
1324
|
+
"additionalProperties": additional_properties
|
1325
|
+
}
|
1326
|
+
}
|
1327
|
+
guid = egeria_client.create_data_class(body)
|
1328
|
+
if guid:
|
1329
|
+
# Now update our element dictionary with the new information
|
1330
|
+
update_element_dictionary(qualified_name, {
|
1331
|
+
'guid': guid, 'display_name': display_name
|
1332
|
+
})
|
1333
|
+
# Start assembling the information we will present back out
|
1334
|
+
core_props = egeria_client.get_data_class_by_guid(guid, None, 'MD')
|
1335
|
+
|
1336
|
+
# Add the field to any data dictionaries
|
1337
|
+
if in_data_dictionary:
|
1338
|
+
logger.info(f"Will add to data dictionary `{in_data_dictionary}`")
|
1339
|
+
add_member_to_data_collections(egeria_client, data_dict_guid_list, display_name, guid)
|
1340
|
+
core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
|
1341
|
+
|
1342
|
+
if glossary_term:
|
1343
|
+
if glossary_term_guid:
|
1344
|
+
glossary_body = {
|
1345
|
+
"class": "RelationshipRequestBody", "externalSourceGUID": external_source_guid,
|
1346
|
+
"externalSourceName": external_source_name, "effectiveTime": effective_time,
|
1347
|
+
"forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
|
1351
|
+
egeria_client.link_semantic_definition(guid, glossary_term_guid, glossary_body)
|
1352
|
+
|
1353
|
+
if containing_data_class_guids:
|
1354
|
+
for dc_guid in containing_data_class_guids:
|
1355
|
+
egeria_client.link_nested_data_class(dc_guid, guid)
|
1356
|
+
core_props += f"\n\n## Parent Data Field\n\n{containing_data_class_names}\n\n"
|
1357
|
+
|
1358
|
+
if specializes_data_class_guid:
|
1359
|
+
egeria_client.link_specialist_data_class(specializes_data_class_guid, guid)
|
1360
|
+
core_props += f"\n\n## Specialized Data Field\n\n{specializes_data_class_name}\n\n"
|
1361
|
+
|
1362
|
+
logger.success(f"Created Element `{display_name}`")
|
1363
|
+
core_props += "\n___\n\n"
|
1364
|
+
return core_props
|
1365
|
+
|
1366
|
+
else:
|
1367
|
+
logger.error(f"Failed to create Term `{display_name}`\n\n___")
|
1368
|
+
return None
|
1369
|
+
|
1370
|
+
except Exception as e:
|
1371
|
+
logger.error(f"Error performing {command}: {e}\n\n___")
|
1372
|
+
return None
|
1373
|
+
else:
|
1374
|
+
return None
|
1375
|
+
|
1376
|
+
|
1377
|
+
@logger.catch
|
1378
|
+
def process_data_collection_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
|
1379
|
+
str]:
|
980
1380
|
"""
|
981
1381
|
Processes a Data Dictionary list object_action by extracting key attributes such as
|
982
1382
|
search string from the given text.
|
@@ -986,197 +1386,279 @@ def process_data_dict_list_command(egeria_client: EgeriaTech, txt: str, directiv
|
|
986
1386
|
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
987
1387
|
:return: A string summarizing the outcome of the processing.
|
988
1388
|
"""
|
989
|
-
|
1389
|
+
command, object_type, object_action = extract_command_plus(txt)
|
1390
|
+
print(Markdown(f"# {command}\n"))
|
1391
|
+
if object_type in ["Data Dictionary", "Data Dictionaries", "DataDict", "DataDictionary"]:
|
1392
|
+
col_type = "DataDictionary"
|
1393
|
+
elif object_type in ["Data Specification", "Data Specifications", "Data Specs"]:
|
1394
|
+
col_type = "DataSpec"
|
1395
|
+
else:
|
1396
|
+
col_type = "Collection"
|
990
1397
|
|
991
|
-
|
992
|
-
|
1398
|
+
parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
|
1399
|
+
|
1400
|
+
|
1401
|
+
|
1402
|
+
valid = parsed_output['valid']
|
1403
|
+
print(Markdown(f"Performing {command}"))
|
1404
|
+
print(Markdown(parsed_output['display']))
|
1405
|
+
|
1406
|
+
attr = parsed_output.get('attributes',{})
|
1407
|
+
effective_time = attr.get('effectiveTime', {}).get('value', None)
|
1408
|
+
as_of_time = attr.get('asOfTime', {}).get('value', None)
|
1409
|
+
for_duplicate_processing = attr.get('forDuplicateProcessing', {}).get('value', False)
|
1410
|
+
for_lineage = attr.get('forLineage',{}).get('value', False)
|
1411
|
+
limit_result_by_status = attr.get('limitResultsByStatus',{}).get('value', ['ACTIVE'])
|
1412
|
+
sequencing_property = attr.get('sequencingProperty',{}).get('value',"qualifiedName" )
|
1413
|
+
sequencing_order = attr.get('sequencingOrder',{}).get('value', "PROPERTY_ASCENDING")
|
1414
|
+
search_string = attr.get('Search String', {}).get('value', '*')
|
1415
|
+
output_format = attr.get('Output Format', {}).get('value', 'LIST')
|
1416
|
+
detailed = attr.get('Detailed', {}).get('value', False)
|
1417
|
+
|
1418
|
+
if directive == "display":
|
1419
|
+
return None
|
1420
|
+
elif directive == "validate":
|
1421
|
+
if valid:
|
1422
|
+
print(Markdown(f"==> Validation of {command} completed successfully!\n"))
|
1423
|
+
else:
|
1424
|
+
msg = f"Validation failed for object_action `{command}`\n"
|
1425
|
+
logger.error(msg)
|
1426
|
+
return valid
|
1427
|
+
|
1428
|
+
elif directive == "process":
|
1429
|
+
try:
|
1430
|
+
if not valid: # First validate the command before we process it
|
1431
|
+
msg = f"Validation failed for {object_action} `{object_type}`\n"
|
1432
|
+
logger.error(msg)
|
1433
|
+
return None
|
1434
|
+
|
1435
|
+
list_md = f"\n# `{col_type}` with filter: `{search_string}`\n\n"
|
1436
|
+
body = {
|
1437
|
+
"class": "FilterRequestBody",
|
1438
|
+
"asOfTime": as_of_time,
|
1439
|
+
"effectiveTime": effective_time,
|
1440
|
+
"forLineage": for_lineage,
|
1441
|
+
"forDuplicateProcessing": for_duplicate_processing,
|
1442
|
+
"limitResultsByStatus": limit_result_by_status,
|
1443
|
+
"sequencingOrder": sequencing_order,
|
1444
|
+
"sequencingProperty": sequencing_property,
|
1445
|
+
"filter": search_string,
|
1446
|
+
}
|
1447
|
+
|
1448
|
+
struct = egeria_client.find_collections_w_body(body, col_type, output_format=output_format)
|
1449
|
+
if output_format == "DICT":
|
1450
|
+
list_md += f"```\n{json.dumps(struct, indent=4)}\n```\n"
|
1451
|
+
else:
|
1452
|
+
list_md += struct
|
1453
|
+
logger.info(f"Wrote `{col_type}` for search string: `{search_string}`")
|
1454
|
+
|
1455
|
+
return list_md
|
1456
|
+
|
1457
|
+
except Exception as e:
|
1458
|
+
logger.error(f"Error performing {command}: {e}")
|
1459
|
+
console.print_exception(show_locals=True)
|
1460
|
+
return None
|
1461
|
+
else:
|
1462
|
+
return None
|
1463
|
+
|
1464
|
+
|
1465
|
+
def process_data_structure_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
|
1466
|
+
str]:
|
1467
|
+
"""
|
1468
|
+
Processes a Data Dictionary list object_action by extracting key attributes such as
|
1469
|
+
search string from the given text.
|
1470
|
+
|
1471
|
+
:param txt: A string representing the input cell to be processed for
|
1472
|
+
extracting term-related attributes.
|
1473
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
1474
|
+
:return: A string summarizing the outcome of the processing.
|
1475
|
+
"""
|
993
1476
|
command, object_type, object_action = extract_command_plus(txt)
|
1477
|
+
print(Markdown(f"# {command}\n"))
|
994
1478
|
|
995
|
-
|
996
|
-
set_debug_level(directive)
|
1479
|
+
parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
|
997
1480
|
|
998
|
-
|
1481
|
+
attributes = parsed_output['attributes']
|
1482
|
+
|
1483
|
+
valid = parsed_output['valid']
|
1484
|
+
print(Markdown(f"Performing {command}"))
|
999
1485
|
print(Markdown(parsed_output['display']))
|
1486
|
+
|
1487
|
+
if directive == "display":
|
1488
|
+
return None
|
1489
|
+
elif directive == "validate":
|
1490
|
+
if valid:
|
1491
|
+
print(Markdown(f"==> Validation of {command} completed successfully!\n"))
|
1492
|
+
else:
|
1493
|
+
msg = f"Validation failed for object_action `{command}`\n"
|
1494
|
+
logger.error(msg)
|
1495
|
+
return valid
|
1496
|
+
|
1497
|
+
elif directive == "process":
|
1498
|
+
attributes = parsed_output['attributes']
|
1499
|
+
search_string = attributes.get('Search String', {}).get('value', '*')
|
1500
|
+
output_format = attributes.get('Output Format', {}).get('value', 'LIST')
|
1501
|
+
detailed = attributes.get('Detailed', {}).get('value', False)
|
1502
|
+
|
1503
|
+
try:
|
1504
|
+
if not valid: # First validate the command before we process it
|
1505
|
+
msg = f"Validation failed for {object_action} `{object_type}`\n"
|
1506
|
+
logger.error(msg)
|
1507
|
+
return None
|
1508
|
+
|
1509
|
+
list_md = f"\n# `{object_type}` with filter: `{search_string}`\n\n"
|
1510
|
+
struct = egeria_client.find_data_structures(search_string, output_format=output_format)
|
1511
|
+
|
1512
|
+
if output_format == "DICT":
|
1513
|
+
list_md += f"```\n{json.dumps(struct, indent=4)}\n```\n"
|
1514
|
+
else:
|
1515
|
+
list_md += struct
|
1516
|
+
logger.info(f"Wrote `{object_type}` for search string: `{search_string}`")
|
1517
|
+
|
1518
|
+
return list_md
|
1519
|
+
|
1520
|
+
except Exception as e:
|
1521
|
+
logger.error(f"Error performing {command}: {e}")
|
1522
|
+
console.print_exception(show_locals=True)
|
1523
|
+
return None
|
1524
|
+
else:
|
1525
|
+
return None
|
1526
|
+
|
1527
|
+
|
1528
|
+
def process_data_field_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1529
|
+
"""
|
1530
|
+
Processes a Data Dictionary list object_action by extracting key attributes such as
|
1531
|
+
search string from the given text.
|
1532
|
+
|
1533
|
+
:param txt: A string representing the input cell to be processed for
|
1534
|
+
extracting term-related attributes.
|
1535
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
1536
|
+
:return: A string summarizing the outcome of the processing.
|
1537
|
+
"""
|
1538
|
+
command, object_type, object_action = extract_command_plus(txt)
|
1539
|
+
print(Markdown(f"# {command}\n"))
|
1540
|
+
|
1541
|
+
parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
|
1542
|
+
|
1543
|
+
attributes = parsed_output['attributes']
|
1544
|
+
|
1000
1545
|
valid = parsed_output['valid']
|
1546
|
+
print(Markdown(f"Performing {command}"))
|
1547
|
+
print(Markdown(parsed_output['display']))
|
1001
1548
|
|
1002
1549
|
if directive == "display":
|
1003
1550
|
return None
|
1004
1551
|
elif directive == "validate":
|
1005
1552
|
if valid:
|
1006
|
-
|
1553
|
+
print(Markdown(f"==> Validation of {command} completed successfully!\n"))
|
1007
1554
|
else:
|
1008
|
-
msg = f"Validation failed for
|
1009
|
-
|
1555
|
+
msg = f"Validation failed for object_action `{command}`\n"
|
1556
|
+
logger.error(msg)
|
1010
1557
|
return valid
|
1558
|
+
|
1011
1559
|
elif directive == "process":
|
1012
1560
|
attributes = parsed_output['attributes']
|
1013
1561
|
search_string = attributes.get('Search String', {}).get('value', '*')
|
1014
1562
|
output_format = attributes.get('Output Format', {}).get('value', 'LIST')
|
1015
1563
|
detailed = attributes.get('Detailed', {}).get('value', False)
|
1564
|
+
as_of_time = attributes.get('AsOfTime', {}).get('value', None)
|
1565
|
+
effective_time = attributes.get('Effective Time', {}).get('value', None)
|
1566
|
+
sort_order = attributes.get('Sort Order', {}).get('value', None)
|
1567
|
+
order_property = attributes.get('Order Property', {}).get('value', None)
|
1568
|
+
starts_with = attributes.get('Start With', {}).get('value', True)
|
1569
|
+
ends_with = attributes.get('End With', {}).get('value', False)
|
1570
|
+
ignore_case = attributes.get('Ignore Case', {}).get('value', False)
|
1571
|
+
start_from = attributes.get('Start From', {}).get('value', 0)
|
1572
|
+
page_size = attributes.get('Page Size', {}).get('value', None)
|
1016
1573
|
|
1017
1574
|
try:
|
1018
1575
|
if not valid: # First validate the command before we process it
|
1019
1576
|
msg = f"Validation failed for {object_action} `{object_type}`\n"
|
1020
|
-
|
1577
|
+
logger.error(msg)
|
1021
1578
|
return None
|
1022
1579
|
|
1023
|
-
list_md = f"\n#
|
1580
|
+
list_md = f"\n# `{object_type}` with filter: `{search_string}`\n\n"
|
1581
|
+
body = {
|
1582
|
+
"class": "FilterRequestBody", "asOfTime": as_of_time, "effectiveTime": effective_time,
|
1583
|
+
"forLineage": False, "forDuplicateProcessing": False, "limitResultsByStatus": ["ACTIVE"],
|
1584
|
+
"sequencingOrder": sort_order, "sequencingProperty": order_property, "filter": search_string,
|
1585
|
+
}
|
1586
|
+
struct = egeria_client.find_data_fields_w_body(body, start_from, page_size, starts_with, ends_with,
|
1587
|
+
ignore_case, output_format)
|
1588
|
+
|
1024
1589
|
if output_format == "DICT":
|
1025
|
-
|
1026
|
-
list_md += f"```{json.dumps(struct, indent=4)}```\n"
|
1590
|
+
list_md += f"```\n{json.dumps(struct, indent=4)}\n```\n"
|
1027
1591
|
else:
|
1028
|
-
list_md +=
|
1029
|
-
|
1592
|
+
list_md += struct
|
1593
|
+
logger.info(f"Wrote `{object_type}` for search string: `{search_string}`")
|
1030
1594
|
|
1031
1595
|
return list_md
|
1032
1596
|
|
1033
1597
|
except Exception as e:
|
1034
|
-
|
1598
|
+
logger.error(f"Error performing {command}: {e}")
|
1035
1599
|
console.print_exception(show_locals=True)
|
1036
1600
|
return None
|
1037
1601
|
else:
|
1038
1602
|
return None
|
1039
1603
|
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
#
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
#
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
# set_debug_level(directive)
|
1102
|
-
# print(Markdown(f"{pre_command} `{object_action}` with directive: `{directive}`"))
|
1103
|
-
#
|
1104
|
-
# term_name = process_simple_attribute(txt, TERM_NAME_LABELS, ERROR)
|
1105
|
-
# output_format = process_simple_attribute(txt, OUTPUT_LABELS)
|
1106
|
-
# output_format = output_format.upper() if output_format else "MD"
|
1107
|
-
# if output_format not in ELEMENT_OUTPUT_FORMATS:
|
1108
|
-
# print_msg(WARNING, f"Output format {output_format} not recognized, using MD", debug_level)
|
1109
|
-
# output_format = "MD"
|
1110
|
-
#
|
1111
|
-
# if term_name is None:
|
1112
|
-
# print_msg(ERROR, "No term name found", debug_level)
|
1113
|
-
# return None
|
1114
|
-
#
|
1115
|
-
# known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, "Term",
|
1116
|
-
# TERM_NAME_LABELS, txt,
|
1117
|
-
# EXISTS_REQUIRED, None)
|
1118
|
-
# if not term_exists:
|
1119
|
-
# print_msg(ERROR, f"Term {term_name} not found", debug_level)
|
1120
|
-
# return None
|
1121
|
-
#
|
1122
|
-
# if directive == "display":
|
1123
|
-
# print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
|
1124
|
-
# output_format}"))
|
1125
|
-
# return None
|
1126
|
-
# elif directive == "validate":
|
1127
|
-
# print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
|
1128
|
-
# output_format}"))
|
1129
|
-
# return True
|
1130
|
-
# elif directive == "process":
|
1131
|
-
# print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
|
1132
|
-
# output_format}"))
|
1133
|
-
# return egeria_client.get_term_history(known_guid, output_format=output_format)
|
1134
|
-
#
|
1135
|
-
#
|
1136
|
-
# def process_term_revision_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") ->
|
1137
|
-
# Optional[str]:
|
1138
|
-
# """
|
1139
|
-
# Processes a term revision history object_action by extracting key attributes such as
|
1140
|
-
# term name and output format from the given text.
|
1141
|
-
#
|
1142
|
-
# :param txt: A string representing the input cell to be processed for
|
1143
|
-
# extracting term-related attributes.
|
1144
|
-
# :param directive: an optional string indicating the directive to be used - display, validate or execute
|
1145
|
-
# :return: A string summarizing the outcome of the processing.
|
1146
|
-
# """
|
1147
|
-
# from md_processing.md_processing_utils.common_md_utils import set_debug_level
|
1148
|
-
#
|
1149
|
-
# object_action = extract_command(txt)
|
1150
|
-
# set_debug_level(directive)
|
1151
|
-
# print(Markdown(f"{pre_command} `{object_action}` with directive: `{directive}`"))
|
1152
|
-
#
|
1153
|
-
# term_name = process_simple_attribute(txt, TERM_NAME_LABELS, ERROR)
|
1154
|
-
# output_format = process_simple_attribute(txt, OUTPUT_LABELS)
|
1155
|
-
# output_format = output_format.upper() if output_format else "MD"
|
1156
|
-
# if output_format not in ELEMENT_OUTPUT_FORMATS:
|
1157
|
-
# print_msg(WARNING, f"Output format {output_format} not recognized, using MD", debug_level)
|
1158
|
-
# output_format = "MD"
|
1159
|
-
#
|
1160
|
-
# if term_name is None:
|
1161
|
-
# print_msg(ERROR, "No term name found", debug_level)
|
1162
|
-
# return None
|
1163
|
-
#
|
1164
|
-
# known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, "Term",
|
1165
|
-
# TERM_NAME_LABELS, txt,
|
1166
|
-
# EXISTS_REQUIRED, None)
|
1167
|
-
# if not term_exists:
|
1168
|
-
# print_msg(ERROR, f"Term {term_name} not found", debug_level)
|
1169
|
-
# return None
|
1170
|
-
#
|
1171
|
-
# if directive == "display":
|
1172
|
-
# print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
|
1173
|
-
# output_format}"))
|
1174
|
-
# return None
|
1175
|
-
# elif directive == "validate":
|
1176
|
-
# print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
|
1177
|
-
# output_format}"))
|
1178
|
-
# return True
|
1179
|
-
# elif directive == "process":
|
1180
|
-
# print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
|
1181
|
-
# output_format}"))
|
1182
|
-
# return egeria_client.get_term_revision_history(known_guid, output_format=output_format)
|
1604
|
+
|
1605
|
+
def process_data_class_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1606
|
+
"""
|
1607
|
+
Processes a Data Dictionary list object_action by extracting key attributes such as
|
1608
|
+
search string from the given text.
|
1609
|
+
|
1610
|
+
:param txt: A string representing the input cell to be processed for
|
1611
|
+
extracting term-related attributes.
|
1612
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
1613
|
+
:return: A string summarizing the outcome of the processing.
|
1614
|
+
"""
|
1615
|
+
command, object_type, object_action = extract_command_plus(txt)
|
1616
|
+
print(Markdown(f"# {command}\n"))
|
1617
|
+
|
1618
|
+
parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
|
1619
|
+
|
1620
|
+
attributes = parsed_output['attributes']
|
1621
|
+
|
1622
|
+
valid = parsed_output['valid']
|
1623
|
+
print(Markdown(f"Performing {command}"))
|
1624
|
+
print(Markdown(parsed_output['display']))
|
1625
|
+
|
1626
|
+
if directive == "display":
|
1627
|
+
return None
|
1628
|
+
elif directive == "validate":
|
1629
|
+
if valid:
|
1630
|
+
print(Markdown(f"==> Validation of {command} completed successfully!\n"))
|
1631
|
+
else:
|
1632
|
+
msg = f"Validation failed for object_action `{command}`\n"
|
1633
|
+
logger.error(msg)
|
1634
|
+
return valid
|
1635
|
+
|
1636
|
+
elif directive == "process":
|
1637
|
+
attributes = parsed_output['attributes']
|
1638
|
+
search_string = attributes.get('Search String', {}).get('value', '*')
|
1639
|
+
output_format = attributes.get('Output Format', {}).get('value', 'LIST')
|
1640
|
+
detailed = attributes.get('Detailed', {}).get('value', False)
|
1641
|
+
|
1642
|
+
try:
|
1643
|
+
if not valid: # First validate the command before we process it
|
1644
|
+
msg = f"Validation failed for {object_action} `{object_type}`\n"
|
1645
|
+
logger.error(msg)
|
1646
|
+
return None
|
1647
|
+
|
1648
|
+
list_md = f"\n# `{object_type}` with filter: `{search_string}`\n\n"
|
1649
|
+
struct = egeria_client.find_data_classes(search_string, output_format=output_format)
|
1650
|
+
|
1651
|
+
if output_format == "DICT":
|
1652
|
+
list_md += f"```\n{json.dumps(struct, indent=4)}\n```\n"
|
1653
|
+
else:
|
1654
|
+
list_md += struct
|
1655
|
+
logger.info(f"Wrote `{object_type}` for search string: `{search_string}`")
|
1656
|
+
|
1657
|
+
return list_md
|
1658
|
+
|
1659
|
+
except Exception as e:
|
1660
|
+
logger.error(f"Error performing {command}: {e}")
|
1661
|
+
console.print_exception(show_locals=True)
|
1662
|
+
return None
|
1663
|
+
else:
|
1664
|
+
return None
|