pyegeria 5.3.10__py3-none-any.whl → 5.4.0.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. commands/cat/debug_log.2025-06-05_20-24-18_123924.log.zip +0 -0
  2. commands/cat/debug_log.2025-06-10_08-45-03_929921.log.zip +0 -0
  3. commands/cat/debug_log.2025-06-11_09-57-21_247890.log.zip +0 -0
  4. commands/cat/debug_log.2025-06-12_16-14-31_212042.log.zip +0 -0
  5. commands/cat/dr_egeria_md.py +32 -5
  6. commands/cat/list_collections.py +10 -4
  7. commands/cat/list_data_designer.py +171 -0
  8. md_processing/__init__.py +7 -2
  9. md_processing/data/commands.json +4666 -848
  10. md_processing/md_commands/data_designer_commands.py +840 -557
  11. md_processing/md_commands/solution_architect_commands.py +985 -0
  12. md_processing/md_processing_utils/common_md_proc_utils.py +262 -89
  13. md_processing/md_processing_utils/common_md_utils.py +11 -4
  14. md_processing/md_processing_utils/md_processing_constants.py +18 -16
  15. pyegeria/_client.py +39 -0
  16. pyegeria/classification_manager_omvs.py +1 -1
  17. pyegeria/collection_manager_omvs.py +248 -188
  18. pyegeria/data_designer_omvs.py +217 -9
  19. pyegeria/governance_officer_omvs.py +2349 -0
  20. pyegeria/output_formatter.py +24 -12
  21. pyegeria/solution_architect_omvs.py +4219 -1084
  22. pyegeria/utils.py +15 -2
  23. {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dev2.dist-info}/METADATA +2 -1
  24. {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dev2.dist-info}/RECORD +27 -62
  25. {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dev2.dist-info}/entry_points.txt +3 -0
  26. commands/cat/.DS_Store +0 -0
  27. md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
  28. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
  29. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
  30. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
  31. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
  32. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
  33. md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
  34. md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
  35. md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
  36. md_processing/dr_egeria_inbox/cat_test.md +0 -100
  37. md_processing/dr_egeria_inbox/data_field.md +0 -54
  38. md_processing/dr_egeria_inbox/data_spec.md +0 -77
  39. md_processing/dr_egeria_inbox/data_spec_test.md +0 -2406
  40. md_processing/dr_egeria_inbox/data_test.md +0 -86
  41. md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
  42. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
  43. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -313
  44. md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
  45. md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
  46. md_processing/dr_egeria_inbox/glossary_test1.md +0 -324
  47. md_processing/dr_egeria_inbox/rel.md +0 -8
  48. md_processing/dr_egeria_inbox/sb.md +0 -119
  49. md_processing/dr_egeria_inbox/search_test.md +0 -39
  50. md_processing/dr_egeria_inbox/solution-components.md +0 -154
  51. md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
  52. md_processing/dr_egeria_inbox/synonym_test.md +0 -42
  53. md_processing/dr_egeria_inbox/t1.md +0 -0
  54. md_processing/dr_egeria_inbox/t2.md +0 -268
  55. md_processing/dr_egeria_outbox/processed-2025-05-15 19:52-data_test.md +0 -94
  56. md_processing/dr_egeria_outbox/processed-2025-05-16 07:39-data_test.md +0 -88
  57. md_processing/dr_egeria_outbox/processed-2025-05-17 16:01-data_field.md +0 -56
  58. md_processing/dr_egeria_outbox/processed-2025-05-18 15:51-data_test.md +0 -103
  59. md_processing/dr_egeria_outbox/processed-2025-05-18 16:47-data_test.md +0 -94
  60. md_processing/dr_egeria_outbox/processed-2025-05-19 07:14-data_test.md +0 -96
  61. md_processing/dr_egeria_outbox/processed-2025-05-19 07:20-data_test.md +0 -100
  62. md_processing/dr_egeria_outbox/processed-2025-05-19 07:22-data_test.md +0 -88
  63. md_processing/dr_egeria_outbox/processed-2025-05-19 09:26-data_test.md +0 -91
  64. md_processing/dr_egeria_outbox/processed-2025-05-19 10:27-data_test.md +0 -91
  65. md_processing/dr_egeria_outbox/processed-2025-05-19 14:04-data_test.md +0 -91
  66. md_processing/md_commands/blueprint_commands.py +0 -303
  67. pyegeria/.DS_Store +0 -0
  68. {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dev2.dist-info}/LICENSE +0 -0
  69. {pyegeria-5.3.10.dist-info → pyegeria-5.4.0.dev2.dist-info}/WHEEL +0 -0
@@ -2,101 +2,328 @@
2
2
  This file contains term-related object_action functions for processing Egeria Markdown
3
3
  """
4
4
  import json
5
- import os
5
+ import sys
6
6
  from typing import Optional
7
7
 
8
+ from loguru import logger
8
9
  from rich import print
9
10
  from rich.console import Console
10
11
  from rich.markdown import Markdown
11
12
 
12
- from md_processing.md_processing_utils.common_md_proc_utils import (parse_user_command, sync_data_dict_membership,
13
- sync_data_spec_membership, sync_data_structure_membership, sync_term_links, sync_parent_data_field)
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)
13
+ from md_processing.md_processing_utils.common_md_proc_utils import (parse_upsert_command, parse_view_command)
14
+ from md_processing.md_processing_utils.common_md_utils import update_element_dictionary
15
+ from md_processing.md_processing_utils.extraction_utils import (extract_command_plus, update_a_command)
17
16
  from md_processing.md_processing_utils.md_processing_constants import (load_commands, ERROR)
18
17
  from pyegeria import DEBUG_LEVEL, body_slimmer
19
18
  from pyegeria.egeria_tech_client import EgeriaTech
20
- from pyegeria.md_processing_utils import ALWAYS, INFO
21
-
22
19
 
23
20
  load_commands('commands.json')
24
21
  debug_level = DEBUG_LEVEL
25
22
 
26
23
  console = Console(width=int(200))
27
24
 
28
- def add_member_to_data_collections(egeria_client: EgeriaTech, in_data_collection:dict, display_name: str, guid:str )-> bool:
25
+ log_format = "D {time} | {level} | {function} | {line} | {message} | {extra}"
26
+ logger.remove()
27
+ logger.add(sys.stderr, level="INFO", format=log_format, colorize=True)
28
+ logger.add("debug_log.log", rotation="1 day", retention="1 week", compression="zip", level="TRACE", format=log_format,
29
+ colorize=True)
30
+
31
+
32
+ #
33
+ # Helper functions for the data designer commands
34
+ #
35
+ @logger.catch
36
+ def add_member_to_data_collections(egeria_client: EgeriaTech, collection_list: list, display_name: str,
37
+ guid: str) -> None:
29
38
  """
30
39
  Add member to data dictionaries and data specifications.
31
40
  """
41
+ body = {
42
+ "class": "CollectionMembershipProperties", "membershipRationale": "User Specified",
43
+ "notes": "Added by Dr.Egeria"
44
+ }
32
45
  try:
33
- for collection in in_data_collection.keys():
34
- collection_name = collection
35
- collection_valid = in_data_collection[collection].get('el_valid', False)
36
- collection_guid = in_data_collection[collection].get('guid', None)
37
- if collection_guid and collection_valid:
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
46
+ for collection in collection_list:
47
+ egeria_client.add_to_collection(collection, guid, body)
48
+ msg = f"Added `{display_name}` member to `{collection}`"
49
+ logger.info(msg)
50
+ return
42
51
 
43
52
  except Exception as e:
44
53
  console.print_exception()
45
54
 
46
55
 
47
- def find_memberships_in_collection_type(egeria_client: EgeriaTech, collection_type: str, guid: str) -> list:
48
- """ Find the collections of a particular type that the element is a member of"""
49
- collection_guid_list = []
50
- collections = egeria_client.get_related_elements(guid, "CollectionMembership", "Collection")
51
- for collection in collections:
52
- print(collection["relationshipHeader"]['guid'])
53
- related_el_guid = collection["relatedElement"]['elementHeader']["guid"]
54
- coll_type = collection["relatedElement"]['properties'].get('collectionType', None)
55
- print(coll_type)
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
56
+ @logger.catch
57
+ def remove_member_from_data_collections(egeria_client: EgeriaTech, collection_list: list, display_name: str,
58
+ guid: str) -> None:
59
+ try:
60
+ for collection in collection_list:
61
+ egeria_client.remove_from_collection(collection, guid)
62
+ msg = f"Removed `{display_name}` member from `{collection}`"
63
+ logger.info(msg)
64
+ return
61
65
 
66
+ except Exception as e:
67
+ console.print_exception()
62
68
 
63
69
 
70
+ @logger.catch
71
+ def update_data_collection_memberships(egeria_client: EgeriaTech, entity_type: str, guid_list: list,
72
+ collection_class: str, guid: str, display_name: str,
73
+ replace_all_props: bool = True) -> None:
74
+ """ update the collection membership of the element
64
75
 
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
76
+ If replace_all_props is set to True, all existing memberships are removed and new memberships are added.
77
+ If replace_all_props is set to False, only the new memberships are added.
78
+ """
68
79
 
80
+ if replace_all_props:
81
+ match entity_type:
82
+ case "Data Specification":
83
+ get_command = egeria_client.get_collection_by_guid
84
+ case "Data Structure":
85
+ get_command = egeria_client.get_data_structure_by_guid
86
+ case "Data Field":
87
+ get_command = egeria_client.get_data_field_by_guid
88
+ case "Data Class":
89
+ get_command = egeria_client.get_data_class_by_guid
90
+
91
+ coll_list = egeria_client.get_data_memberships(get_command, guid)
92
+ if coll_list is None:
93
+ logger.error("Internal Error -> the collection list cannot be None")
94
+ return
95
+ # compare the existing collections to desired collections
96
+ if collection_class == "DataDictionary":
97
+ as_is = set(coll_list.get("DictList", {}))
98
+ elif collection_class == "DataSpec":
99
+ as_is = set(coll_list.get("SpecList", {}))
100
+
101
+ dict_set = set(coll_list.get("DictList", {}))
102
+ spec_set = set(coll_list.get("SpecList", {}))
103
+ to_be_set = set(guid_list) if guid_list is not None else set()
104
+ logger.debug(f"as_is: {as_is}")
105
+ logger.debug(f"to_be_set: {to_be_set}")
106
+
107
+ # Remove membership for collections that are in the as-is but not in the to-be
108
+ to_remove = as_is - to_be_set
109
+ logger.debug(f"to_remove: {to_remove}")
110
+ if len(to_remove) > 0:
111
+ remove_member_from_data_collections(egeria_client, to_remove, display_name, guid)
112
+
113
+ # add membership for collections that are in the to-be but are not in the as-is
114
+ to_add = to_be_set - as_is
115
+ logger.debug(f"to_add: {to_add}")
116
+ if len(to_add) > 0:
117
+ add_member_to_data_collections(egeria_client, to_add, display_name, guid)
118
+ else:
119
+ add_member_to_data_collections(egeria_client, guid_list, display_name, guid)
120
+
121
+
122
+ # @logger.catch
123
+
124
+
125
+ @logger.catch
126
+ def add_field_to_data_structures(egeria_client: EgeriaTech, display_name: str, struct_list: list, guid) -> None:
127
+ """
128
+ Add data field to data structures.
129
+ """
130
+
131
+ try:
132
+ for structure_guid in struct_list:
133
+ egeria_client.link_member_data_field(structure_guid, guid, None)
134
+ msg = f"Added `{display_name}` to structure `{structure_guid}`"
135
+ logger.info(msg)
136
+ return
137
+
138
+ except Exception as e:
139
+ console.print_exception()
140
+
141
+
142
+ @logger.catch
143
+ def remove_field_from_data_structures(egeria_client: EgeriaTech, display_name: str, struct_list: list,
144
+ guid: str) -> None:
145
+ """Remove a data field from a list of data structures."""
146
+ try:
147
+ for structure_guid in struct_list:
148
+ egeria_client.detach_member_data_field(structure_guid, guid, None)
149
+ msg = f"Removed `{display_name}` from structure `{structure_guid}`"
150
+ logger.info(msg)
151
+ return
152
+
153
+ except Exception as e:
154
+ console.print_exception()
69
155
 
70
- # def update_term_categories(egeria_client: EgeriaTech, term_guid: str, current_categories: List[str],
71
- # new_categories: List[str]) -> None:
72
- # """
73
- # Updates the categories of a term.
74
- #
75
- # Args:
76
- # egeria_client: The Egeria client to use for the update.
77
- # term_guid: The GUID of the term to update.
78
- # current_categories: The current categories of the term.
79
- # new_categories: The new categories of the term.
80
- # """
81
- # if new_categories: # If categories are specified, add them
82
- # for cat in new_categories:
83
- # if cat not in current_categories:
84
- # egeria_client.add_term_to_category(term_guid, cat)
85
- # msg = f"Added term {term_guid} to category {cat}"
86
- # print_msg("DEBUG-INFO", msg, debug_level)
87
- # # Remove any categories that are not in the new list
88
- # for cat in current_categories:
89
- # if cat not in new_categories:
90
- # egeria_client.remove_term_from_category(term_guid, cat)
91
- # msg = f"Removed term {term_guid} from category {cat}"
92
- # print_msg("DEBUG-INFO", msg, debug_level)
93
- # else: # No categories specified - so remove any categories a term is in
94
- # for cat in current_categories:
95
- # egeria_client.remove_term_from_category(term_guid, cat)
96
- # msg = f"Removed term {term_guid} from category {cat}"
97
- # print_msg("DEBUG-INFO", msg, debug_level)
98
156
 
157
+ @logger.catch
158
+ def sync_data_field_rel_elements(egeria_client: EgeriaTech, structure_list: list, parent_field_list: list, terms: list,
159
+ data_class_guid: str, guid: str, display_name: str,
160
+ replace_all_props: bool = True) -> None:
161
+ """Sync a field's related elements.
99
162
 
163
+ TODO: Need to add data class support when ready and may need to revisit bodies.
164
+
165
+ """
166
+ if replace_all_props:
167
+ rel_el_list = egeria_client.get_data_field_rel_elements(guid)
168
+ # should I throw an exception if empty?
169
+ as_is_data_structs = set(rel_el_list.get("data_structure_guids", []))
170
+ as_is_parent_fields = set(rel_el_list.get("parent_guids", []))
171
+ as_is_assigned_meanings = set(rel_el_list.get("assigned_meanings_guids", []))
172
+ as_is_data_classes = set(rel_el_list.get("data_class_guids", []))
173
+
174
+ to_be_data_structs = set(structure_list) if structure_list is not None else set()
175
+ to_be_parent_fields = set(parent_field_list) if parent_field_list is not None else set()
176
+ to_be_assigned_meanings = set(terms) if terms is not None else set()
177
+ to_be_data_classes = set(data_class_guid) if data_class_guid is not None else set()
178
+
179
+ logger.trace(f"as_is_data_structs: {list(as_is_data_structs)} to_be_data_struct: {list(to_be_data_structs)}")
180
+ logger.trace(
181
+ f"as_is_parent_fields: {list(as_is_parent_fields)} to_be_parent_fields: {list(to_be_parent_fields)}")
182
+ logger.trace(f"as_is_assigned_meanings: {list(as_is_assigned_meanings)} to_be_assigned_meanings: "
183
+ f"{list(to_be_assigned_meanings)}")
184
+ logger.trace(f"as_is_data_classes: {list(as_is_data_classes)} to_be_assigned_data_classes: "
185
+ f"{list(to_be_data_classes)}")
186
+
187
+ data_struct_to_remove = as_is_data_structs - to_be_data_structs
188
+ logger.trace(f"data_struct_to_remove: {list(data_struct_to_remove)}")
189
+ if len(data_struct_to_remove) > 0:
190
+ for ds in data_struct_to_remove:
191
+ egeria_client.detach_member_data_field(ds, guid, None)
192
+ msg = f"Removed `{display_name}` from structure `{ds}`"
193
+ logger.trace(msg)
194
+ data_struct_to_add = to_be_data_structs - as_is_data_structs
195
+ logger.trace(f"data_struct_to_add: {list(data_struct_to_add)}")
196
+ if len(data_struct_to_add) > 0:
197
+ for ds in data_struct_to_add:
198
+ egeria_client.link_member_data_field(ds, guid, None)
199
+ msg = f"Added `{display_name}` to structure `{ds}`"
200
+ logger.trace(msg)
201
+
202
+ parent_field_to_remove = to_be_parent_fields - as_is_parent_fields
203
+ logger.trace(f"parent_field_to_remove: {list(parent_field_to_remove)}")
204
+ if len(parent_field_to_remove) > 0:
205
+ for field in parent_field_to_remove:
206
+ egeria_client.detach_nested_data_field(field, guid, None)
207
+ msg = f"Removed `{display_name}` from field `{field}`"
208
+ logger.trace(msg)
209
+ parent_field_to_add = to_be_parent_fields - as_is_parent_fields
210
+ logger.trace(f"parent_field_to_add: {list(parent_field_to_add)}")
211
+ if len(parent_field_to_add) > 0:
212
+ for field in parent_field_to_add:
213
+ egeria_client.link_nested_data_field(field, guid, None)
214
+ msg = f"Added `{display_name}` to field `{field}`"
215
+ logger.trace(msg)
216
+
217
+ terms_to_remove = as_is_assigned_meanings - to_be_assigned_meanings
218
+ logger.trace(f"terms_to_remove: {list(terms_to_remove)}")
219
+ if len(terms_to_remove) > 0:
220
+ for term in terms_to_remove:
221
+ egeria_client.detach_semantic_definition(guid, term, None)
222
+ msg = f"Removed `{term}` from `{display_name}`"
223
+ logger.trace(msg)
224
+ terms_to_add = to_be_assigned_meanings - as_is_assigned_meanings
225
+ logger.trace(f"terms_to_add: {list(terms_to_add)}")
226
+ if len(terms_to_add) > 0:
227
+ for term in terms_to_add:
228
+ egeria_client.link_semantic_definition(guid, term, None)
229
+ msg = f"Added `{term}` to`{display_name}`"
230
+ logger.trace(msg)
231
+
232
+ classes_to_remove = as_is_data_classes - to_be_data_classes
233
+ logger.trace(f"classes_to_remove: {list(classes_to_remove)}")
234
+ if len(terms_to_remove) > 0:
235
+ for dc in classes_to_remove:
236
+ egeria_client.detach_data_class_definition(guid, dc)
237
+ msg = f"Removed `{dc}` from `{display_name}`"
238
+ logger.trace(msg)
239
+ classes_to_add = to_be_data_classes - as_is_data_classes
240
+ logger.trace(f"classes_to_add: {list(classes_to_add)}")
241
+ if len(terms_to_add) > 0:
242
+ for dc in classes_to_add:
243
+ egeria_client.link_data_class_definition(guid, dc)
244
+ msg = f"Added `{dc}` to`{display_name}`"
245
+ logger.trace(msg)
246
+
247
+
248
+ else: # merge - add field to related elements
249
+ add_field_to_data_structures(egeria_client, display_name, structure_list, guid)
250
+ msg = f"Added `{display_name}` to `{structure_list}`"
251
+ logger.trace(msg)
252
+
253
+ for field in parent_field_list:
254
+ egeria_client.link_nested_data_field(field, guid, None)
255
+ msg = f"Added `{display_name}` to `{field}`"
256
+ logger.trace(msg)
257
+ for term in terms:
258
+ egeria_client.link_semantic_definition(guid, term, None)
259
+ msg = f"Added `{term}` to `{display_name}`"
260
+ logger.trace(msg)
261
+
262
+ egeria_client.link_data_class_definition(guid, data_class_guid)
263
+ msg = f"Added `{data_class_guid}` to `{display_name}`"
264
+ logger.trace(msg)
265
+
266
+
267
+ @logger.catch
268
+ def sync_data_class_rel_elements(egeria_client: EgeriaTech, containing_data_class_guids: list, terms: list,
269
+ containing_data_classes: list, super_data_classes: list, guid: str, display_name: str,
270
+ replace_all_props: bool = True) -> None:
271
+ """Sync a data class' related elements.
272
+
273
+ TODO: may need to revisit bodies.
274
+
275
+ """
276
+ if replace_all_props:
277
+ rel_el_list = egeria_client.get_data_field_rel_elements(guid)
278
+ # should I throw an exception if empty?
279
+ as_is_containing_data_class_guids = set(rel_el_list.get("data_structure_guids", []))
280
+ as_is_parent_fields = set(rel_el_list.get("parent_guids", []))
281
+ as_is_assigned_meanings = set(rel_el_list.get("assigned_meanings_guids", []))
282
+ as_is_data_classes = set(rel_el_list.get("data_class_guids", []))
283
+
284
+ # to_be_data_structs = set(structure_list) if structure_list is not None else set() #
285
+ # to_be_parent_fields = set(parent_field_list) if parent_field_list is not None else set() #
286
+ # to_be_assigned_meanings = set(terms) if data_class_list is not None else set() #
287
+ # to_be_assigned_data_classes = set(data_class_list) if data_class_list is not None else set() # #
288
+ # logger.trace(f"as_is_data_structs: {list(as_is_data_structs)} to_be_data_struct: {list(
289
+ # to_be_data_structs)}") # logger.trace( # f"as_is_parent_fields: {list(as_is_parent_fields)}
290
+ # to_be_parent_fields: {list(to_be_parent_fields)}") # logger.trace( #
291
+ # f"as_is_assigned_meanings: {list(as_is_assigned_meanings)} to_be_assigned_meanings: " # f"{list(
292
+ # to_be_assigned_meanings)}") # logger.trace( # f"as_is_data_classes: {list(
293
+ # as_is_data_classes)} to_be_assigned_data_classes: " # f"{list(to_be_assigned_data_classes)}") #
294
+ # data_struct_to_remove = as_is_data_structs - to_be_data_structs # logger.trace(
295
+ # f"data_struct_to_remove: {list(data_struct_to_remove)}") # if len(data_struct_to_remove) > 0: #
296
+ # for ds in data_struct_to_remove: # egeria_client.detach_member_data_field(ds, guid,
297
+ # None) # msg = f"Removed `{display_name}` from structure `{ds}`" # logger.trace(
298
+ # msg) # data_struct_to_add = to_be_data_structs - as_is_data_structs # logger.trace(
299
+ # f"data_struct_to_add: {list(data_struct_to_add)}") # if len(data_struct_to_add) > 0: # for ds
300
+ # in data_struct_to_add: # egeria_client.link_member_data_field(ds, guid, None) #
301
+ # msg = f"Added `{display_name}` to structure `{ds}`" # logger.trace(msg) # #
302
+ # parent_field_to_remove = to_be_parent_fields - as_is_parent_fields # logger.trace(
303
+ # f"parent_field_to_remove: {list(parent_field_to_remove)}") # if len(parent_field_to_remove) > 0: #
304
+ # for field in parent_field_to_remove: # egeria_client.detach_nested_data_field(field, guid,
305
+ # None) # msg = f"Removed `{display_name}` from field `{field}`" # logger.trace(
306
+ # msg) # parent_field_to_add = to_be_parent_fields - as_is_parent_fields # logger.trace(
307
+ # f"parent_field_to_add: {list(parent_field_to_add)}") # if len(parent_field_to_add) > 0: # for
308
+ # field in parent_field_to_add: # egeria_client.link_nested_data_field(field, guid, None) #
309
+ # msg = f"Added `{display_name}` to field `{field}`" # logger.trace(msg) # #
310
+ # terms_to_remove = as_is_assigned_meanings - to_be_assigned_meanings # logger.trace(f"terms_to_remove:
311
+ # {list(terms_to_remove)}") # if len(terms_to_remove) > 0: # for term in terms_to_remove: #
312
+ # egeria_client.detach_semantic_definition(guid, term, None) # msg = f"Removed `{term}` from `{
313
+ # display_name}`" # logger.trace(msg) # terms_to_add = to_be_assigned_meanings -
314
+ # as_is_assigned_meanings # logger.trace(f"terms_to_add: {list(terms_to_add)}") # if len(
315
+ # terms_to_add) > 0: # for term in terms_to_add: #
316
+ # egeria_client.link_semantic_definition(guid, term, None) # msg = f"Added `{term}` to`{
317
+ # display_name}`" # logger.trace(msg) # # else: # merge - add field to related elements #
318
+ # add_field_to_data_structures(egeria_client, display_name, structure_list, guid) # msg = f"Added `{
319
+ # display_name}` to `{structure_list}`" # logger.trace(msg) # # for field in parent_field_list: #
320
+ # egeria_client.link_nested_data_field(field, guid, None) # msg = f"Added `{display_name}` to `{
321
+ # field}`" # logger.trace(msg) # for term in terms: #
322
+ # egeria_client.link_semantic_definition(guid, term, None) # msg = f"Added `{term}` to `{
323
+ # display_name}`" # logger.trace(msg)
324
+
325
+
326
+ @logger.catch
100
327
  def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
101
328
  """
102
329
  Processes a data specification create or update object_action by extracting key attributes such as
@@ -107,13 +334,10 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
107
334
  :param directive: an optional string indicating the directive to be used - display, validate or execute
108
335
  :return: A string summarizing the outcome of the processing.
109
336
  """
110
- from md_processing.md_processing_utils.common_md_utils import set_debug_level
111
-
112
- set_debug_level(directive)
113
337
 
114
338
  command, object_type, object_action = extract_command_plus(txt)
115
339
 
116
- parsed_output = parse_user_command(egeria_client, object_type, object_action, txt, directive)
340
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
117
341
 
118
342
  valid = parsed_output['valid']
119
343
  exists = parsed_output['exists']
@@ -123,21 +347,32 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
123
347
 
124
348
  print(Markdown(parsed_output['display']))
125
349
 
126
- print(json.dumps(parsed_output, indent=4))
350
+ logger.debug(json.dumps(parsed_output, indent=4))
127
351
 
128
352
  attributes = parsed_output['attributes']
129
353
  description = attributes['Description'].get('value', None)
130
354
  display_name = attributes['Display Name'].get('value', None)
131
355
  anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
132
356
  parent_guid = attributes.get('Parent ID', {}).get('guid', None)
133
- parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', "CollectionMembership")
357
+ parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value',
358
+ "CollectionMembership")
134
359
  parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
135
360
 
136
361
  anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
137
362
  is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
138
- collection_ordering = "NAME"
139
- order_property_name = "Something"
140
- collection_type = object_type
363
+ if parent_guid is None:
364
+ is_own_anchor = True
365
+
366
+ collection_type = attributes.get('Collection Type', {}).get('value', None)
367
+ collection_ordering = attributes.get('Collection Ordering', {}).get('value', None)
368
+ order_property_name = attributes.get('Order Property Name', {}).get('value', None)
369
+ replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
370
+
371
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
372
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
373
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
374
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
375
+
141
376
  replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
142
377
  in_data_spec_list = attributes.get('In Data Specification', {}).get('value', None)
143
378
  in_data_spec_valid = attributes.get('In Data Specification', {}).get('valid', None)
@@ -154,16 +389,12 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
154
389
  return valid
155
390
 
156
391
  elif directive == "process":
157
-
158
-
159
-
160
-
161
392
  try:
162
393
  if object_action == "Update":
163
394
  if not exists:
164
395
  msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
165
- f"object_action\n")
166
- print_msg(ERROR, msg, debug_level)
396
+ f"object_action\n")
397
+ logger.error(msg)
167
398
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
168
399
  elif not valid:
169
400
  return None
@@ -172,48 +403,53 @@ def process_data_spec_upsert_command(egeria_client: EgeriaTech, txt: str, direct
172
403
  f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
173
404
 
174
405
  egeria_client.update_collection(guid, qualified_name, display_name, description, collection_type,
175
- collection_ordering, order_property_name, replace_all_props)
176
- print_msg(ALWAYS, f"Updated {object_type} `{display_name}` with GUID {guid}", debug_level)
406
+ collection_ordering, order_property_name, replace_all_props,
407
+ additional_properties, extended_properties)
408
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
177
409
  update_element_dictionary(qualified_name, {
178
410
  'guid': guid, 'display_name': display_name
179
411
  })
180
- return egeria_client.get_collection_by_guid(guid, output_format='FORM')
412
+ return egeria_client.get_collection_by_guid(guid, collection_type='Data Specification',
413
+ output_format='MD')
181
414
 
182
415
 
183
416
  elif object_action == "Create":
184
417
  if valid is False and exists:
185
418
  msg = (f" Data Specification `{display_name}` already exists and result document updated changing "
186
- f"`Create` to `Update` in processed output\n")
187
- print_msg(ERROR, msg, debug_level)
419
+ f"`Create` to `Update` in processed output\n\n___")
420
+ logger.error(msg)
188
421
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
189
422
  elif valid is False and in_data_spec_valid is False:
190
423
  msg = (f" Invalid data specification(s) `{in_data_spec_list}` "
191
- f" perhaps they don't yet exist? - Correct and try again")
192
- print_msg(ERROR, msg, debug_level)
424
+ f" invalid data? - Correct and try again\n\n___")
425
+ logger.error(msg)
426
+ return None
193
427
  else:
194
428
  guid = egeria_client.create_data_spec_collection(anchor_guid, parent_guid,
195
429
  parent_relationship_type_name, parent_at_end1,
196
430
  display_name, description, collection_type,
197
- anchor_scope_guid, is_own_anchor,
198
- collection_ordering, order_property_name,
199
- qualified_name)
431
+ anchor_scope_guid, is_own_anchor, qualified_name)
200
432
  if guid:
201
-
202
- print_msg(ALWAYS, f"Created Element `{display_name}` with GUID {guid}", debug_level)
203
-
204
- return egeria_client.get_collection_by_guid(guid, output_format='FORM')
433
+ update_element_dictionary(qualified_name, {
434
+ 'guid': guid, 'display_name': display_name
435
+ })
436
+ msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
437
+ logger.success(msg)
438
+ return egeria_client.get_collection_by_guid(guid, collection_type='Data Specification',
439
+ output_format='MD')
205
440
  else:
206
- print_msg(ERROR, f"Failed to create Term `{display_name}`", debug_level)
441
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
442
+ logger.error(msg)
207
443
  return None
208
444
 
209
445
  except Exception as e:
210
- print(f"{ERROR}Error performing {command}: {e}")
211
- Console().print_exception(show_locals=True)
446
+ logger.error(f"Error performing {command}: {e}")
212
447
  return None
213
448
  else:
214
449
  return None
215
450
 
216
451
 
452
+ @logger.catch
217
453
  def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
218
454
  """
219
455
  Processes a data dictionary create or update object_action by extracting key attributes such as
@@ -224,13 +460,10 @@ def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, direct
224
460
  :param directive: an optional string indicating the directive to be used - display, validate or execute
225
461
  :return: A string summarizing the outcome of the processing.
226
462
  """
227
- from md_processing.md_processing_utils.common_md_utils import set_debug_level
228
-
229
- set_debug_level(directive)
230
463
 
231
464
  command, object_type, object_action = extract_command_plus(txt)
232
465
 
233
- parsed_output = parse_user_command(egeria_client, object_type, object_action, txt, directive)
466
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
234
467
 
235
468
  valid = parsed_output['valid']
236
469
  exists = parsed_output['exists']
@@ -239,9 +472,33 @@ def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, direct
239
472
  guid = parsed_output.get('guid', None)
240
473
 
241
474
  print(Markdown(parsed_output['display']))
475
+ logger.debug(json.dumps(parsed_output, indent=4))
242
476
 
243
- if directive == "display":
477
+ attributes = parsed_output['attributes']
478
+ description = attributes['Description'].get('value', None)
479
+ display_name = attributes.get('Display Name', {}).get('value', "None Found")
480
+ display_name = display_name if display_name is not None else "None Found"
481
+ anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
482
+ parent_guid = attributes.get('Parent ID', {}).get('guid', None)
483
+ parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value',
484
+ "CollectionMembership")
485
+ parent_at_end1 = attributes.get('Parent at End1', {}).get('value', True)
486
+
487
+ anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
488
+ is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', True)
489
+ if parent_guid is None:
490
+ is_own_anchor = True
491
+ collection_type = attributes.get('Collection Type', {}).get('value', None)
492
+ collection_ordering = attributes.get('Collection Ordering', {}).get('value', None)
493
+ order_property_name = attributes.get('Order Property Name', {}).get('value', None)
494
+ replace_all_props = not attributes.get('Merge Update', {}).get('value', True)
244
495
 
496
+ additional_prop = attributes.get('Additional Properties', {}).get('value', None)
497
+ additional_properties = json.loads(additional_prop) if additional_prop is not None else None
498
+ extended_prop = attributes.get('Extended Properties', {}).get('value', None)
499
+ extended_properties = json.loads(extended_prop) if extended_prop is not None else None
500
+
501
+ if directive == "display":
245
502
  return None
246
503
  elif directive == "validate":
247
504
  if valid:
@@ -251,79 +508,67 @@ def process_data_dict_upsert_command(egeria_client: EgeriaTech, txt: str, direct
251
508
  return valid
252
509
 
253
510
  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
511
 
275
512
  try:
276
513
  if object_action == "Update":
277
514
 
278
515
  if not exists:
279
- print(f"\n{ERROR}Element `{display_name}` does not exist! Updating result document with Create "
280
- f"object_action\n")
516
+ logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
517
+ f"object_action\n\n___")
281
518
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
282
519
  elif not valid:
520
+ logger.error(f"Element `{display_name}` does not have a valid specification? Review..\n\n___ ")
283
521
  return None
284
522
  else:
285
523
  print(Markdown(
286
- f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
524
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes."))
287
525
 
288
526
  egeria_client.update_collection(guid, qualified_name, display_name, description, collection_type,
289
- collection_ordering, order_property_name, replace_all_props)
290
- print_msg(ALWAYS, f"Updated {object_type} `{display_name}` with GUID {guid}", debug_level)
527
+ collection_ordering, order_property_name, replace_all_props,
528
+ additional_properties, extended_properties)
529
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
291
530
  update_element_dictionary(qualified_name, {
292
531
  'guid': guid, 'display_name': display_name
293
532
  })
294
- return egeria_client.get_collection_by_guid(guid, output_format='FORM')
533
+ return egeria_client.get_collection_by_guid(guid, collection_type='Data Dictionary', output_format='MD')
295
534
 
296
535
  elif object_action == "Create":
297
536
  if valid is False and exists:
298
- print(f"\nElement `{display_name}` already exists and result document updated changing "
299
- f"`Create` to `Update` in processed output\n")
537
+ logger.error(f"\nElement `{display_name}` already exists and result document updated changing "
538
+ f"`Create` to `Update` in processed output\n\n___")
300
539
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
301
540
  else:
302
541
  guid = egeria_client.create_data_dictionary_collection(anchor_guid, parent_guid,
303
542
  parent_relationship_type_name,
304
543
  parent_at_end1, display_name, description,
305
544
  collection_type, anchor_scope_guid,
306
- is_own_anchor, collection_ordering,
307
- order_property_name, qualified_name)
545
+ is_own_anchor, qualified_name,
546
+ additional_properties, extended_properties)
308
547
  if guid:
309
- print_msg(ALWAYS, f"Created Element `{display_name}` with GUID {guid}", debug_level)
548
+ update_element_dictionary(qualified_name, {
549
+ 'guid': guid, 'display_name': display_name
550
+ })
551
+ logger.success(f"Created Element `{display_name}` with GUID {guid}\n\n___")
310
552
 
311
- return egeria_client.get_collection_by_guid(guid, output_format='FORM')
553
+ return egeria_client.get_collection_by_guid(guid, collection_type='Data Dictionary',
554
+ output_format='MD')
312
555
  else:
313
- print_msg(ERROR, f"Failed to create Term `{display_name}`", debug_level)
556
+ logger.error(f"Failed to create Term `{display_name}`\n\n___")
314
557
  return None
315
558
 
316
559
  except Exception as e:
317
- print(f"{ERROR}Error performing {command}: {e}")
560
+ logger.error(f"{ERROR}Error performing {command}: {e}")
318
561
  Console().print_exception(show_locals=True)
319
562
  return None
320
563
  else:
321
564
  return None
322
565
 
323
566
 
324
- def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
567
+ @logger.catch
568
+ def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
569
+ str]:
325
570
  """
326
- Processes a data dictionary create or update object_action by extracting key attributes such as
571
+ Processes a data structure create or update object_action by extracting key attributes such as
327
572
  spec name, parent_guid, parent_relationship_type, parent_at_end_1, collection_type
328
573
 
329
574
  :param txt: A string representing the input cell to be processed for
@@ -337,7 +582,7 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
337
582
 
338
583
  command, object_type, object_action = extract_command_plus(txt)
339
584
 
340
- parsed_output = parse_user_command(egeria_client, object_type, object_action, txt, directive)
585
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
341
586
 
342
587
  valid = parsed_output['valid']
343
588
  exists = parsed_output['exists']
@@ -348,8 +593,8 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
348
593
  print(Markdown(parsed_output['display']))
349
594
 
350
595
  if directive == "display":
351
-
352
596
  return None
597
+
353
598
  elif directive == "validate":
354
599
  if valid:
355
600
  print(Markdown(f"==> Validation of {command} completed successfully!\n"))
@@ -358,9 +603,206 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
358
603
  return valid
359
604
 
360
605
  elif directive == "process":
361
- print(json.dumps(parsed_output, indent=4))
606
+ logger.debug(json.dumps(parsed_output, indent=4))
362
607
  attributes = parsed_output['attributes']
363
608
 
609
+ external_source_guid = attributes.get('External Source Name', {}).get('guid', None)
610
+ external_source_name = attributes.get('External Source Name', {}).get('value', None)
611
+ effective_time = attributes.get('Effective Time', {}).get('value', None)
612
+ for_lineage = attributes.get('For Lineage', {}).get('value', None)
613
+ for_duplicate_processing = attributes.get('For Duplicate Processing', {}).get('value', None)
614
+ anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
615
+ is_own_anchor = attributes.get('Is Own Anchor', {}).get('value', None)
616
+ parent_id = attributes.get('Parent ID', {}).get('value', None)
617
+ parent_guid = attributes.get('Parent ID', {}).get('guid', None)
618
+ parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
619
+ parent_relationship_properties = attributes.get('Parent Relationship Properties', {}).get('value', None)
620
+ parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
621
+
622
+ display_name = attributes['Display Name'].get('value', None)
623
+
624
+ namespace = attributes.get('Namespace', {}).get('value', None)
625
+ description = attributes.get('Description', {}).get('value', None)
626
+ version_id = attributes.get('Version Identifier', {}).get('value', None)
627
+ aliases = attributes.get('Aliases', {}).get('value', None)
628
+ name_patterns = attributes.get('Name Patterns', {}).get('value', None)
629
+ is_nullable = attributes.get('Is Nullable', {}).get('value', None)
630
+ default_value = attributes.get('Default Value', {}).get('value', None)
631
+ data_type = attributes.get('Data Type', {}).get('value', None)
632
+ min_length = attributes.get('Minimum Length', {}).get('value', None)
633
+ length = attributes.get('Length', {}).get('value', None)
634
+ precision = attributes.get('Precision', {}).get('value', None)
635
+ ordered_values = attributes.get('Ordered Values', {}).get('value', None)
636
+ sort_order = attributes.get('Sort Order', {}).get('value', None)
637
+ additional_properties = attributes.get('Additional Properties', {}).get('value', None)
638
+ effective_from = attributes.get('Effective From', {}).get('value', None)
639
+ effective_to = attributes.get('Effective To', {}).get('value', None)
640
+
641
+ position = attributes.get('Position', {}).get('value', None)
642
+ min_cardinality = attributes.get('Minimum Cardinality', {}).get('value', None)
643
+ max_cardinality = attributes.get('Maximum Cardinality', {}).get('value', None)
644
+ in_data_structure = attributes.get('In Data Structure', {}).get('value', None)
645
+ data_class = attributes.get('Data Class', {}).get('value', None)
646
+ glossary_term = attributes.get('Glossary Term', {}).get('value', None)
647
+ glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
648
+
649
+ # name_details_list = attributes.get("dict_list", None)
650
+
651
+ data_spec_name_list = attributes.get("In Data Specification", {}).get("name_list", "")
652
+ data_spec_value = attributes.get("In Data Specification", {}).get("value", None)
653
+ data_spec_guid_list = attributes.get("In Data Specification", {}).get("guid_list", None)
654
+
655
+ in_data_dictionary = attributes.get('In Data Dictionary', {}).get('dict_list', None)
656
+ data_dict_name_list = attributes.get('In Data Dictionary', {}).get('name_list', "")
657
+ data_dict_value_list = attributes.get('In Data Dictionary', {}).get('value', None)
658
+ data_dict_guid_list = attributes.get("In Data Dictionary", {}).get("guid_list", None)
659
+
660
+ parent_data_field = attributes.get('Parent Data Field', {}).get('value', None)
661
+ parent_data_field_guid = attributes.get('Parent Data Field', {}).get('guid', None)
662
+
663
+ anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
664
+
665
+ collection_type = object_type
666
+ replace_all_props = True
667
+ if not valid:
668
+ if exists and object_action == "Create":
669
+ msg = (f"Create failed because Element `{display_name}` exists - changing `Create` to `Update` in "
670
+ f"processed output \n\n___")
671
+ logger.error(msg)
672
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
673
+ else:
674
+ return None
675
+ elif object_action == "Update" and not exists:
676
+ logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
677
+ f"object_action\n\n___")
678
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
679
+
680
+ else:
681
+ print(Markdown(f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
682
+
683
+ try:
684
+ if object_action == "Update":
685
+ body = {
686
+ "class": "UpdateDataStructureRequestBody", "externalSourceGUID": external_source_guid,
687
+ "externalSourceName": external_source_name, "effectiveTime": effective_time,
688
+ "forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing, "properties": {
689
+ "class": "DataStructureProperties", "qualifiedName": qualified_name,
690
+ "displayName": display_name, "description": description, "namespace": namespace,
691
+ "versionIdentifier": version_id, "additionalProperties": additional_properties,
692
+ "effectiveFrom": effective_from, "effectiveTo": effective_to
693
+ }
694
+ }
695
+ egeria_client.update_data_structure_w_body(guid, body, replace_all_props)
696
+ logger.info(f"Updated element `{display_name}` with GUID {guid}")
697
+ core_props = egeria_client.get_data_structure_by_guid(guid, output_format='MD')
698
+
699
+ update_element_dictionary(qualified_name, {
700
+ 'guid': guid, 'display_name': display_name
701
+ })
702
+
703
+ update_data_collection_memberships(egeria_client, object_type, data_spec_guid_list, "DataSpec", guid,
704
+ display_name, replace_all_props)
705
+ core_props += f"## In Data Dictionary\n\n{data_dict_name_list}\n\n"
706
+ core_props += f"## In Data Specification\n\n{data_spec_name_list}\n\n"
707
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
708
+ return core_props
709
+
710
+ elif object_action == "Create":
711
+ if exists:
712
+ logger.warning(f"\nTerm `{display_name}` already exists and result document updated\n\n___")
713
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
714
+ else:
715
+
716
+ body = {
717
+ "class": "NewDataStructureRequestBody", "externalSourceGUID": external_source_guid,
718
+ "externalSourceName": external_source_name, "effectiveTime": effective_time,
719
+ "forLineage": False, "forDuplicateProcessing": False, "anchorGUID": anchor_guid,
720
+ "isOwnAnchor": is_own_anchor, "parentGUID": parent_guid,
721
+ "parentRelationshipTypeName": parent_relationship_type_name,
722
+ "parentRelationshipProperties": parent_relationship_properties, "parentAtEnd1": parent_at_end1,
723
+ "properties": {
724
+ "class": "DataStructureProperties", "qualifiedName": qualified_name,
725
+ "displayName": display_name, "description": description, "namespace": namespace,
726
+ "versionIdentifier": version_id, "additionalProperties": additional_properties,
727
+ "effectiveFrom": effective_from, "effectiveTo": effective_to
728
+ }
729
+ }
730
+
731
+ guid = egeria_client.create_data_structure_w_body(body_slimmer(body))
732
+ if guid:
733
+ update_element_dictionary(qualified_name, {
734
+ 'guid': guid, 'display_name': display_name
735
+ })
736
+
737
+ core_props = egeria_client.get_data_structure_by_guid(guid, output_format='MD')
738
+
739
+ if in_data_dictionary:
740
+ logger.info(f"Will add to data dictionary(s) `{in_data_dictionary}`")
741
+ result = add_member_to_data_collections(egeria_client, in_data_dictionary, display_name,
742
+ guid)
743
+ core_props += f"## In Data Dictionary\n\n{data_dict_name_list}\n\n"
744
+
745
+ if data_spec_guid_list:
746
+ result = add_member_to_data_collections(egeria_client, data_spec_guid_list, display_name,
747
+ guid)
748
+ core_props += f"## In Data Specifications\n\n`{data_spec_name_list}`\n\n"
749
+
750
+ logger.info(f"Created Element `{display_name}` with GUID {guid}\n\n___")
751
+
752
+ return core_props
753
+ else:
754
+ logger.error(f"Failed to create Data Structure `{display_name}`\n\n___")
755
+ return None
756
+
757
+
758
+ except Exception as e:
759
+ logger.error(f"Error performing {object_action}: {e}\n\n___")
760
+ return None
761
+ else:
762
+ return None
763
+
764
+
765
+ @logger.catch
766
+ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
767
+ """
768
+ Processes a data field create or update object_action by extracting key attributes such as
769
+ spec name, parent_guid, parent_relationship_type, parent_at_end_1, collection_type
770
+
771
+ :param txt: A string representing the input cell to be processed for
772
+ extracting glossary-related attributes.
773
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
774
+ :return: A string summarizing the outcome of the processing.
775
+ """
776
+ from md_processing.md_processing_utils.common_md_utils import set_debug_level
777
+
778
+ set_debug_level(directive)
779
+
780
+ command, object_type, object_action = extract_command_plus(txt)
781
+
782
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
783
+ attributes = parsed_output['attributes']
784
+ display_name = attributes['Display Name'].get('value', None)
785
+ qualified_name = parsed_output.get('qualified_name', None)
786
+ guid = parsed_output.get('guid', None)
787
+ valid = parsed_output['valid']
788
+ exists = parsed_output['exists']
789
+
790
+ print(Markdown(parsed_output['display']))
791
+
792
+ if directive == "display":
793
+
794
+ return None
795
+ elif directive == "validate":
796
+ if valid:
797
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
798
+ else:
799
+ msg = f"Validation failed for object_action `{command}`\n"
800
+ logger.error(msg)
801
+ return valid
802
+
803
+ elif directive == "process":
804
+ logger.debug(json.dumps(parsed_output, indent=4))
805
+
364
806
  external_source_guid = attributes.get('External Source Name', {}).get('guid', None)
365
807
  external_source_name = attributes.get('External Source Name', {}).get('value', None)
366
808
  effective_time = attributes.get('Effective Time', {}).get('value', None)
@@ -374,10 +816,8 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
374
816
  # parent_relationship_properties = attributes.get('Parent Relationship Properties',{}).get('value', None)
375
817
  # parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
376
818
 
377
- display_name = attributes['Display Name'].get('value', None)
378
-
379
- namespace = attributes.get('Namespace',{}).get('value', None)
380
- description = attributes.get('Description',{}).get('value', None)
819
+ namespace = attributes.get('Namespace', {}).get('value', None)
820
+ description = attributes.get('Description', {}).get('value', None)
381
821
  version_id = attributes.get('Version Identifier', {}).get('value', None)
382
822
  aliases = attributes.get('Aliases', {}).get('value', None)
383
823
  name_patterns = attributes.get('Name Patterns', {}).get('value', None)
@@ -393,41 +833,51 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
393
833
  effective_from = attributes.get('Effective From', {}).get('value', None)
394
834
  effective_to = attributes.get('Effective To', {}).get('value', None)
395
835
 
836
+ glossary_term = attributes['Glossary Term'].get('value', None)
837
+ glossary_term_guid = attributes['Glossary Term'].get('guid', None)
838
+
839
+ merge_update = attributes.get('Merge Update', {}).get('value', None)
840
+
396
841
  position = attributes.get('Position', {}).get('value', None)
397
842
  min_cardinality = attributes.get('Minimum Cardinality', {}).get('value', None)
398
843
  max_cardinality = attributes.get('Maximum Cardinality', {}).get('value', None)
399
844
 
400
845
  in_data_structure = attributes.get('In Data Structure', {}).get('value', None)
846
+ data_structure_guid_list = attributes.get('In Data Structure', {}).get('guid_list', None)
401
847
  in_data_structure_names = attributes.get('In Data Structure Names', {}).get('name_list', None)
402
848
 
403
- data_class = attributes['Data Class'].get('value', None)
849
+ data_class = attributes.get('Data Class', {}).get('value', None)
850
+ glossary_term = attributes.get('Glossary Term', {}).get('value', None)
404
851
 
405
- glossary_term = attributes['Glossary Term'].get('value', None)
406
- glossary_term_guid = attributes['Glossary Term'].get('guid', None)
852
+ glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
853
+
854
+ # name_details_list = attributes.get("dict_list", None)
855
+
856
+ in_data_spec = attributes.get("In Data Specification", {}).get("value", None) # this is a [dict]
857
+ data_spec_name_list = attributes.get("In Data Specification", {}).get("name_list", None)
858
+ data_spec_guid_list = attributes.get("In Data Specification", {}).get("guid_list", None)
407
859
 
408
860
  in_data_dictionary = attributes.get('In Data Dictionary', {}).get('value', None)
409
- in_data_dictionary_names = attributes.get('In Data Dictionary Names', {}).get('name_list', None)
861
+ in_data_dictionary_names = attributes.get('In Data Dictionary', {}).get('name_list', None)
862
+ data_dict_guid_list = attributes.get("In Data Dictionary", {}).get("guid_list", None)
410
863
 
411
864
  parent_data_field = attributes.get('Parent Data Field', {}).get('value', None)
412
- parent_data_field_guid = attributes.get('Parent Data Field', {}).get('guid', None)
865
+ parent_data_field_guids = attributes.get('Parent Data Field', {}).get('guid_list', None)
866
+ parent_data_field_names = attributes.get('Parent Data Field', {}).get('name_list', None)
413
867
 
414
868
  anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
415
869
 
416
- merge_update = attributes.get('Merge Update', {}).get('value', None)
417
-
418
-
419
- collection_ordering = "NAME"
420
- order_property_name = "Something"
421
- collection_type = object_type
422
- replace_all_props = True
870
+ replace_all_props = not merge_update
423
871
 
424
872
  if not valid:
425
873
  if exists and object_action == "Create":
426
874
  msg = (f"Create failed because Element `{display_name}` exists - changing `Create` to `Update` in "
427
- f"processed output \n")
428
- print_msg(ERROR, msg, debug_level)
875
+ f"processed output\n\n___")
876
+ logger.error(msg)
429
877
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
430
878
  else:
879
+ msg = f"Invalid specification - please review\n\n___"
880
+ logger.error(msg)
431
881
  return None
432
882
  else:
433
883
  print(Markdown(f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
@@ -435,89 +885,60 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
435
885
  try:
436
886
  if object_action == "Update":
437
887
  if not exists:
438
- print(f"\n{ERROR}Element `{display_name}` does not exist! Updating result document with Create "
439
- f"object_action\n")
888
+ logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
889
+ f"object_action\n\n___")
440
890
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
441
891
 
892
+ # first update the base data field
442
893
  body = {
443
- "class": "UpdateDataFieldRequestBody",
444
- "externalSourceGUID": external_source_guid,
445
- "externalSourceName": external_source_name,
446
- "effectiveTime": None,
447
- "forLineage": False,
448
- "forDuplicateProcessing": False,
449
- "properties": {
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,
894
+ "class": "UpdateDataFieldRequestBody", "externalSourceGUID": external_source_guid,
895
+ "externalSourceName": external_source_name, "effectiveTime": effective_time,
896
+ "forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing, "properties": {
897
+ "class": "DataFieldProperties", "qualifiedName": qualified_name, "displayName": display_name,
898
+ "namespace": namespace, "description": description, "versionIdentifier": version_id,
899
+ "aliases": aliases, "namePatterns": name_patterns, "isDeprecated": False,
900
+ "isNullable": is_nullable, "defaultValue": default_value, "dataType": data_type,
901
+ "minimumLength": min_length, "length": length, "precision": precision,
902
+ "orderedValues": ordered_values, "sortOrder": sort_order,
903
+ "additionalProperties": additional_properties, "effectiveFrom": effective_from,
469
904
  "effectiveTo": effective_to
470
905
  }
471
906
  }
472
907
 
473
908
  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)
909
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}")
475
910
  # Update data dictionary membership
476
911
  update_element_dictionary(qualified_name, {
477
912
  'guid': guid, 'display_name': display_name
478
913
  })
479
- core_props = egeria_client.get_data_field_by_guid(guid, output_format='MD')
914
+ core_props = egeria_client.find_data_fields(qualified_name,
915
+ output_format='MD') ## update back to by_guid?
480
916
 
481
- existing_data_field = egeria_client.get_data_field_by_guid(guid, output_format='JSON')
482
- existing_data_field_dicts = 3
917
+ # existing_data_field = egeria_client.get_data_field_by_guid(guid, output_format='JSON')
483
918
 
484
919
  # 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
-
920
+ update_data_collection_memberships(egeria_client, object_type, data_dict_guid_list, "DataDictionary",
921
+ guid, display_name, replace_all_props)
922
+ logger.success(f"Updating data dictionaries `{in_data_dictionary_names}`")
923
+ core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
924
+
925
+ # Sync data field related elements (data structure, parent data fields, terms, data classes
926
+ sync_data_field_rel_elements(egeria_client, data_structure_guid_list, parent_data_field_guids,
927
+ [glossary_term_guid], data_class, guid, display_name, replace_all_props)
928
+ core_props += f"\n\n## In Data Structure {in_data_structure_names}\n\n"
504
929
  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"
930
+ core_props += f"\n\n## Parent Data Field\n\n{parent_data_field_names}\n\n"
931
+ core_props += "\n___\n\n"
509
932
 
510
933
  # Update data classes
511
- print_msg(ALWAYS, f"Created Element `{display_name}` ", debug_level)
512
-
513
-
934
+ logger.success(f"Updated Element `{display_name}`\n\n___")
514
935
  return core_props
515
936
 
516
-
517
937
  elif object_action == "Create":
518
938
  if valid is False and exists:
519
- print(f"\nData Field `{display_name}` already exists and result document updated changing `Create` "
520
- f"to `Update` in processed output\n")
939
+ logger.error(
940
+ f"\nData Field `{display_name}` already exists and result document updated changing `Create` "
941
+ f"to `Update` in processed output\n\n___")
521
942
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
522
943
  else:
523
944
  # First lets create the data field
@@ -539,72 +960,78 @@ def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, direc
539
960
  'guid': guid, 'display_name': display_name
540
961
  })
541
962
  # Start assembling the information we will present back out
542
- core_props = egeria_client.get_data_field_by_guid(guid, output_format='MD')
963
+ core_props = egeria_client.get_data_field_by_guid(guid, None, 'MD')
543
964
 
544
965
  # Add the field to any data dictionaries
545
966
  if in_data_dictionary:
546
- print_msg(ALWAYS, f"Will add to data dictionary `{in_data_dictionary}`", debug_level)
967
+ logger.info(f"Will add to data dictionary `{in_data_dictionary}`")
968
+ add_member_to_data_collections(egeria_client, data_dict_guid_list, display_name, guid)
547
969
  core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
970
+
548
971
  # Add the field to any data structures
549
972
  if in_data_structure:
550
973
  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
- }
974
+ for ds_guid in data_structure_guid_list:
975
+ # todo This is too naive? - need to better accommodate the relationship
976
+ df_body = {
977
+ "class": "MemberDataFieldRequestBody", "properties": {
978
+ "class": "MemberDataFieldProperties", "dataFieldPosition": position,
979
+ "minCardinality": min_cardinality, "maxCardinality": max_cardinality,
560
980
  }
981
+ }
561
982
 
562
- msg = f"Adding field to structure {ds_qname}"
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"
983
+ msg = f"Adding field to structure {ds_guid}"
984
+ logger.info(msg)
985
+ egeria_client.link_member_data_field(ds_guid, guid, df_body)
986
+ core_props += f"\n\n## In Data Structure {in_data_structure_names}\n\n"
566
987
 
567
988
  if glossary_term:
568
989
  if glossary_term_guid:
569
990
  glossary_body = {
570
- "class": "MetadataSourceRequestBody", "externalSourceGUID": None,
571
- "externalSourceName": None, "effectiveTime": None, "forLineage": False,
572
- "forDuplicateProcessing": False
991
+ "class": "MetadataSourceRequestBody", "externalSourceGUID": external_source_guid,
992
+ "externalSourceName": external_source_name, "effectiveTime": effective_time,
993
+ "forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing
573
994
  }
574
-
575
995
  core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
576
996
  egeria_client.link_semantic_definition(guid, glossary_term_guid, glossary_body)
577
997
 
578
- if parent_data_field_guid:
579
- parent_df_body = {
580
- "class": "MetadataSourceRequestBody", "externalSourceGUID": None,
581
- "externalSourceName": None, "effectiveTime": None, "forLineage": False,
582
- "forDuplicateProcessing": False
583
- }
998
+ if parent_data_field_guids:
999
+ # parent_df_body = {
1000
+ # "class": "MetadataSourceRequestBody", "externalSourceGUID": external_source_guid,
1001
+ # "externalSourceName": external_source_name, "effectiveTime": effective_time,
1002
+ # "forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing
1003
+ # }
584
1004
 
585
- egeria_client.link_nested_data_field(parent_data_field_guid, guid, parent_df_body)
586
- core_props += f"\n\n## Parent Data Field\n\n{parent_data_field}\n\n"
1005
+ # egeria_client.link_nested_data_field(parent_data_field_guid, guid, parent_df_body)
1006
+ for parent_guid in parent_data_field_guids:
1007
+ egeria_client.link_nested_data_field(parent_guid, guid)
1008
+ core_props += f"\n\n## Parent Data Field\n\n{parent_data_field_names}\n\n"
587
1009
 
588
1010
  # Link data class
589
- print_msg(ALWAYS, f"Created Element `{display_name}` ", debug_level)
1011
+ # if data_class:
1012
+ # egeria_client.link_data_class_definition(guid, data_class)
1013
+ # msg = f"Adding data class `{data_class}` to data field {display_name}"
1014
+ # logger.info(msg)
1015
+
1016
+ logger.success(f"Created Element `{display_name}` with guid `{guid}`")
1017
+ core_props += "\n====================================================\n\n"
590
1018
  return core_props
591
1019
 
592
1020
  else:
593
- print_msg(ERROR, f"Failed to create Term `{display_name}`", debug_level)
1021
+ logger.error(f"Failed to create Term `{display_name}`\n\n___")
594
1022
  return None
595
1023
 
596
1024
  except Exception as e:
597
- print(f"{ERROR}Error performing {command}: {e}")
598
- Console().print_exception(show_locals=True)
1025
+ logger.error(f"Error performing {command}: {e}\n\n___")
599
1026
  return None
600
1027
  else:
601
1028
  return None
602
1029
 
603
1030
 
604
- def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
605
- str]:
1031
+ @logger.catch
1032
+ def process_data_class_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
606
1033
  """
607
- Processes a data structure create or update object_action by extracting key attributes such as
1034
+ Processes a data class create or update object_action by extracting key attributes such as
608
1035
  spec name, parent_guid, parent_relationship_type, parent_at_end_1, collection_type
609
1036
 
610
1037
  :param txt: A string representing the input cell to be processed for
@@ -612,35 +1039,33 @@ def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, d
612
1039
  :param directive: an optional string indicating the directive to be used - display, validate or execute
613
1040
  :return: A string summarizing the outcome of the processing.
614
1041
  """
615
- from md_processing.md_processing_utils.common_md_utils import set_debug_level
616
-
617
- set_debug_level(directive)
618
1042
 
619
1043
  command, object_type, object_action = extract_command_plus(txt)
620
1044
 
621
- parsed_output = parse_user_command(egeria_client, object_type, object_action, txt, directive)
622
-
623
- valid = parsed_output['valid']
624
- exists = parsed_output['exists']
1045
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
625
1046
 
1047
+ attributes = parsed_output['attributes']
1048
+ display_name = attributes['Display Name'].get('value', None)
626
1049
  qualified_name = parsed_output.get('qualified_name', None)
627
1050
  guid = parsed_output.get('guid', None)
1051
+ valid = parsed_output['valid']
1052
+ exists = parsed_output['exists']
628
1053
 
629
1054
  print(Markdown(parsed_output['display']))
630
1055
 
631
1056
  if directive == "display":
632
- return None
633
1057
 
1058
+ return None
634
1059
  elif directive == "validate":
635
1060
  if valid:
636
1061
  print(Markdown(f"==> Validation of {command} completed successfully!\n"))
637
1062
  else:
638
1063
  msg = f"Validation failed for object_action `{command}`\n"
1064
+ logger.error(msg)
639
1065
  return valid
640
1066
 
641
1067
  elif directive == "process":
642
- print(json.dumps(parsed_output, indent=4))
643
- attributes = parsed_output['attributes']
1068
+ logger.debug(json.dumps(parsed_output, indent=4))
644
1069
 
645
1070
  external_source_guid = attributes.get('External Source Name', {}).get('guid', None)
646
1071
  external_source_name = attributes.get('External Source Name', {}).get('value', None)
@@ -649,333 +1074,214 @@ def process_data_structure_upsert_command(egeria_client: EgeriaTech, txt: str, d
649
1074
  for_duplicate_processing = attributes.get('For Duplicate Processing', {}).get('value', None)
650
1075
  anchor_guid = attributes.get('Anchor ID', {}).get('guid', None)
651
1076
  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.get('Parent ID', {}).get('guid', None)
654
- parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
655
- parent_relationship_properties = attributes.get('Parent Relationship Properties', {}).get('value', None)
656
- parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
657
-
658
- display_name = attributes['Display Name'].get('value', None)
1077
+ # parent_id = attributes.get('Parent ID', {}).get('value', None)
1078
+ # parent_guid = attributes['Parent ID'].get('guid', None)
1079
+ # parent_relationship_type_name = attributes.get('Parent Relationship Type Name', {}).get('value', None)
1080
+ # parent_relationship_properties = attributes.get('Parent Relationship Properties',{}).get('value', None)
1081
+ # parent_at_end1 = attributes.get('Parent at End1', {}).get('value', None)
659
1082
 
660
1083
  namespace = attributes.get('Namespace', {}).get('value', None)
661
1084
  description = attributes.get('Description', {}).get('value', None)
662
1085
  version_id = attributes.get('Version Identifier', {}).get('value', None)
1086
+
1087
+ ###############
1088
+ match_property_names = attributes.get('Match Property Names', {}).get('value', [])
1089
+ specification_details = attributes.get('Specification Details', {}).get('value', {})
1090
+ match_threshold = attributes.get('Match Threshold', {}).get('value', 0)
1091
+ specification = attributes.get('Specification', {}).get('value', None)
1092
+ data_type = attributes.get('Data Type', {}).get('value', None)
1093
+ is_nullable = attributes.get('Is Nullable', {}).get('value', True)
1094
+ allow_duplicates = attributes.get('Allow Duplicates', {}).get('value', True)
1095
+ default_value = attributes.get('Default Value', {}).get('value', None)
1096
+ average_value = attributes.get('Average Value', {}).get('value', None)
1097
+ value_list = attributes.get('Value List', {}).get('value', None)
1098
+ value_range_from = attributes.get('Value Range From', {}).get('value', None)
1099
+ value_range_to = attributes.get('Value Range To', {}).get('value', None)
1100
+ sample_values = attributes.get('Sample Values', {}).get('value', [])
1101
+ data_patterns = attributes.get('Data Patterns', {}).get('value', [])
1102
+ additional_properties = attributes.get('Additional Properties', {}).get('value', {})
1103
+
1104
+ ###############
663
1105
  aliases = attributes.get('Aliases', {}).get('value', None)
664
1106
  name_patterns = attributes.get('Name Patterns', {}).get('value', None)
665
- is_nullable = attributes.get('Is Nullable', {}).get('value', None)
666
- default_value = attributes.get('Default Value', {}).get('value', None)
667
- data_type = attributes.get('Data Type', {}).get('value', None)
1107
+
668
1108
  min_length = attributes.get('Minimum Length', {}).get('value', None)
669
1109
  length = attributes.get('Length', {}).get('value', None)
670
1110
  precision = attributes.get('Precision', {}).get('value', None)
671
1111
  ordered_values = attributes.get('Ordered Values', {}).get('value', None)
672
1112
  sort_order = attributes.get('Sort Order', {}).get('value', None)
673
- additional_properties = attributes.get('Additional Properties', {}).get('value', None)
674
1113
  effective_from = attributes.get('Effective From', {}).get('value', None)
675
1114
  effective_to = attributes.get('Effective To', {}).get('value', None)
676
1115
 
1116
+ glossary_term = attributes.get('Glossary Term', {}).get('value', None)
1117
+ glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
1118
+
1119
+ merge_update = attributes.get('Merge Update', {}).get('value', None)
1120
+
677
1121
  position = attributes.get('Position', {}).get('value', None)
678
1122
  min_cardinality = attributes.get('Minimum Cardinality', {}).get('value', None)
679
1123
  max_cardinality = attributes.get('Maximum Cardinality', {}).get('value', None)
1124
+
680
1125
  in_data_structure = attributes.get('In Data Structure', {}).get('value', None)
1126
+ data_structure_guid_list = attributes.get('In Data Structure', {}).get('guid_list', None)
1127
+ in_data_structure_names = attributes.get('In Data Structure Names', {}).get('name_list', None)
1128
+
681
1129
  data_class = attributes.get('Data Class', {}).get('value', None)
682
1130
  glossary_term = attributes.get('Glossary Term', {}).get('value', None)
1131
+
683
1132
  glossary_term_guid = attributes.get('Glossary Term', {}).get('guid', None)
684
1133
 
685
- # name_details_list = attributes.get("dict_list", None)
1134
+ in_data_dictionary = attributes.get('In Data Dictionary', {}).get('value', None)
1135
+ in_data_dictionary_names = attributes.get('In Data Dictionary', {}).get('name_list', None)
1136
+ data_dict_guid_list = attributes.get("In Data Dictionary", {}).get("guid_list", None)
686
1137
 
687
- in_data_spec = attributes.get("In Data Specification", {}).get("dict_list") # this is a [dict]
688
- data_spec_name_list = attributes.get("In Data Specification", {}).get("name_list", None)
689
- data_spec_value_list = attributes.get("In Data Specification", {}).get("value", None)
1138
+ containing_data_class = attributes.get('Containing Data Class', {}).get('value', None)
1139
+ containing_data_class_guids = attributes.get('Containing Data Class', {}).get('guid_list', None)
1140
+ containing_data_class_names = attributes.get('Containing Data Class', {}).get('name_list', None)
690
1141
 
691
- in_data_dictionary = attributes.get('In Data Dictionary', {}).get('dict_list', None)
692
- data_dict_name_list = attributes.get('In Data Dictionary', {}).get('name_list', None)
693
- data_dict_value_list = attributes.get('In Data Dictionary', {}).get('value', None)
694
-
695
- parent_data_field = attributes.get('Parent Data Field', {}).get('value', None)
696
- parent_data_field_guid = attributes.get('Parent Data Field', {}).get('guid', None)
1142
+ specializes_data_class = attributes.get('Specializes Data Class', {}).get('value', None)
1143
+ specializes_data_class_guid = attributes.get('Specializes Data Class', {}).get('guid', None)
1144
+ specializes_data_class_name = attributes.get('Specializes Data Class', {}).get('name', None)
697
1145
 
698
1146
  anchor_scope_guid = attributes.get('Anchor Scope GUID', {}).get('value', None)
699
1147
 
700
- collection_ordering = "NAME"
701
- order_property_name = "Something"
702
- collection_type = object_type
703
- replace_all_props = True
1148
+ replace_all_props = not merge_update
1149
+
704
1150
  if not valid:
705
1151
  if exists and object_action == "Create":
706
1152
  msg = (f"Create failed because Element `{display_name}` exists - changing `Create` to `Update` in "
707
- f"processed output \n")
708
- print_msg(ERROR, msg, debug_level)
1153
+ f"processed output\n\n___")
1154
+ logger.error(msg)
709
1155
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
710
1156
  else:
1157
+ msg = f"Invalid specification - please review\n\n___"
711
1158
  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
1159
  else:
718
1160
  print(Markdown(f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
719
1161
 
720
1162
  try:
721
1163
  if object_action == "Update":
1164
+ if not exists:
1165
+ logger.error(f"Element `{display_name}` does not exist! Updating result document with Create "
1166
+ f"object_action\n\n___")
1167
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
1168
+
1169
+ # first update the base data class
722
1170
  body = {
723
- "class": "UpdateDataStructureRequestBody",
724
- "externalSourceGUID": external_source_guid,
725
- "externalSourceName": external_source_name,
726
- "effectiveTime": effective_time,
727
- "forLineage": for_lineage,
728
- "forDuplicateProcessing": for_duplicate_processing,
729
- "properties": {
730
- "class": "DataStructureProperties",
731
- "qualifiedName": qualified_name,
732
- "displayName": display_name,
733
- "description": description,
734
- "namespace": namespace,
735
- "versionIdentifier": version_id,
736
- "additionalProperties": additional_properties,
737
- "effectiveFrom": effective_from,
738
- "effectiveTo": effective_to
1171
+ "class": "UpdateDataClassRequestBody", "externalSourceGUID": external_source_guid,
1172
+ "externalSourceName": external_source_name, "effectiveTime": effective_time,
1173
+ "forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing, "properties": {
1174
+ "class": "DataClassProperties", "qualifiedName": qualified_name, "displayName": display_name,
1175
+ "description": description, "namespace": namespace, "matchPropertyNames": match_property_names,
1176
+ "matchThreshold": match_threshold, "specification": specification,
1177
+ "specificationDetails": specification_details, "dataType": data_type,
1178
+ "allowsDuplicateValues": allow_duplicates, "isNullable": is_nullable,
1179
+ "defaultValue": default_value, "averageValue": average_value, "valueList": value_list,
1180
+ "valueRangeFrom": value_range_from, "valueRangeTo": value_range_to,
1181
+ "sampleValues": sample_values, "dataPatterns": data_patterns,
1182
+ "additionalProperties": additional_properties
739
1183
  }
740
1184
  }
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
1185
 
1186
+ egeria_client.update_data_class(guid, body, not merge_update)
1187
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}")
1188
+ # Update data dictionary membership
745
1189
  update_element_dictionary(qualified_name, {
746
1190
  'guid': guid, 'display_name': display_name
747
1191
  })
748
- update_data_collection_memberships(egeria_client, in_data_spec, guid, replace_all_props)
1192
+ core_props = egeria_client.get_data_class_by_guid(guid, None, 'MD')
1193
+
1194
+ # Sync membership in data dictionaries
1195
+ update_data_collection_memberships(egeria_client, object_type, data_dict_guid_list, "DataDictionary",
1196
+ guid, display_name, replace_all_props)
1197
+ logger.success(f"Updating data dictionaries `{in_data_dictionary_names}`")
1198
+ core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
749
1199
 
750
- return egeria_client.get_data_structure_by_guid(guid, output_format='MD')
1200
+ # Sync data field related elements (data structure, parent data fields, terms, data classes
1201
+ sync_data_class_rel_elements(egeria_client, containing_data_class_guids, [glossary_term_guid],
1202
+ specializes_data_class_guid, [glossary_term_guid], guid, display_name,
1203
+ replace_all_props)
1204
+
1205
+ core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
1206
+ core_props += f"\n\n## Containing Data Class\n\n{containing_data_class_names}\n\n"
1207
+ core_props += "\n___\n\n"
1208
+
1209
+ # Update data classes
1210
+ logger.success(f"Updated Element `{display_name}`\n\n___")
1211
+ return core_props
751
1212
 
752
1213
  elif object_action == "Create":
753
- if exists:
754
- print(f"\nTerm `{display_name}` already exists and result document updated\n")
1214
+ if valid is False and exists:
1215
+ logger.error(
1216
+ f"\nData Class `{display_name}` already exists and result document updated changing `Create` "
1217
+ f"to `Update` in processed output\n\n___")
755
1218
  return update_a_command(txt, object_action, object_type, qualified_name, guid)
756
1219
  else:
757
-
1220
+ # First lets create the data class
758
1221
  body = {
759
- "class": "NewDataStructureRequestBody", "externalSourceGUID": external_source_guid,
760
- "externalSourceName": external_source_name, "effectiveTime": effective_time,
761
- "forLineage": False, "forDuplicateProcessing": False, "anchorGUID": anchor_guid,
762
- "isOwnAnchor": is_own_anchor, "parentGUID": parent_guid,
763
- "parentRelationshipTypeName": parent_relationship_type_name,
764
- "parentRelationshipProperties": parent_relationship_properties, "parentAtEnd1": parent_at_end1,
765
1222
  "properties": {
766
- "class": "DataStructureProperties", "qualifiedName": qualified_name,
1223
+ "class": "DataClassProperties", "qualifiedName": qualified_name,
767
1224
  "displayName": display_name, "description": description, "namespace": namespace,
768
- "versionIdentifier": version_id, "additionalProperties": additional_properties,
769
- "effectiveFrom": effective_from, "effectiveTo": effective_to
1225
+ "matchPropertyNames": match_property_names, "matchThreshold": match_threshold,
1226
+ "specification": specification, "specificationDetails": specification_details,
1227
+ "dataType": data_type, "allowsDuplicateValues": allow_duplicates, "isNullable": is_nullable,
1228
+ "defaultValue": default_value, "averageValue": average_value, "valueList": value_list,
1229
+ "valueRangeFrom": value_range_from, "valueRangeTo": value_range_to,
1230
+ "sampleValues": sample_values, "dataPatterns": data_patterns,
1231
+ "additionalProperties": additional_properties
770
1232
  }
771
1233
  }
772
-
773
- guid = egeria_client.create_data_structure_w_body(body_slimmer(body))
1234
+ guid = egeria_client.create_data_class(body)
774
1235
  if guid:
1236
+ # Now update our element dictionary with the new information
775
1237
  update_element_dictionary(qualified_name, {
776
1238
  'guid': guid, 'display_name': display_name
777
1239
  })
1240
+ # Start assembling the information we will present back out
1241
+ core_props = egeria_client.get_data_class_by_guid(guid, None, 'MD')
778
1242
 
779
- core_props = egeria_client.get_data_structure_by_guid(guid, output_format='FORM')
780
-
1243
+ # Add the field to any data dictionaries
781
1244
  if in_data_dictionary:
782
- print_msg(ALWAYS, f"Will add to data dictionary(s) `{in_data_dictionary}`", debug_level)
783
- result = add_member_to_data_collections(egeria_client, in_data_dictionary, display_name,guid )
784
- core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary}\n\n"
785
- # ==>> update to use new function.
786
- if in_data_spec:
787
- # member_body = {
788
- # "class": "CollectionMembershipProperties",
789
- # "membershipRationale": "Adding data structure to data specification",
790
- # "expression": None, "confidence": 100, "status": None, "userDefinedStatus": None,
791
- # "steward": None, "stewardTypeName": None, "stewardPropertyName": None, "source": None,
792
- # "notes": None,
793
- # }
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)
1245
+ logger.info(f"Will add to data dictionary `{in_data_dictionary}`")
1246
+ add_member_to_data_collections(egeria_client, data_dict_guid_list, display_name, guid)
1247
+ core_props += f"\n\n## In Data Dictionary\n\n{in_data_dictionary_names}\n\n"
1248
+
1249
+ if glossary_term:
1250
+ if glossary_term_guid:
1251
+ glossary_body = {
1252
+ "class": "MetadataSourceRequestBody", "externalSourceGUID": external_source_guid,
1253
+ "externalSourceName": external_source_name, "effectiveTime": effective_time,
1254
+ "forLineage": for_lineage, "forDuplicateProcessing": for_duplicate_processing
1255
+ }
1256
+
1257
+ core_props += f"\n\n## Glossary Term \n\n{glossary_term}\n\n"
1258
+ egeria_client.link_semantic_definition(guid, glossary_term_guid, glossary_body)
1259
+
1260
+ if containing_data_class_guids:
1261
+ for dc_guid in containing_data_class_guids:
1262
+ egeria_client.link_nested_data_class(dc_guid, guid)
1263
+ core_props += f"\n\n## Parent Data Field\n\n{containing_data_class_names}\n\n"
1264
+
1265
+ if specializes_data_class_guid:
1266
+ egeria_client.link_specialist_data_class(specializes_data_class_guid, guid)
1267
+ core_props += f"\n\n## Specialized Data Field\n\n{specializes_data_class_name}\n\n"
810
1268
 
1269
+ logger.success(f"Created Element `{display_name}`")
1270
+ core_props += "\n___\n\n"
811
1271
  return core_props
1272
+
812
1273
  else:
813
- print_msg(ERROR, f"Failed to create Data Structure `{display_name}`", debug_level)
1274
+ logger.error(f"Failed to create Term `{display_name}`\n\n___")
814
1275
  return None
815
1276
 
816
-
817
1277
  except Exception as e:
818
- print(f"{ERROR}Error performing {object_action}: {e}")
819
- Console().print_exception(show_locals=True)
1278
+ logger.error(f"Error performing {command}: {e}\n\n___")
820
1279
  return None
821
1280
  else:
822
1281
  return None
823
1282
 
824
1283
 
825
- # def process_data_field_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
826
- # str]:
827
- # """
828
- # Processes a data structure create or update object_action by extracting key attributes such as
829
- # spec name, parent_guid, parent_relationship_type, parent_at_end_1, collection_type
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)
844
-
845
- # object_action = extract_command(txt)
846
- # object_type = object_action.split(' ')[1].strip()
847
- # object_action = object_action.split(' ')[0].strip()
848
-
849
- # parsed_output = parse_user_command(egeria_client, object_type, object_action, txt)
850
-
851
-
852
- # valid = True
853
- #
854
- # set_debug_level(directive)
855
- # known_q_name = None
856
- # object_action = extract_command(txt)
857
- # object_type = object_action.split(' ')[1].strip()
858
- # object_action = object_action.split(' ')[0].strip()
859
- #
860
- # display_name_label = ['Data Structure Name', 'Display Name', 'Name']
861
- #
862
- # display_name = process_simple_attribute(txt, display_name_label, ERROR)
863
- # print(Markdown(f"{pre_command} `{object_action}` for term:`{display_name}` with directive: `{directive}`"))
864
- #
865
- # description = process_simple_attribute(txt, ['Description'], INFO)
866
- # data_type = process_simple_attribute(txt, ['Data Type', "Type"], WARNING)
867
- # positoion = process_simple_attribute(txt, ['Position'], INFO)
868
- # min_cardinalityc = process_simple_attribute(txt, ['Minimum Cardinality', 'Min Cardinality'], WARNING)
869
- # max_cardinality= process_simple_attribute(txt, ['Maximum Cardinality', 'Max Cardinality'], INFO)
870
- # in_data_structure = process_simple_attribute(txt, ['In Data Structure', 'In Data Struct'], INFO)
871
- # data_class = process_simple_attribute(txt, ['Data Class','DataClass'], INFO)
872
- # glossary_term = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, INFO)
873
- # namesspace= process_simple_attribute(txt, ['Namespace'], INFO)
874
- # version_id = process_simple_attribute(txt, ['Version','Version Id', 'Version Identifier'], INFO)
875
- # in_data_dict = process_simple_attribute(txt, ['In Data Dict', 'Data Dictionary', 'In Data Dictionary'], INFO)
876
- #
877
- # q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
878
- #
879
- # # validate display name and get existing qualified_name and guid if they exist
880
- # if display_name is None:
881
- # valid = False
882
- # known_q_name, known_guid, exists = None, None, False
883
- # else:
884
- # known_q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type,
885
- # display_name_label, txt, object_action,
886
- # None)
887
- #
888
- # if object_action == "Update": # check to see if provided information exists and is consistent with existing info
889
- # guid = process_simple_attribute(txt, GUID_LABELS)
890
- #
891
- # display = (f"\n* Command: {object_action}\n\t"
892
- # f"* Name: {display_name}\n\t* Description: {description}\n\t"
893
- # f"* Qualified Name: {q_name}\n\t* GUID: {guid}"
894
- # )
895
- #
896
- # if not exists:
897
- # msg = f"Update request invalid, Term {display_name} does not exist\n"
898
- # print_msg(ERROR, msg, debug_level)
899
- # valid = False
900
- #
901
- # elif object_action == 'Create': # if the object_action is create, check that it doesn't already exist
902
- # display = (f"\n* Command: {object_action}\n\t* Glossary: {known_q_name}\n\t"
903
- # f"* Name: {display_name}\n\t* Description: {description}\n\t"
904
- # f"* Qualified Name: {q_name}\n\t"
905
- # )
906
- # if exists:
907
- # msg = f"Element `{display_name}` cannot be created since it already exists\n"
908
- # print_msg(ERROR, msg, debug_level)
909
- # else:
910
- # msg = f"It is valid to create Element `{display_name}`"
911
- # print_msg(ALWAYS, msg, debug_level)
912
-
913
- # if directive == "display":
914
- # print(Markdown(display))
915
- # return None
916
- # elif directive == "validate":
917
- # if valid:
918
- # print(Markdown(display))
919
- # else:
920
- # msg = f"Validation failed for Term `{display_name}`\n"
921
- # print_msg(ERROR, msg, debug_level)
922
- # print(Markdown(display))
923
- # return valid
924
- #
925
- # elif directive == "process":
926
- # if valid:
927
- # print(Markdown(display))
928
- # else:
929
- # if exists and object_action == "Create":
930
- # msg = f"Create failed because Element `{display_name}` exists - changing `Create` to `Update` in
931
- # processed output \n"
932
- # print_msg(ERROR, msg, debug_level)
933
- # print(Markdown(display))
934
- # return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
935
- # else:
936
- # return None
937
- #
938
- # try:
939
- # if object_action == "Update":
940
- # if not exists:
941
- # print(f"\n{ERROR}Element `{display_name}` does not exist! Updating result document with Create "
942
- # f"object_action\n")
943
- # return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
944
- #
945
- # egeria_client.update_term(known_guid, body)
946
- # print_msg(ALWAYS, f"Updated Term `{term_name}` with GUID {known_guid}", debug_level)
947
- # update_element_dictionary(known_q_name, {
948
- # 'guid': known_guid, 'display_name': term_name
949
- # })
950
- #
951
- # return egeria_client.get_term_by_guid(known_guid, output_format='MD')
952
- #
953
- # elif object_action == "Create":
954
- # if exists:
955
- # print(f"\nTerm `{display_name}` already exists and result document updated\n")
956
- # return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
957
- # else:
958
- # guid = egeria_client.create_data_spec_collection(None, None, None,
959
- # True, display_name, description,
960
- # collection_type, None,
961
- # True, None)
962
- # if guid:
963
- # print_msg(ALWAYS, f"Created Element `{display_name}` with GUID {guid}", debug_level)
964
- # # Add categories if specified
965
- #
966
- # return egeria_client.get_collection_by_guid(guid, output_format='FORM')
967
- # else:
968
- # print_msg(ERROR, f"Failed to create Term `{display_name}`", debug_level)
969
- # return None
970
- #
971
- # except Exception as e:
972
- # print(f"{ERROR}Error performing {object_action}: {e}")
973
- # Console().print_exception(show_locals=True)
974
- # return None
975
- # else:
976
- # return None
977
- #
978
- #
1284
+ @logger.catch
979
1285
  def process_data_dict_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
980
1286
  """
981
1287
  Processes a Data Dictionary list object_action by extracting key attributes such as
@@ -986,28 +1292,26 @@ def process_data_dict_list_command(egeria_client: EgeriaTech, txt: str, directiv
986
1292
  :param directive: an optional string indicating the directive to be used - display, validate or execute
987
1293
  :return: A string summarizing the outcome of the processing.
988
1294
  """
989
- from md_processing.md_processing_utils.common_md_utils import set_debug_level
990
-
991
- set_debug_level(directive)
992
- known_q_name = None
993
1295
  command, object_type, object_action = extract_command_plus(txt)
994
1296
 
995
- object_action = extract_command(txt)
996
- set_debug_level(directive)
1297
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
1298
+
1299
+ attributes = parsed_output['attributes']
997
1300
 
998
- parsed_output = parse_user_command(egeria_client, object_action, 'View', txt)
999
- print(Markdown(parsed_output['display']))
1000
1301
  valid = parsed_output['valid']
1001
1302
 
1303
+ print(Markdown(parsed_output['display']))
1304
+
1002
1305
  if directive == "display":
1003
1306
  return None
1004
1307
  elif directive == "validate":
1005
1308
  if valid:
1006
- msg = f"Validation passed for {object_action} `{object_type}`\n"
1309
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
1007
1310
  else:
1008
- msg = f"Validation failed for {object_action} `{object_type}`\n"
1009
- print_msg(ERROR, msg, debug_level)
1311
+ msg = f"Validation failed for object_action `{command}`\n"
1312
+ logger.error(msg)
1010
1313
  return valid
1314
+
1011
1315
  elif directive == "process":
1012
1316
  attributes = parsed_output['attributes']
1013
1317
  search_string = attributes.get('Search String', {}).get('value', '*')
@@ -1017,7 +1321,7 @@ def process_data_dict_list_command(egeria_client: EgeriaTech, txt: str, directiv
1017
1321
  try:
1018
1322
  if not valid: # First validate the command before we process it
1019
1323
  msg = f"Validation failed for {object_action} `{object_type}`\n"
1020
- print_msg(ERROR, msg, debug_level)
1324
+ logger.error(msg)
1021
1325
  return None
1022
1326
 
1023
1327
  list_md = f"\n# Data Dictionaries with filter: `{search_string}`\n\n"
@@ -1026,50 +1330,29 @@ def process_data_dict_list_command(egeria_client: EgeriaTech, txt: str, directiv
1026
1330
  list_md += f"```{json.dumps(struct, indent=4)}```\n"
1027
1331
  else:
1028
1332
  list_md += egeria_client.find_collections(search_string, output_format=output_format)
1029
- print_msg("ALWAYS", f"Wrote Dictionaries for search string: `{search_string}`", debug_level)
1333
+ logger.info(f"Wrote Dictionaries for search string: `{search_string}`")
1030
1334
 
1031
1335
  return list_md
1032
1336
 
1033
1337
  except Exception as e:
1034
- print(f"{ERROR}Error performing {command}: {e}")
1338
+ logger.error(f"Error performing {command}: {e}")
1035
1339
  console.print_exception(show_locals=True)
1036
1340
  return None
1037
1341
  else:
1038
1342
  return None
1039
1343
 
1040
- # def process_term_details_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1344
+ # @logger.catch
1345
+ # def process_list_data_dictionary_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") ->
1346
+ # Optional[str]:
1041
1347
  # """
1042
- # Processes a term details object_action by extracting key attributes such as
1043
- # term name and output format from the given text.
1348
+ # Processes a list data dictionary.
1044
1349
  #
1045
1350
  # :param txt: A string representing the input cell to be processed for
1046
1351
  # extracting term-related attributes.
1047
1352
  # :param directive: an optional string indicating the directive to be used - display, validate or execute
1048
1353
  # :return: A string summarizing the outcome of the processing.
1049
1354
  # """
1050
- # from md_processing.md_processing_utils.common_md_utils import set_debug_level
1051
1355
  #
1052
- # object_action = extract_command(txt)
1053
- # set_debug_level(directive)
1054
- # print(Markdown(f"{pre_command} `{object_action}` with directive: `{directive}`"))
1055
- #
1056
- # term_name = process_simple_attribute(txt, TERM_NAME_LABELS, ERROR)
1057
- # output_format = process_simple_attribute(txt, OUTPUT_LABELS)
1058
- # output_format = output_format.upper() if output_format else "MD"
1059
- # if output_format not in ELEMENT_OUTPUT_FORMATS:
1060
- # print_msg(WARNING, f"Output format {output_format} not recognized, using MD", debug_level)
1061
- # output_format = "MD"
1062
- #
1063
- # if term_name is None:
1064
- # print_msg(ERROR, "No term name found", debug_level)
1065
- # return None
1066
- #
1067
- # known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, "Term",
1068
- # TERM_NAME_LABELS, txt,
1069
- # EXISTS_REQUIRED, None)
1070
- # if not term_exists:
1071
- # print_msg(ERROR, f"Term {term_name} not found", debug_level)
1072
- # return None
1073
1356
  #
1074
1357
  # if directive == "display":
1075
1358
  # print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
@@ -1083,7 +1366,7 @@ def process_data_dict_list_command(egeria_client: EgeriaTech, txt: str, directiv
1083
1366
  # print(Markdown(f"\n* Command: {object_action}\n\t* Term Name: {term_name}\n\t* Output Format: {
1084
1367
  # output_format}"))
1085
1368
  # return egeria_client.get_term_by_guid(known_guid, output_format=output_format)
1086
- #
1369
+
1087
1370
  #
1088
1371
  # def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1089
1372
  # """