pyegeria 5.3.7.8__py3-none-any.whl → 5.3.8.1__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.
@@ -5,44 +5,57 @@ This file contains functions to parse and process Egeria Markdown (Freddie)
5
5
 
6
6
  """
7
7
 
8
- import json
9
- from jupyter_notebook_parser import JupyterNotebookParser
10
- import nbformat
11
- from typing import List, Optional
12
-
13
8
  import os
14
9
  import re
10
+ import sys
11
+ from datetime import datetime
12
+ from typing import List, Optional
15
13
 
16
- from rich import box, print
14
+ from prompt_toolkit.filters import Always
15
+ from rich import print
17
16
  from rich.console import Console
18
17
  from rich.markdown import Markdown
19
18
 
20
19
  from pyegeria import body_slimmer
21
- from pyegeria._globals import NO_TERMS_FOUND, NO_GLOSSARIES_FOUND, NO_TERMS_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, NO_CATEGORIES_FOUND
20
+ from pyegeria._globals import (NO_GLOSSARIES_FOUND, NO_TERMS_FOUND, NO_ELEMENTS_FOUND,
21
+ NO_PROJECTS_FOUND, \
22
+ NO_CATEGORIES_FOUND)
22
23
  from pyegeria.egeria_tech_client import EgeriaTech
24
+
23
25
  # from pyegeria.md_processing_helpers import process_q_name_list
24
26
  from pyegeria.project_manager_omvs import ProjectManager
25
- from pyegeria.glossary_manager_omvs import GlossaryManager
26
- from pyegeria.shared_state import get_element_dictionary, update_element_dictionary
27
+ from pyegeria.shared_state import get_element_dictionary, update_element_dictionary, find_key_with_value
27
28
 
28
- from datetime import datetime
29
29
  EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "170"))
30
30
  console = Console(width=EGERIA_WIDTH)
31
31
 
32
- command_list = ["Provenance",
33
- "Create Glossary", "Update Glossary",
34
- "Create Term", "Update Term",
35
- "Create Personal Project", "Update Personal Project",
36
- "Create Category", "Update Category",
37
- "Create Solution Blueprint", "Update Solution Blueprint",
38
- "Create Solution Component", "Update Solution Component",]
39
-
40
- ERROR = "ERROR-> "
41
- INFO = "INFO- "
42
- WARNING = "WARNING-> "
32
+ command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term",
33
+ "Create Personal Project", "Update Personal Project", "Create Category", "Update Category",
34
+ "Create Solution Blueprint", "Update Solution Blueprint", "Create Solution Component",
35
+ "Update Solution Component", ]
36
+ # verbosity - verbose, quiet, debug
37
+ debug_level = "verbose"
38
+ message_types = {
39
+ "INFO": "INFO-", "WARNING": "WARNING->", "ERROR": "ERROR->", "DEBUG-INFO": "DEBUG-INFO->",
40
+ "DEBUG-WARNING": "DEBUG-WARNING->", "DEBUG-ERROR": "DEBUG-ERROR->", "ALWAYS": "\n\n==> "
41
+ }
42
+ ALWAYS = "ALWAYS"
43
+ ERROR = "ERROR"
44
+ INFO = "INFO"
45
+ WARNING = "WARNING"
43
46
  pre_command = "\n---\n==> Processing command:"
44
-
45
-
47
+ command_seperator = Markdown("\n---\n")
48
+
49
+ GLOSSARY_NAME_LABELS = ["Glossary Name", "Glossary", "Glossaries", "Owning Glossary", "In Glossary"]
50
+ CATEGORY_NAME_LABELS = [ "Glossary Category Name", "Glossary Category", "Glossary Categories", "Category Name", "Category", "Categories"]
51
+ TERM_NAME_LABELS= ["Glossary Term Name", "Glossary Term", "Glossary Terms", "Term Name", "Term", "Terms", "Term Names"]
52
+ PROJECT_NAME_LABELS = ["Project Name", "Project", "Project Names", "Projects"]
53
+ BLUEPRINT_NAME_LABELS = ["Solution Blueprint Name", "Solution Blueprint", "Solution Blueprints", "Blueprint Name", "Blueprint", "Blueprints"]
54
+ COMPONENT_NAME_LABELS = ["Solution Component Name", "Solution Component", "Solution Components", "Component Name", "Component", "Components", "Parent Components", "Parent Component"]
55
+ SOLUTION_ROLE_LABELS = ["Solution Role Name", "Solution Role", "Solution Roles", "Role Name", "Role", "Roles"]
56
+ SOLUTION_ACTOR_ROLE_LABELS = [ "Solution Actor Role Name", "Solution Actor Role Names","Solution Actor Role", "Solution Actor Roles", "Actor Role Name", "Actor Role", "Actor Roles", "Actor Role Names"]
57
+ SOLUTION_LINKING_ROLE_LABELS = [ "Solution Linking Role Name", "Solution Linking Role Names", "Solution Linking Role", "Solution Linking Roles", "Linking Role Name", "Linking Role", "Linking Roles", "Linking Role Names"]
58
+ GUID_LABELS = ['GUID','guid']
46
59
 
47
60
  def render_markdown(markdown_text: str) -> None:
48
61
  """Renders the given markdown text in the console."""
@@ -64,9 +77,30 @@ def get_current_datetime_string():
64
77
  return now
65
78
 
66
79
 
67
- def add_term_to_categories(egeria_client: GlossaryManager, term_guid: str, categories_exist: bool,
68
- categories_list: List[str], element_dictionary: dict) -> None:
80
+ def add_term_to_categories(egeria_client: EgeriaTech, term_guid: str, categories_exist: bool,
81
+ categories_list: List[str]) -> None:
82
+ """
83
+ Adds a term to specified categories in a glossary.
84
+
85
+ This function associates a term, identified by its GUID, with one or more
86
+ categories. It uses the provided EgeriaTech client to assign the term
87
+ to the categories. If the GUID of a category is not readily available, it
88
+ is retrieved either from a pre-loaded dictionary or through a client lookup.
89
+
90
+ Args:
91
+ egeria_client (EgeriaTech): The client to interact with the glossary.
92
+ term_guid (str): The GUID of the term to be associated with categories.
93
+ categories_exist (bool): Flag indicating whether the categories already
94
+ exist.
95
+ categories_list (List[str]): A list of category names to associate with
96
+ the term.
97
+
98
+ Returns:
99
+ None
100
+ """
69
101
  if categories_exist is True and categories_list is not None:
102
+ if type(categories_list) is str:
103
+ categories_list = categories_list.split(",").trim()
70
104
  for category in categories_list:
71
105
  cat_guid = None
72
106
  cat_el = category.strip()
@@ -79,24 +113,63 @@ def add_term_to_categories(egeria_client: GlossaryManager, term_guid: str, categ
79
113
  egeria_client.add_term_to_category(term_guid, cat_guid)
80
114
 
81
115
 
82
- def extract_command_plus(block: str) -> tuple[str, str] | None:
116
+ def extract_command_plus(block: str) -> tuple[str, str, str] | None:
117
+ """
118
+ Extracts a multi-word object and its associated action from the given block of text.
119
+
120
+ This function searches for a pattern in the format of `#...##` or `#...\n`
121
+ inside the provided string `block`. The matched pattern is split into
122
+ two parts: the action and the object type. The action is expected to
123
+ be the first part, while the rest is treated as the object type. If
124
+ no match is found, the function returns None.
125
+
126
+ Args:
127
+ block: A string containing the block of text to search for the
128
+ command and action.
129
+
130
+ Returns:
131
+ A tuple containing the command, the object type and the object action if a
132
+ match is found. Otherwise, returns None.
133
+ """
83
134
  match = re.search(r"#(.*?)(?:##|\n|$)", block) # Using a non capturing group
84
135
  if match:
85
136
  clean_match = match.group(1).strip()
86
- parts = clean_match.split(' ')
87
- object_action = parts[0].strip()
137
+ if ' ' in clean_match:
138
+ parts = clean_match.split(' ')
139
+ object_action = parts[0].strip()
88
140
  # Join the rest of the parts to allow object_type to be one or two words
89
- object_type = ' '.join(parts[1:]).strip()
90
- return object_type, object_action
141
+ object_type = ' '.join(parts[1:]).strip()
142
+ else:
143
+ object_type = clean_match.split(' ')[1].strip()
144
+ object_action = clean_match.split(' ')[0].strip()
145
+
146
+ return clean_match, object_type, object_action
91
147
  return None
92
148
 
149
+
93
150
  def extract_command(block: str) -> str | None:
151
+ """
152
+ Extracts a command from a block of text that is contained between a single hash ('#') and
153
+ either a double hash ('##'), a newline character, or the end of the string.
154
+
155
+ The function searches for a specific pattern within the block of text and extracts the
156
+ content that appears immediately after a single hash ('#'). Ensures that the extracted
157
+ content is appropriately trimmed of leading or trailing whitespace, if present.
158
+
159
+ Args:
160
+ block: A string representing the block of text to process. Contains the content
161
+ in which the command and delimiters are expected to be present.
162
+
163
+ Returns:
164
+ The extracted command as a string if a match is found, otherwise None.
165
+ """
94
166
  match = re.search(r"#(.*?)(?:##|\n|$)", block) # Using a non capturing group
95
167
  if match:
96
168
  return match.group(1).strip()
97
169
  return None
98
170
 
99
- def extract_attribute(text: str, labels: List[str]) -> Optional[str]:
171
+
172
+ def extract_attribute(text: str, labels: [str]) -> str | None:
100
173
  """
101
174
  Extracts the glossary name from a string.
102
175
 
@@ -110,17 +183,93 @@ def extract_attribute(text: str, labels: List[str]) -> Optional[str]:
110
183
  # Iterate over the list of labels
111
184
  for label in labels:
112
185
  # Construct pattern for the current label
113
- pattern = rf"## {re.escape(label)}\n(.*?)(?:#|---|$)"
186
+ pattern = rf"## {re.escape(label)}\n(.*?)(?:#|___|$)" # modified from --- to enable embedded tables
114
187
  match = re.search(pattern, text, re.DOTALL)
115
188
  if match:
116
189
  # Extract matched text and replace consecutive \n with a single \n
117
190
  extracted_text = re.sub(r'\n+', '\n', match.group(1).strip())
118
191
  if not extracted_text.isspace() and extracted_text:
119
- return extracted_text # Return the cleaned text
192
+ return extracted_text.title() # Return the cleaned text
193
+
120
194
 
195
+ def print_msg(msg_level: str, msg: str, verbosity: str):
196
+ """
197
+ Prints a message based on its type and verbosity level.
198
+
199
+ This function handles the output of messages depending on the specified
200
+ verbosity level and message type. It uses predefined message types and
201
+ formats the output accordingly.
202
+
203
+ Args:
204
+ msg_type: The type of the message, such as 'WARNING', 'ERROR', 'INFO', or
205
+ 'ALWAYS'.
206
+ msg: The content of the message to display.
207
+ verbosity: The verbosity level, which determines how the message is
208
+ displayed ('verbose', 'quiet', or 'debug').
209
+ """
210
+ msg_level = msg_level.upper()
211
+ record = f"{message_types[msg_level]} {msg}"
212
+ if msg_level in ("WARNING", "ERROR", "INFO"):
213
+ record = f"* {record}"
214
+
215
+ match verbosity.lower():
216
+ case "verbose":
217
+ if msg_level in ("WARNING", "ERROR", "INFO", "ALWAYS"):
218
+ print(record)
219
+ case "quiet":
220
+ if msg_level in ("WARNING", "ERROR", "ALWAYS"):
221
+ print(record)
222
+ case "debug":
223
+ print(record)
224
+ case _:
225
+ print("Invalid verbosity level - exiting\n")
226
+ sys.exit(1)
227
+
228
+ def process_simple_attribute(txt: str, labels: [str], if_missing: str = INFO) -> str | None:
229
+ """Process a simple attribute based on the provided labels and if_missing value.
230
+ Extract the attribute value from the text and return it if it exists.
231
+ If it doesn`t exist, return None and print an error message with severity of if_missing.
232
+
233
+ Parameters:
234
+ ----------
235
+ txt: str
236
+ The block of command text to extract attributes from.
237
+ labels: list
238
+ The possible attribute labels to search for. The first label will be used in messages.
239
+ if_missing: str, default is INFO
240
+ Can be one of "WARNING", "ERROR", "INFO". The severity of the missing attribute.
241
+ """
242
+ if if_missing not in ["WARNING", "ERROR", "INFO"]:
243
+ print_msg("ERROR", "Invalid severity for missing attribute", debug_level)
244
+ return None
121
245
 
246
+ attribute = extract_attribute(txt, labels)
247
+
248
+ if attribute is None:
249
+ msg = f"Missing {labels[0]} attribute"
250
+ print_msg(if_missing, msg, debug_level)
251
+ return None
252
+ return attribute
122
253
 
123
254
  def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid: str) -> str:
255
+ """
256
+ Updates a command by modifying the input text with corresponding actions, GUID, and qualified name.
257
+ The function processes the provided command based on the given parameters, updating the relevant
258
+ sections in the text, including command actions, GUID, qualified name, and optionally the status
259
+ of the attributes. It ensures that proper formatting and necessary fields are present in the text.
260
+
261
+ Args:
262
+ txt (str): The input text containing the content to be updated.
263
+ command (str): The command to be processed (e.g., "Create Term", "Update Term").
264
+ obj_type (str): The object type related to the command (e.g., "Term", "Category").
265
+ q_name (str): The qualified name to be added or updated in the text.
266
+ u_guid (str): The unique identifier (GUID) to be added or updated in the text. If not provided,
267
+ it defaults to an empty string.
268
+
269
+ Returns:
270
+ str: The updated text containing the modifications based on the provided command.
271
+
272
+ """
124
273
  u_guid = u_guid if u_guid else " "
125
274
  verb = command.split(' ')[0].strip()
126
275
  action = "Update" if (verb == "Create" and u_guid is not None) else "Create"
@@ -132,12 +281,6 @@ def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid:
132
281
  if "GUID" not in txt:
133
282
  txt += f"\n## GUID\n{u_guid}\n"
134
283
 
135
- # if (command in {"Update Term", "Update Category", 'Update Glossary'}) and ("Update Description" not in txt):
136
- # txt += '\n** Update Description\n\n\n'
137
- # elif "Update Description" in txt:
138
- # pattern = r"(## Update Description\n).*?(#)"
139
- # replacement = r"\1\n\n\2"
140
- # txt += re.sub(pattern, replacement, txt)
141
284
 
142
285
  status = extract_attribute(txt, ["Status"])
143
286
  if command in ["Create Term", "Update Term"] and status is None:
@@ -146,6 +289,7 @@ def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid:
146
289
  txt = re.sub(pattern, replacement, txt)
147
290
  return txt
148
291
 
292
+
149
293
  def process_provenance_command(file_path: str, txt: [str]) -> str:
150
294
  """This commands processes a provenence command by pre-pending the current file name and time to the provenance
151
295
  output"""
@@ -157,24 +301,27 @@ def process_provenance_command(file_path: str, txt: [str]) -> str:
157
301
  # Extract matched text and replace consecutive \n with a single \n
158
302
  extracted_text = re.sub(r'\n+', '\n', match.group(1).strip())
159
303
  if not extracted_text.isspace() and extracted_text:
160
- existing_prov = extracted_text # Return the cleaned text
304
+ existing_prov = extracted_text # Return the cleaned text
161
305
  else:
162
306
  existing_prov = None
163
307
  print(f"txt is: {txt}, existing_prov: {existing_prov}")
164
308
  existing_prov = existing_prov if existing_prov else " "
165
309
  return f"\n# Provenance:\n{existing_prov}\n{output}\n"
166
310
 
167
- def process_element_identifiers(egeria_client: EgeriaTech, element_type:str, txt: str, action: str, version: str=None) \
168
- -> tuple[str, str, str, bool, bool]:
311
+
312
+ def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, element_labels: [str], txt: str, action: str,
313
+ version: str = None) -> tuple[str, str, bool, bool]:
169
314
  """
170
315
  Processes element identifiers by extracting display name and qualified name from the input text,
171
316
  checking if the element exists in Egeria, and validating the information.
172
317
 
173
318
  Parameters:
319
+ element_labels:
174
320
  egeria_client: EgeriaTech
175
321
  Client object for interacting with Egeria.
176
322
  element_type: str
177
323
  type of element to process (e.g., 'blueprint', 'category', 'term')
324
+ element_labels: a list of equivalent label names to use in processing the element.
178
325
  txt: str
179
326
  A string representing the input text to be processed for extracting element identifiers.
180
327
  action: str
@@ -186,46 +333,63 @@ def process_element_identifiers(egeria_client: EgeriaTech, element_type:str, txt
186
333
  A tuple containing:
187
334
  - qualified_name: Empty string or element identifier
188
335
  - guid: Empty string or additional element information
189
- - msg: Information or error messages about the processing
190
336
  - Valid: Boolean indicating if the element information is valid
191
337
  - Exists: Boolean indicating if the element exists in Egeria
192
338
  """
193
- msg = ""
194
- guid = None
195
339
  valid = True
196
- exists = False
197
- unique: bool | None = None
198
- display_name = extract_attribute(txt, ["Display Name"])
199
340
 
341
+ element_name = extract_attribute(txt, element_labels)
200
342
  qualified_name = extract_attribute(txt, ["Qualified Name"])
343
+
344
+
201
345
  if qualified_name:
202
- q_name, guid, msg, unique, exists = get_element_by_name(egeria_client,element_type,qualified_name)
203
- # Qualified name could be different if it is being updated
346
+ q_name, guid, unique, exists = get_element_by_name(egeria_client, element_type,
347
+ qualified_name) # Qualified name could be different if it is being updated
204
348
  else:
205
- q_name, guid, msg, unique, exists = get_element_by_name(egeria_client,element_type,display_name)
349
+ q_name, guid, unique, exists = get_element_by_name(egeria_client, element_type, element_name)
206
350
  if unique is False:
207
- msg += f"{ERROR} Multiple elements named {display_name} found\n"
351
+ msg = f"Multiple elements named {element_name} found"
352
+ print_msg("DEBUG-ERROR", msg, debug_level)
208
353
  valid = False
354
+
209
355
  if action == "Update" and not exists:
210
- msg += f"* {ERROR}Element {display_name} does not exist\n"
356
+ msg = f"Element {element_name} does not exist"
357
+ print_msg("DEBUG-ERROR", msg, debug_level)
211
358
  valid = False
359
+
212
360
  elif action == "Update" and exists:
213
- msg += f"* {INFO}Element {display_name} exists\n"
361
+ msg = f"Element {element_name} exists"
362
+ print_msg("DEBUG-INFO", msg, debug_level)
363
+
214
364
  elif action == "Create" and exists:
215
- msg += f"* {ERROR}Element {display_name} already exists\n"
365
+ msg = f"Element {element_name} already exists"
366
+ print_msg("DEBUG-ERROR", msg, debug_level)
216
367
  valid = False
368
+
217
369
  elif action == "Create" and not exists:
218
- msg += f"* {INFO}Element {display_name} does not exist and can be created\n"
219
- if q_name is None:
220
- q_name = egeria_client.__create_qualified_name__(element_type, display_name,
221
- version_identifier=version)
222
- update_element_dictionary(q_name, {'display_name': display_name})
370
+ msg = f"{element_type} `{element_name}` does not exist"
371
+ print_msg("DEBUG-INFO", msg, debug_level)
372
+
373
+ if q_name is None and qualified_name is None:
374
+ q_name = egeria_client.__create_qualified_name__(element_type, element_name, version_identifier=version)
375
+ update_element_dictionary(q_name, {'display_name': element_name})
376
+ elif qualified_name:
377
+ update_element_dictionary(qualified_name, {'display_name': element_name})
378
+ elif action == "Exists Required":
379
+ if not exists:
380
+ msg = f"Required {element_type} `{element_name}` does not exist"
381
+ print_msg("DEBUG-ERROR", msg, debug_level)
382
+ valid = False
383
+ else:
384
+ msg = f"Required {element_type} `{element_name}` exists"
385
+ print_msg("DEBUG-INFO", msg, debug_level)
386
+ valid = True
223
387
 
224
- return q_name, guid, msg, valid, exists
388
+ return q_name, guid, valid, exists
225
389
 
226
390
 
227
- def get_element_by_name(egeria_client, element_type: str, element_name: str)\
228
- ->tuple[str | None, str | None, str, bool | None, bool | None]:
391
+ def get_element_by_name(egeria_client, element_type: str, element_name: str) -> tuple[
392
+ str | None, str | None, bool | None, bool | None]:
229
393
  """
230
394
  Generalized function to retrieve an element by name based on its type.
231
395
 
@@ -238,92 +402,111 @@ def get_element_by_name(egeria_client, element_type: str, element_name: str)\
238
402
  The name of the element to retrieve.
239
403
 
240
404
  Returns:
241
- tuple of qualified_name, guid, msg, uniqye, exists
405
+ tuple of qualified_name, guid, uniqye, exists
242
406
  """
243
407
  unique = None
408
+
244
409
  element_dict = get_element_dictionary()
245
- if element_name in element_dict: # use information from element_dictionary
246
- guid = element_dict[element_name].get('guid',None)
410
+ q_name = find_key_with_value(element_name)
411
+ if q_name: # use information from element_dictionary
412
+ guid = element_dict[q_name].get('guid', None)
247
413
  unique = True
248
- exists = False
249
- if guid is not None: # Found complete entry in element_dictionary
250
- return element_name, guid, 'Found qualified name', unique, exists
251
- else: # Missing guid from element_dictionary
414
+ exists = True
415
+ if guid is not None: # Found complete entry in element_dictionary
416
+ msg = f'Found {element_type} qualified name and guid in element_dictionary for `{element_name}`'
417
+ print_msg("DEBUG-INFO", msg, debug_level)
418
+ return q_name, guid, unique, exists
419
+
420
+ else: # Missing guid from element_dictionary
252
421
  guid = egeria_client.get_element_guid_by_unique_name(element_name)
253
422
  if guid == NO_ELEMENTS_FOUND:
254
- exists = False
255
- msg = f"{INFO}No {element_type} guid found with name {element_name}\n"
256
- return element_name, None, msg, unique, exists
423
+ guid = None
424
+ msg = f"No {element_type} guid found with name {element_name} in Egeria"
425
+ print_msg("DEBUG-INFO", msg, debug_level)
426
+
427
+ return q_name, guid, unique, exists
257
428
  else:
258
429
  exists = True
259
- update_element_dictionary(element_name, {'guid': guid})
260
- return element_name, guid, 'Found qualified name', unique, exists
430
+ update_element_dictionary(q_name, {'guid': guid})
431
+ msg = f"Found guid value of {guid} for {element_name} in Egeria"
432
+ print_msg("DEBUG-INFO", msg, debug_level)
433
+
434
+ return q_name, guid, unique, exists
261
435
 
262
436
  # Haven't seen this element before
263
437
  property_names = ['qualifiedName', 'name', 'displayName']
264
438
  open_metadata_type_name = None
265
- details = egeria_client.get_elements_by_property_value(
266
- element_name, property_names, open_metadata_type_name
267
- )
439
+ details = egeria_client.get_elements_by_property_value(element_name, property_names, open_metadata_type_name)
268
440
  if isinstance(details, str):
269
- msg = f"{INFO}{element_type} `{element_name}` not found\n"
441
+ msg = f"{element_type} `{element_name}` not found in Egeria"
442
+ print_msg("DEBUG-INFO", msg, debug_level)
270
443
  exists = False
271
- return element_name, None, msg, unique, exists
444
+ return None, None, unique, exists
272
445
  if len(details) > 1:
273
- msg = (f"{ERROR}More than one element with name {element_name} found, please specify a "
274
- f"**Qualified Name**\n")
275
- unique= False
446
+ msg = (f"More than one element with name {element_name} found, please specify a "
447
+ f"**Qualified Name**")
448
+ print_msg("DEBUG-ERROR", msg, debug_level)
449
+ unique = False
276
450
  exists = None
277
- return element_name, None, msg, unique, exists
451
+ return element_name, None, unique, exists
278
452
 
279
453
  el_qname = details[0]["properties"].get('qualifiedName', None)
280
454
  el_guid = details[0]['elementHeader']['guid']
281
455
  el_display_name = details[0]["properties"].get('displayName', None)
282
456
  update_element_dictionary(el_qname, {
283
- 'guid': el_guid,
284
- 'displayName': el_display_name
457
+ 'guid': el_guid, 'displayName': el_display_name
285
458
  })
286
- msg = f"{INFO}Found {element_type} `{element_name}`\n"
459
+ msg = f"Found {element_type} `{el_display_name}` with qualified name `{el_qname}`"
460
+ print_msg("DEBUG-INFO", msg, debug_level)
287
461
  exists = True
288
462
  unique = True
289
- return el_qname, el_guid, msg, unique, exists
290
-
291
- # Convert element_type to plural form for method name construction
292
- # if element_type.endswith('y'):
293
- # plural_type = f"{element_type[:-1]}ies"
294
- # elif element_type.endswith('s'):
295
- # plural_type = f"{element_type}es"
296
- # else:
297
- # plural_type = f"{element_type}s"
298
- #
299
- # # Construct method name
300
- # method_name = f"get_{plural_type}_by_name"
301
- #
302
- # # Check if the method exists on the client
303
- # if hasattr(egeria_client, method_name):
304
- # # Call the method
305
- # method = getattr(egeria_client, method_name)
306
- # result = method(element_name)
307
- # return result
308
- # else:
309
- # # Method doesn't exist
310
- # return f"Method {method_name} not found on client"
311
-
312
-
313
-
314
- def process_q_name_list(egeria_client: EgeriaTech, element_type: str, txt: str) -> tuple[
315
- str | None, list | None, str | None, bool, bool]:
316
- msg = ""
317
- known_guid = None
463
+ return el_qname, el_guid, unique, exists
464
+
465
+ # Convert element_type to plural form for method name construction # if element_type.endswith('y'): #
466
+ # plural_type = f"{element_type[:-1]}ies" # elif element_type.endswith('s'): # plural_type = f"{
467
+ # element_type}es" # else: # plural_type = f"{element_type}s" # # # Construct method name # method_name
468
+ # = f"get_{plural_type}_by_name" # # # Check if the method exists on the client # if hasattr(egeria_client,
469
+ # method_name): # # Call the method # method = getattr(egeria_client, method_name) # result =
470
+ # method(element_name) # return result # else: # # Method doesn't exist # return f"Method {
471
+ # method_name} not found on client"
472
+
473
+
474
+ def process_q_name_list(egeria_client: EgeriaTech, element_type: str, txt: str, element_labels: [str]) -> tuple[
475
+ str | None, list | None, bool, bool]:
476
+ """
477
+ Processes a list of qualified names specified in the given text, retrieves details for each
478
+ element based on the provided type, and generates a list of valid qualified names.
479
+
480
+ The function reads a text block, extracts a list of element names according to the specified
481
+ element type, looks them up using the provided Egeria client, and classifies them as valid or
482
+ invalid. It returns the processed names, a list of qualified names, and validity and existence
483
+ flags.
484
+
485
+ Args:
486
+
487
+ egeria_client (EgeriaTech): The client instance to connect and query elements from an
488
+ external system.
489
+ element_type (str): The type of element, such as schema or attribute, to process.
490
+ txt (str): The raw input text containing element names to be processed.
491
+ element_labels: a list of equivalent label names to use in processing the element.
492
+
493
+ Returns:
494
+ tuple[str | None, list | None, bool, bool]: A tuple containing:
495
+ - Concatenated valid input names as a single string (or None if empty).
496
+ - A list of known qualified names extracted from the processed elements.
497
+ - A boolean indicating whether all elements are valid.
498
+ - A boolean indicating whether all elements exist.
499
+ """
318
500
  valid = True
319
- exists = False
501
+ exists = True
320
502
  elements = ""
321
503
  new_element_list = []
322
504
 
323
- elements_txt = extract_attribute(txt, [element_type])
505
+ elements_txt = extract_attribute(txt, element_labels)
324
506
 
325
507
  if elements_txt is None:
326
- msg += f"* {INFO}No {element_type}s found\n"
508
+ msg = f"No {element_type} found"
509
+ print_msg("DEBUG-INFO", msg, debug_level)
327
510
 
328
511
  else:
329
512
  element_list = re.split(r'[,\n]+', elements_txt)
@@ -332,30 +515,31 @@ def process_q_name_list(egeria_client: EgeriaTech, element_type: str, txt: str)
332
515
  element_el = element.strip()
333
516
 
334
517
  # Get the element using the generalized function
335
- known_q_name, known_guid, status_msg, el_valid, el_exists = get_element_by_name(
336
- egeria_client, element_type, element_el)
337
- msg += status_msg
518
+ known_q_name, known_guid, el_valid, el_exists = get_element_by_name(egeria_client, element_type, element_el)
519
+ # print_msg("DEBUG-INFO", status_msg, debug_level)
520
+
338
521
  if el_exists and el_valid:
339
- elements = f"{element_el}, {elements}" # list of the input names
522
+ elements = f"{element_el} {elements}" # list of the input names
340
523
  new_element_list.append(known_q_name) # list of qualified names
341
524
  elif not el_exists:
342
- msg += f"* {INFO}No {element_type} `{element_el}` found\n"
525
+ msg = f"No {element_type} `{element_el}` found"
526
+ print_msg("DEBUG-INFO", msg, debug_level)
343
527
  valid = False
344
- valid = valid if el_valid is None else valid and el_valid
528
+ valid = valid if el_valid is None else (valid and el_valid)
345
529
  exists = exists and el_exists
346
530
 
347
531
  if elements:
348
- elements += "\n"
349
- msg += f"* {INFO}Found {element_type}s: {elements}"
532
+ # elements += "\n"
533
+ msg = f"Found {element_type}: {elements}"
534
+ print_msg("DEBUG-INFO", msg, debug_level)
350
535
  else:
351
- msg += f"* {INFO}List contains one or more invalid elements.\n"
352
- return elements, new_element_list, msg, valid, exists
353
-
354
-
536
+ msg = f" Name list contains one or more invalid qualified names."
537
+ print_msg("DEBUG-INFO", msg, debug_level)
538
+ return elements, new_element_list, valid, exists
355
539
 
356
540
 
357
541
  def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
358
- directive: str = "display") -> Optional[str]:
542
+ directive: str = "display") -> Optional[str]:
359
543
  """
360
544
  Processes a blueprint create or update command by extracting key attributes such as
361
545
  blueprint name, description, and version from the given cell.
@@ -372,111 +556,95 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
372
556
  Returns: str
373
557
  A string summarizing the outcome of the processing.
374
558
  """
375
- object_type, object_action = extract_command_plus(txt)
376
- element_display = ""
377
- valid = True
378
- msg =""
559
+ command, object_type, object_action = extract_command_plus(txt)
379
560
 
380
- display_name = extract_attribute(txt, ['Display Name','Blueprint Name'])
381
- description = extract_attribute(txt, ['Description'])
382
- version = extract_attribute(txt, ['Version', "Version Identifier", "Published Version"])
561
+ display_name = process_simple_attribute(txt, ['Display Name', 'Blueprint Name'],ERROR)
562
+ description = process_simple_attribute(txt, ['Description'])
563
+ version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
383
564
 
384
- print(Markdown(f"{pre_command} {object_action} `{object_type}` for Blueprint: `\'{display_name}\'` with directive: `{directive}`\n"))
565
+ print(Markdown(
566
+ f"{pre_command} {object_action} `{object_type}` for Blueprint: `\'{display_name}\'` with directive: `"
567
+ f"{directive}`\n"))
385
568
  if display_name is None:
386
- msg += f"* {ERROR}Display name is missing\n"
387
569
  valid = False
388
570
  q_name, known_guid, exists = None
389
571
  else:
390
- q_name, known_guid, status_msg, valid, exists = process_element_identifiers(egeria_client, object_type,txt, object_action)
391
- msg+= status_msg
392
-
393
- if description is None:
394
- msg += f"* {INFO}Description is missing\n"
395
-
396
- if version is None:
397
- msg += f"* {INFO}Term version is missing\n"
398
-
399
- update_description = extract_attribute(txt, ['Update Description'])
400
- if update_description is None:
401
- msg += f"* {INFO}Update Description is missing\n"
402
- update_description = "---"
572
+ element_labels = BLUEPRINT_NAME_LABELS
573
+ element_labels.append('Display Name')
574
+ q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type, element_labels,
575
+ txt, object_action, version)
403
576
 
404
577
  element_display = (f"\n* Command: {object_action} {object_type}\n\t* Blueprint: {display_name}\n\t"
405
578
  f"* Description: {description}\n\t"
406
579
  f"* Version: {version}\n\t* Qualified Name:{q_name}\n\t* GUID: {known_guid} "
407
- f"\n\t* Update Description: {update_description}\n")
408
-
409
- # if object_action == "Update": # check to see if provided information exists and is consistent with existing info
410
- # if not exists:
411
- # msg += f"* {ERROR}Element {display_name} does not exist\n"
412
- # valid = False
413
-
414
- # elif object_action == 'Create': # if the command is create, check that it doesn't already exist
415
- # if exists:
416
- # msg += f"\n{WARNING}Element \'{display_name}\' already exists.\n"
417
- # elif not valid:
418
- # msg += f"\n-->Validation checks failed in creating element \'{display_name}\' with: {element_display}\n"
419
- # else: # valid to create - update element_dictionary
420
- # msg += f"\n-->It is valid to create element \'{display_name}\' with: {element_display}\n"
421
- # if known_q_name is None:
422
- # known_q_name = egeria_client.__create_qualified_name__(object_type, display_name)
423
- # element_dictionary[known_q_name] = {'display_name': display_name}
424
- if valid:
425
- msg += f"\n-->It is valid to create element \'{display_name}\' with: {element_display}\n"
580
+ # f"\n\t* Update Description: {update_description}\n"
581
+ )
426
582
 
583
+ if valid:
584
+ msg = f"\n-->It is valid to **{object_action}** element \'{display_name}\'\n"
585
+ print_msg("ALWAYS", msg, debug_level)
427
586
  if directive == "display":
428
587
  print(Markdown(element_display))
429
588
  return None
430
589
  elif directive == "validate":
431
- print(Markdown(msg))
432
590
  print(Markdown(element_display))
433
591
  return valid
434
592
 
435
593
  elif directive == "process":
436
- print(Markdown(msg))
594
+ print(Markdown(element_display))
437
595
  try:
438
- if not valid: # First validate the term before we process it
596
+ if not valid: # First validate the element before we process it
597
+ msg = "\nInvalid input found - please review the errors and warnings above\n"
598
+ print_msg("ERROR", msg, debug_level)
439
599
  return None
440
600
 
441
601
  if object_action == "Update" and directive == "process":
442
602
  if not exists:
443
- print(f"\n-->Blueprint {display_name} does not exist")
603
+ msg = f"\n-->Update failed - Blueprint {display_name} does not exist"
604
+ print_msg("ERROR", msg, debug_level)
444
605
  return None
445
606
 
446
607
  # call update blueprint here
447
608
 
448
- print(f"\n-->Updated Blueprint {display_name} with GUID {known_guid}")
609
+ msg = f"\nUpdated Blueprint `{display_name}` with GUID {known_guid}"
610
+ print_msg("ALWAYS", msg, debug_level)
611
+
449
612
  # update with get blueprint by guid
450
- return 'Would return get blueprint by guid and return md' #egeria_client.get_terms_by_guid(known_guid, 'md')
613
+ return 'Would return get blueprint by guid and return md' # egeria_client.get_terms_by_guid(
614
+ # known_guid, 'md')
451
615
 
452
616
  elif object_action == "Update" and directive == "validate":
453
- return 'Would call get_blueprint_by_guid and return md' #egeria_client.get_terms_by_guid(known_guid, 'md')
617
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid(
618
+ # known_guid, 'md')
454
619
 
455
620
  elif object_action == "Create":
456
621
  if exists:
457
- print(f"\n{WARNING}Blueprint {display_name} exists and result document updated")
458
- return update_a_command(txt, f"{object_type}{object_action}",
459
- object_type, q_name, known_guid)
622
+ msg = f"\n{WARNING}Blueprint {display_name} exists and result document updated"
623
+ print_msg("WARNING", msg, debug_level)
624
+ return update_a_command(txt, f"{object_type}{object_action}", object_type, q_name, known_guid)
460
625
  else:
461
- # create the blueprint
462
- #term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
626
+ # create the blueprint
627
+ # term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
463
628
  # if term_guid == NO_ELEMENTS_FOUND:
464
629
  # print(f"{ERROR}Term {term_name} not created")
465
630
  # return None
466
- new_guid= f"guid:{get_current_datetime_string()}"
467
- print(f"\n-->Created Blueprint {display_name} with GUID {new_guid}")
631
+ new_guid = f"guid:{get_current_datetime_string()}"
632
+ msg = f"\nCreated Blueprint `{display_name}`with GUID {new_guid}"
633
+ print_msg("ALWAYS", msg, debug_level)
634
+
468
635
  update_element_dictionary(q_name, {'guid': new_guid, 'display_name': display_name})
469
- return 'Would return get blueprint by guid results as md' #egeria_client.get_terms_by_guid(term_guid, 'MD')
636
+ return 'Would return get blueprint by guid results as md' # egeria_client.get_terms_by_guid(
637
+ # term_guid, 'MD')
470
638
 
471
639
  except Exception as e:
472
- print(f"{ERROR}Error creating term {display_name}: {e}")
640
+ msg = f"{ERROR}Error creating term {display_name}: {e}"
641
+ print_msg("ERROR", msg, debug_level)
473
642
  console.print_exception(show_locals=True)
474
643
  return None
475
644
 
476
645
 
477
-
478
646
  def process_solution_component_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
479
- directive: str = "display") -> Optional[str]:
647
+ directive: str = "display") -> Optional[str]:
480
648
  """
481
649
  Processes a solution componentt create or update command by extracting key attributes such as
482
650
  solution component name, description, version, solution component type etc from the given cell.
@@ -493,56 +661,55 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
493
661
  Returns: str
494
662
  A string summarizing the outcome of the processing.
495
663
  """
496
- object_type, object_action = extract_command_plus(txt)
497
- element_display = ""
498
- bp_exist = True
499
664
  bp_qname_list = []
500
- parent_qname_list = []
665
+ command, object_type, object_action = extract_command_plus(txt)
501
666
 
502
- display_name = extract_attribute(txt, ['Display Name', 'Solution Component Name'])
503
- description = extract_attribute(txt, ['Description'])
504
- version = extract_attribute(txt, ['Version', "Version Identifier", "Published Version"])
505
- solution_component_type = extract_attribute(txt, ['Solution Component Type'])
506
- planned_deployed_implementation_type = extract_attribute(txt, ['Planned Deployment Implementation Type'])
507
- solution_blueprints = extract_attribute(txt, ['Solution Blueprints'])
508
- parent_components = extract_attribute(txt, ['Parent Components'])
667
+ display_name = process_simple_attribute(txt,['Display Name', 'Solution Component Name'] , ERROR)
668
+ description = process_simple_attribute(txt, ['Description'])
669
+ version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
670
+ solution_component_type = process_simple_attribute(txt, ['Solution Component Type'])
671
+ planned_deployed_implementation_type = process_simple_attribute(txt, ['Planned Deployment Implementation Type'])
672
+ solution_blueprints = process_simple_attribute(txt, ['Solution Blueprints'])
673
+ parent_components = process_simple_attribute(txt, ['Parent Components'])
509
674
 
510
675
  print(Markdown(
511
- f"{pre_command} {object_action} `{object_type}` for Solution Component: `\'{display_name}\'` with directive: `{directive}`\n"))
512
-
513
- known_q_name, known_guid, msg, valid, exists = process_element_identifiers(egeria_client, object_type,txt, object_action)
514
-
515
- if description is None:
516
- msg += f"* {INFO}Description is missing\n"
517
-
518
- if version is None:
519
- msg += f"* {INFO}Term version is missing\n"
520
-
521
- update_description = extract_attribute(txt, ['Update Description'])
522
- if update_description is None:
523
- msg += f"* {INFO}Update Description is missing\n"
524
- update_description = "---"
525
-
526
- if solution_component_type is None:
527
- msg += f"* {INFO}Solution Component Type is missing\n"
528
-
529
- if planned_deployed_implementation_type is None:
530
- msg += f"* {INFO}Planned Deployed Implementation Type is missing\n"
531
-
532
- if solution_blueprints is None:
533
- msg += f"* {INFO}No Solution Blueprints found\n"
534
-
535
- else: # Find information about blueprints that include this component
536
- solution_blueprints, bp_qname_list, msg, valid, exists = process_q_name_list(egeria_client,
537
- 'Solution Blueprints', txt)
676
+ f"{pre_command} {object_action} `{object_type}` for Solution Component: `\'{display_name}\'` with directive: "
677
+ f"`{directive}`\n"))
538
678
 
679
+ if display_name is None:
680
+ valid = False
681
+ q_name, known_guid, exists = None
682
+ else:
683
+ element_labels = COMPONENT_NAME_LABELS
684
+ element_labels.append('Display Name')
685
+ known_q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type, element_labels, txt,
686
+ object_action, version)
687
+
688
+ if solution_blueprints: # Find information about blueprints that include this component
689
+ msg = "Checking for blueprints that include this solution component"
690
+ print_msg("DEBUG-INFO", msg, debug_level)
691
+ solution_blueprints, bp_qname_list, bp_valid, bp_exist = process_q_name_list(egeria_client,
692
+ 'Solution Blueprints', txt, BLUEPRINT_NAME_LABELS)
693
+ if bp_exist and bp_valid:
694
+ msg = f"Found valid blueprints that include this solution component:\n\t{solution_blueprints}"
695
+ print_msg("INFO", msg, debug_level)
696
+ else:
697
+ msg = f"No valid blueprints that include this solution component found."
698
+ print_msg("INFO", msg, debug_level)
539
699
  if parent_components is None:
540
- msg += f"* {INFO}Parent Components are missing\n"
700
+ msg = f"Parent Components are missing"
701
+ print_msg("INFO", msg, debug_level)
541
702
  else:
542
- parent_components, parent_qname_list, msg, valid, exists = process_q_name_list(egeria_client,
543
- 'Solution Component', parent_components)
703
+ parent_components, parent_qname_list, parents_valid, parent_components_exist = process_q_name_list(
704
+ egeria_client, 'Parent Components', txt, COMPONENT_NAME_LABELS)
705
+ if parent_components_exist and parents_valid:
706
+ msg = f"Found valid parent components that include this solution component:\n\t{parent_qname_list}"
707
+ print_msg("INFO", msg, debug_level)
708
+ else:
709
+ msg = f"No valid parent components that include this solution component found."
710
+ print_msg("INFO", msg, debug_level)
544
711
 
545
- element_display = (f"\n* Command: {object_action} {object_type}\n\t* Display Name: {display_name}\n\t"
712
+ element_display = (f"* Command: {object_action} {object_type}\n\t* Display Name: {display_name}\n\t"
546
713
  f"* Description: {description}\n\t"
547
714
  f"* Version Identifier: {version}\n\t"
548
715
  f"* Solution Component Type {solution_component_type}\n\t"
@@ -550,77 +717,96 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
550
717
  f"* Solution_Blueprints: {solution_blueprints}\n\t"
551
718
  f"* Parent Components: {parent_components}\n\t"
552
719
  f"* Qualified Name:{known_q_name}\n\t* GUID: {known_guid} "
553
- f"\n\t* Update Description: {update_description}\n")
720
+ # f"\n\t* Update Description: {update_description}"
721
+ )
554
722
 
555
723
  if object_action == "Update": # check to see if provided information exists and is consistent with existing info
556
724
  if not exists:
557
- msg += f"* {ERROR}Element {display_name} does not exist\n"
725
+ msg = f"Element {display_name} does not exist with input:\n"
726
+ print_msg("ERROR", msg, debug_level)
558
727
  valid = False
559
- # element_dictionary[known_q_name] = {'display_name': display_name, 'guid': known_guid}
728
+ elif not valid:
729
+ msg = (f"\n-->Validation checks failed in updating {object_type} \'{display_name}\' with: \n"
730
+ f"{element_display}")
731
+ print_msg("ERROR", msg, debug_level)
732
+ else: # it exists and is valid
733
+ msg = f"\n-->It is valid to update {object_type} \'{display_name}\' with: \n"
734
+ print_msg("ALWAYS", msg, debug_level)
735
+ if known_q_name is None:
736
+ known_q_name = egeria_client.__create_qualified_name__(object_type, display_name,
737
+ version_identifier=version)
738
+ update_element_dictionary(known_q_name, {'display_name': display_name, 'guid': known_guid})
560
739
 
561
740
  elif object_action == 'Create': # if the command is create, check that it doesn't already exist
562
741
  if exists:
563
- msg += f"\n{WARNING}Element \'{display_name}\' already exists.\n"
742
+ msg = f"{object_type} `{display_name}` already exists."
743
+ print_msg("ERROR", msg, debug_level)
744
+ valid = False
564
745
  elif not valid:
565
- msg += f"\n-->Validation checks failed in creating element \'{display_name}\' with: {element_display}\n"
746
+ msg = f"\n-->Validation checks failed in creating element \'{display_name}\' with: \n"
747
+ print_msg("ERROR", msg, debug_level)
566
748
  else: # valid to create - update element_dictionary
567
- msg += f"\n-->It is valid to create element \'{display_name}\' with: {element_display}\n"
749
+ msg = f"\n-->It is valid to create element \'{display_name}\' with: \n"
750
+ print_msg("ALWAYS", msg, debug_level)
568
751
  if known_q_name is None:
569
752
  known_q_name = egeria_client.__create_qualified_name__(object_type, display_name,
570
753
  version_identifier=version)
571
754
  update_element_dictionary(known_q_name, {'display_name': display_name})
572
-
755
+ print(Markdown(element_display))
573
756
  if directive == "display":
574
- print(Markdown(element_display))
575
757
  return None
576
758
  elif directive == "validate":
577
- print(Markdown(msg))
578
- print(Markdown(element_display))
579
759
  return valid
580
760
 
581
761
  elif directive == "process":
582
- print(Markdown(msg))
583
762
  try:
584
763
  if not valid: # First validate the term before we process it
585
764
  return None
586
765
 
587
766
  if object_action == "Update" and directive == "process":
588
767
  if not exists:
589
- print(f"\n-->Solution Component {display_name} does not exist")
768
+ msg = (f"\n-->Solution Component {display_name} does not exist")
769
+ print_msg("ERROR", msg, debug_level)
590
770
  return None
591
771
 
592
772
  # call update solution component here
593
773
 
594
- print(f"\n-->Updated Solution Component {display_name} with GUID {known_guid}")
774
+ msg = f"\nUpdated Solution Component `{display_name}` with GUID {known_guid}"
775
+ print_msg("ALWAYS", msg, debug_level)
595
776
  # update with get solution component by guid
596
- return 'Would return get Solution Component by guid and return md' # egeria_client.get_terms_by_guid(known_guid, 'md')
777
+ return 'Would return get Solution Component by guid and return md' #
778
+ # egeria_client.get_terms_by_guid(known_guid, 'md')
597
779
 
598
780
  elif object_action == "Update" and directive == "validate":
599
- return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid(known_guid, 'md')
781
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid(
782
+ # known_guid, 'md')
600
783
 
601
784
  elif object_action == "Create":
602
785
  if exists:
603
- print(f"\n{WARNING}Blueprint {display_name} exists and result document updated")
604
- return update_a_command(txt, f"{object_type}{object_action}",
605
- object_type, known_q_name, known_guid)
786
+ f"\n{WARNING}Component {display_name} exists and result document updated"
787
+ print_msg("WARNING", msg, debug_level)
788
+ return update_a_command(txt, f"{object_type}{object_action}", object_type, known_q_name, known_guid)
606
789
  else:
607
- # create the blueprint
790
+ # create the solution component
608
791
  # term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
609
792
  # if term_guid == NO_ELEMENTS_FOUND:
610
793
  # print(f"{ERROR}Term {term_name} not created")
611
794
  # return None
612
795
 
613
- print(f"\n-->Created Solution Component {display_name} with GUID {known_guid}")
796
+ msg = f"\nCreated Solution Component `{display_name}` with GUID {known_guid}"
797
+ print_msg("ALWAYS", msg, debug_level)
614
798
  update_element_dictionary(known_q_name, {'guid': known_guid, 'display_name': display_name})
615
- return 'Would return get solution component by guid results as md' # egeria_client.get_terms_by_guid(term_guid, 'MD')
799
+ return 'Would return get solution component by guid results as md' #
800
+ # egeria_client.get_terms_by_guid(term_guid, 'MD')
616
801
 
617
802
  except Exception as e:
618
- print(f"{ERROR}Error creating term {display_name}: {e}")
803
+ msg = f"Error creating term {display_name}: {e}"
804
+ print_msg("ERROR", msg, debug_level)
619
805
  console.print_exception(show_locals=True)
620
806
  return None
621
807
 
622
808
 
623
- def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dictionary: dict, txt: str,
809
+ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
624
810
  directive: str = "display") -> Optional[str]:
625
811
  """
626
812
  Processes a glossary create or update command by extracting key attributes such as
@@ -631,94 +817,80 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
631
817
  :param directive: an optional string indicating the directive to be used - display, validate or execute
632
818
  :return: A string summarizing the outcome of the processing.
633
819
  """
634
- command = extract_command(txt)
635
- object_type = command.split(' ')[1].strip()
636
- object_action = command.split(' ')[0].strip()
637
-
638
- glossary_name = extract_attribute(txt, ['Glossary Name','Display Name'])
639
- print(Markdown(f"{pre_command} `{command}` for glossary: `\'{glossary_name}\'` with directive: `{directive}` "))
640
- language = extract_attribute(txt, ['Language'])
641
- description = extract_attribute(txt, ['Description'])
642
- usage = extract_attribute(txt, ['Usage'])
643
-
644
- glossary_display = (f"\n* Command: {command}\n\t* Glossary Name: {glossary_name}\n\t"
820
+ # command = extract_command(txt)
821
+ # object_type = command.split(' ')[1].strip()
822
+ # object_action = command.split(' ')[0].strip()
823
+ command, object_type, object_action = extract_command_plus(txt)
824
+
825
+ glossary_name = process_simple_attribute(txt, ['Glossary Name', 'Display Name'])
826
+ print(Markdown(f"{pre_command} `{object_action}` `{object_type}` for glossary: `\'{glossary_name}\'` with directive: `{directive}` "))
827
+ language = process_simple_attribute(txt, ['Language'])
828
+ description = process_simple_attribute(txt, ['Description'])
829
+ usage = process_simple_attribute(txt, ['Usage'])
830
+ q_name = process_simple_attribute(txt, ['Qualified Name'])
831
+
832
+ if glossary_name is None:
833
+ valid = False
834
+ known_q_name, known_guid, glossary_exists = None
835
+ else:
836
+ element_labels =GLOSSARY_NAME_LABELS
837
+ element_labels.append('Display Name')
838
+ known_q_name, known_guid, valid, glossary_exists = process_element_identifiers(egeria_client, object_type, element_labels,
839
+ txt, object_action, None)
840
+ glossary_display = (f"\n* Command: `{command}`\n\t* Glossary Name: {glossary_name}\n\t"
645
841
  f"* Language: {language}\n\t* Description:\n{description}\n"
646
- f"* Usage: {usage}\n")
842
+ f"* Usage: {usage}\n"
843
+ )
647
844
 
648
845
  if object_action == 'Update':
649
- q_name = extract_attribute(txt, ['Qualified Name'])
650
- guid = extract_attribute(txt, ['GUID', 'guid', 'Guid'])
651
- glossary_display += f"* Qualified Name: {q_name}\n\t* GUID: {guid}\n\n"
652
-
653
- def validate_glossary(obj_action: str) -> tuple[bool, bool, Optional[str], Optional[str]]:
654
-
655
- valid = True
656
- msg = ""
657
-
658
- known_q_name, known_guid, msg, valid, glossary_exists = process_element_identifiers(egeria_client, object_type,txt, object_action)
659
-
660
- if glossary_name is None:
661
- msg = f"* {ERROR}Glossary name is missing\n"
846
+ guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
847
+ glossary_display += f"* Qualified Name: `{q_name}`\n\t* GUID: {guid}\n\n"
848
+ if not glossary_exists:
849
+ msg = f"Glossary can't be updated; `{glossary_name}` not found"
850
+ print_msg("ERROR", msg, debug_level)
662
851
  valid = False
663
- if language is None:
664
- msg += f"* {ERROR}Language is missing\n"
665
- valid = False
666
- if description is None:
667
- msg += f"* {INFO}Description is missing\n"
668
-
669
- if obj_action == "Update":
670
-
671
- if not glossary_exists:
672
- msg += f"* {ERROR}Glossary {glossary_name} does not exist\n"
673
- valid = False
674
-
675
- if q_name is None:
676
- msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
677
- valid = True
678
- elif q_name != known_q_name:
679
- msg += (
680
- f"* {ERROR}Glossary `{glossary_name}` qualifiedName mismatch between {q_name} and {known_q_name}\n")
681
- valid = False
682
- if valid:
683
- msg += glossary_display
684
- msg += f"* -->Glossary `{glossary_name}` exists and can be updated\n"
685
- update_element_dictionary(known_q_name, {'display_name': glossary_name, 'guid': known_guid})
686
- else:
687
- msg += f"* --> validation failed\n"
688
-
689
- print(Markdown(msg))
690
- return valid, glossary_exists, known_guid, known_q_name
852
+ else:
853
+ msg = f"Glossary can be updated; `{glossary_name}` found"
854
+ print_msg(ALWAYS, msg, debug_level)
691
855
 
692
- elif obj_action == "Create":
693
- if glossary_exists:
694
- msg += f"{ERROR}Glossary {glossary_name} already exists\n"
695
856
 
696
- elif valid:
697
- msg += f"-->It is valid to create Glossary \'{glossary_name}\' with:\n"
698
- msg += glossary_display
699
- expected_q_name = egeria_client.__create_qualified_name__('Glossary', glossary_name)
700
- update_element_dictionary(expected_q_name, {'display_name': glossary_name})
857
+ elif object_action == "Create":
858
+ if glossary_exists:
859
+ msg = f"Glossary `{glossary_name}` can't be created because it already exists.\n"
860
+ print_msg("ERROR", msg, debug_level)
861
+ valid = False
862
+ elif valid:
863
+ msg = f"It is valid to create Glossary `{glossary_name}` with:\n"
864
+ print_msg("ALWAYS", msg, debug_level)
701
865
 
702
- print(Markdown(msg))
703
- return valid, glossary_exists, known_guid, known_q_name
704
866
 
705
867
  if directive == "display":
706
868
  print(Markdown(glossary_display))
707
869
  return None
708
870
 
709
871
  elif directive == "validate":
710
- is_valid, exists, known_guid, known_q_name = validate_glossary(object_action)
711
- valid = is_valid if is_valid else None
872
+ if valid:
873
+ print(Markdown(glossary_display))
874
+ else:
875
+ msg = f"Validation failed for Glossary `{glossary_name}`\n"
876
+ print_msg(ERROR, msg, debug_level)
877
+ print(Markdown(glossary_display))
878
+
712
879
  return valid
713
880
 
714
881
  elif directive == "process":
715
- is_valid, exists, known_guid, known_q_name = validate_glossary(object_action)
716
- if not is_valid:
882
+ if valid:
883
+ print(Markdown(glossary_display))
884
+ else:
885
+ msg = f"Validation failed for Glossary `{glossary_name}`\n"
886
+ print_msg(ERROR, msg, debug_level)
887
+ print(Markdown(glossary_display))
717
888
  return None
889
+
718
890
  if object_action == "Update":
719
- if not exists:
891
+ if not glossary_exists:
720
892
  print(
721
- f"\n{ERROR}Glossary {glossary_name} does not exist! Updating result document with Create command\n")
893
+ f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create command\n")
722
894
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
723
895
 
724
896
  body = {
@@ -728,17 +900,16 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
728
900
  }
729
901
  }
730
902
  egeria_client.update_glossary(known_guid, body)
731
- print(f"\n-->Updated Glossary {glossary_name} with GUID {known_guid}")
903
+ print_msg(ALWAYS, f"Updated Glossary `{glossary_name}` with GUID {known_guid}", debug_level)
732
904
  update_element_dictionary(known_q_name, {
733
905
  'guid': known_guid, 'display_name': glossary_name
734
906
  })
735
- # return update_a_command(txt, command, object_type, known_q_name, known_guid)
736
907
  return egeria_client.get_glossary_by_guid(known_guid, output_format='MD')
737
908
  elif object_action == "Create":
738
909
  glossary_guid = None
739
910
 
740
- if exists:
741
- print(f"\nGlossary {glossary_name} already exists and result document updated\n")
911
+ if glossary_exists:
912
+ print(f"\nGlossary `{glossary_name}` already exists and result document updated\n")
742
913
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
743
914
  else:
744
915
  glossary_guid = egeria_client.create_glossary(glossary_name, description, language, usage)
@@ -751,10 +922,11 @@ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dict
751
922
  'guid': glossary_guid, 'display_name': glossary_name
752
923
  })
753
924
  # return update_a_command(txt, command, object_type, qualified_name, glossary_guid)
754
- return egeria_client.get_glossary_by_guid(glossary_guid, output_format = 'MD')
925
+ print_msg(ALWAYS, f"Created Glossary `{glossary_name}` with GUID {glossary_guid}", debug_level)
926
+ return egeria_client.get_glossary_by_guid(glossary_guid, output_format='MD')
755
927
 
756
928
 
757
- def process_categories_upsert_command(egeria_client: GlossaryManager, element_dictionary: dict, txt: str,
929
+ def process_categories_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
758
930
  directive: str = "display") -> Optional[str]:
759
931
  """
760
932
  Processes a glossary category create or update command by extracting key attributes such as
@@ -765,168 +937,131 @@ def process_categories_upsert_command(egeria_client: GlossaryManager, element_di
765
937
  :param directive: an optional string indicating the directive to be used - display, validate or execute
766
938
  :return: A string summarizing the outcome of the processing.
767
939
  """
768
- command = extract_command(txt)
769
- object_type = command.split(' ')[1].strip()
770
- object_action = command.split(' ')[0].strip()
940
+ valid = True
771
941
 
772
- category_name = extract_attribute(txt, ['Category Name', 'category_name', 'Cat'])
942
+ # command = extract_command(txt)
943
+ # object_type = command.split(' ')[1].strip()
944
+ # object_action = command.split(' ')[0].strip()
945
+ command, object_type, object_action = extract_command_plus(txt)
946
+
947
+ category_name = process_simple_attribute(txt, ['Category Name', 'category_name', 'Cat'])
773
948
  print(Markdown(f"{pre_command} `{command}` for category: `\'{category_name}\'` with directive: `{directive}` "))
774
- owning_glossary_qn = extract_attribute(txt, ['Owning Glossary', '[In Glossary'])
775
- description = extract_attribute(txt, ['Description'])
776
- q_name = extract_attribute(txt, ['Qualified Name'])
777
949
 
778
- category_display = (f"\n* Command: {command}\n\t* Category: {category_name}\n\t* In Glossary: {owning_glossary_qn}\n\t"
779
- f"* Description:\n{description}\n\t* Qualified Name: {q_name}\n\t")
780
- update_description = None
950
+ owning_glossary_name = extract_attribute(txt, ['Owning Glossary', 'In Glossary'])
951
+ description = process_simple_attribute(txt, ['Description'])
952
+ q_name = process_simple_attribute(txt, ['Qualified Name'])
781
953
 
782
- if object_action == 'Update':
783
- guid = extract_attribute(txt, ['GUID','guid','Guid'])
784
- update_description = extract_attribute(txt, 'Update Description')
785
- category_display += (f"* GUID: {guid}\n\n"
786
- f"* Update Description: \n {update_description}\n\t")
787
-
788
- def validate_category(obj_action: str) -> tuple[bool, bool, Optional[str], Optional[str], Optional[str]]:
789
- valid = True
790
- msg = ""
791
- known_category_guid = None
792
- known_q_name = None
793
- glossary_guid = None
954
+ element_labels = CATEGORY_NAME_LABELS
955
+ element_labels.append('Display Name')
956
+ # Check if category exists (and get qname and guid)
957
+ if category_name is None:
958
+ valid = False
959
+ known_q_name, known_guid, category_exists = None
960
+ else:
961
+ element_labels = CATEGORY_NAME_LABELS
962
+ element_labels.append('Display Name')
963
+ known_q_name, known_guid, valid, category_exists = process_element_identifiers(egeria_client, object_type, element_labels,
964
+ txt, object_action, None)
794
965
 
795
- category_details = egeria_client.get_categories_by_name(category_name)
796
- if category_details == NO_CATEGORIES_FOUND:
797
- category_exists = False
798
- else:
799
- category_exists = True
800
966
 
801
- if owning_glossary_qn is None:
802
- msg += f"* {ERROR}Owning Glossary Qualified Name is missing\n"
803
- valid = False
967
+ # Check if owning glossary exists (and get qname)
968
+ if owning_glossary_name is None:
969
+ valid = False
970
+ known_glossary_q_name, known_glossary__guid, glossary_exists = None
971
+ else:
972
+ known_glossary_q_name, known_glossary_guid, valid, owning_glossary_exists = process_element_identifiers(egeria_client,
973
+ "Glossary",
974
+ GLOSSARY_NAME_LABELS, txt,
975
+ "Exists Required", None)
804
976
 
805
- elif owning_glossary_qn in get_element_dictionary(): # Check to see if we already know about this glossary
806
- element_dict = get_element_dictionary()
807
- glossary_name = element_dict[owning_glossary_qn].get('display_name', None)
808
- glossary_guid = element_dict[owning_glossary_qn].get('guid', None)
977
+ category_display = (
978
+ f"\n* Command: {command}\n\t* Category: {category_name}\n\t* In Glossary: {owning_glossary_name}\n\t"
979
+ f"* Description:\n{description}\n\t* Qualified Name: {q_name}\n\t")
809
980
 
810
- else:
811
- # need to ask Egeria if it knows the Glossary Name
812
- glossary = egeria_client.get_glossaries_by_name(owning_glossary_qn)
813
- if glossary == NO_GLOSSARIES_FOUND:
814
- msg += f"* {ERROR}Glossary `{owning_glossary_qn}` does not exist\n\n"
815
- valid = False
816
- else:
817
- msg += f"* {INFO}Glossary `{owning_glossary_qn}` exists\n\n"
818
- glossary_guid = glossary[0]['elementHeader'].get('guid', None)
819
- glossary_name = glossary[0]['glossaryProperties'].get('displayName', None)
820
- glossary_qn = glossary[0]['glossaryProperties'].get('qualifiedName', None)
821
- if glossary_qn != owning_glossary_qn: # we were given the right qualified name - maybe a display_name
822
- msg += f"* {ERROR}Glossary `{owning_glossary_qn}` is known by qualifiedName `{glossary_qn}`\n\n"
823
- valid = False
824
- else:
825
- update_element_dictionary(owning_glossary_qn, {
826
- 'guid': glossary_guid, 'display_name': glossary_name
827
- })
828
981
 
829
- if category_name is None:
830
- msg = f"* {ERROR}Category name is missing\n"
982
+ if object_action == 'Update':
983
+ guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
984
+ # update_description = process_simple_attribute(txt, 'Update Description')
985
+ category_display += (f"* GUID: {guid}\n\n")
986
+ if not category_exists:
987
+ msg = f"Category {category_name} can't be updated; {category_name} not found."
988
+ print_msg(ERROR, msg, debug_level)
831
989
  valid = False
990
+ else:
991
+ msg = f"Glossary can be updated; {category_name} found"
992
+ print_msg(ALWAYS, msg, debug_level)
832
993
 
833
- if description is None:
834
- msg += f"* {INFO}Description is missing\n"
835
-
836
- if len(category_details) > 1 and category_exists:
837
- msg += f"* {ERROR}More than one category with name `{category_name}` found\n"
994
+ elif object_action == "Create":
995
+ if category_exists:
996
+ msg = f"Category {category_name} can't be created because it already exists.\n"
997
+ print_msg("ERROR", msg, debug_level)
838
998
  valid = False
839
- if len(category_details) == 1:
840
- known_category_guid = category_details[0]['elementHeader'].get('guid', None)
841
- known_q_name = category_details[0]['glossaryCategoryProperties'].get('qualifiedName', None)
842
-
843
- if obj_action == "Update":
844
- if not category_exists:
845
- msg += f"* {ERROR}category `{category_name}` does not exist\n"
846
- valid = False
847
- if q_name is None:
848
- msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
849
- valid = True
850
- elif q_name != known_q_name:
851
- msg += (
852
- f"* {ERROR}category `{category_name}` qualifiedName mismatch between {q_name} and {known_q_name}\n")
853
- valid = False
854
- if valid:
855
- msg += category_display
856
- msg += f"* -->category `{category_name}` exists and can be updated\n"
857
- update_element_dictionary(known_q_name, {'display_name': glossary_name, 'guid': known_category_guid})
858
- else:
859
- msg += f"* --> validation failed\n"
860
-
861
- print(Markdown(msg))
862
- return valid, category_exists, known_category_guid, known_q_name, glossary_guid
863
-
864
- elif obj_action == "Create":
865
- if category_exists:
866
- msg += f"{ERROR}category `{category_name}` already exists\n"
867
-
868
- elif valid:
869
- msg += f"-->It is valid to create category `{category_name}` with:\n"
870
- msg += category_display
871
- expected_q_name = egeria_client.__create_qualified_name__('Category', category_name)
872
- update_element_dictionary(expected_q_name, {'display_name': category_name})
873
-
874
- print(Markdown(msg))
875
- return valid, category_exists, known_category_guid, known_q_name, glossary_guid
999
+ elif valid:
1000
+ msg = f"It is valid to create Category `{category_name}` with:\n"
1001
+ print_msg("ALWAYS", msg, debug_level)
876
1002
 
877
1003
  if directive == "display":
878
1004
  print(Markdown(category_display))
879
1005
  return None
880
1006
 
881
1007
  elif directive == "validate":
882
- is_valid, exists, known_guid, known_q_name, glossary_guid = validate_category(object_action)
883
- valid = is_valid if is_valid else None
1008
+ if valid:
1009
+ print(Markdown(category_display))
1010
+ else:
1011
+ msg = f"Validation failed for {object_type} `{category_name}`\n"
1012
+ print_msg(ERROR, msg, debug_level)
1013
+ print(Markdown(category_display))
884
1014
  return valid
885
1015
 
886
1016
  elif directive == "process":
887
- is_valid, exists, known_guid, known_q_name, glossary_guid = validate_category(object_action)
888
- if not is_valid:
889
- print(f"{ERROR}Validation checks failed in creating category `{category_name}`")
1017
+ if valid:
1018
+ print(Markdown(category_display))
1019
+ else:
1020
+ msg = f"* --> Validation failed for {object_type} `{category_name}`\n"
1021
+ print_msg(ERROR, msg, debug_level)
1022
+ print(Markdown(category_display))
890
1023
  return None
891
1024
 
892
1025
  if object_action == "Update":
893
- if not exists:
894
- print(
895
- f"\n{ERROR}category `{category_name}` does not exist! Updating result document with Create "
896
- f"command\n")
1026
+ if not category_exists:
1027
+ print(f"\n{ERROR}category `{category_name}` does not exist! Updating result document with Create "
1028
+ f"command\n")
897
1029
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
898
1030
 
899
- egeria_client.update_category(glossary_guid, category_name, description, known_q_name, None,
900
- update_description)
901
- print(f"\n-->Updated category `{category_name}`with GUID {known_guid}")
1031
+ egeria_client.update_category(known_guid, category_name, description, known_q_name, None)
1032
+ msg = f"->Updated category `{category_name}`with GUID {known_guid}"
1033
+ print_msg(ALWAYS, msg, debug_level)
902
1034
  update_element_dictionary(known_q_name, {
903
1035
  'guid': known_guid, 'display_name': category_name
904
1036
  })
905
- # return update_a_command(txt, command, object_type, known_q_name, known_guid)
1037
+ print_msg(ALWAYS, f"Updated Category `{category_name}` with GUID {known_guid}", debug_level)
906
1038
  return egeria_client.get_categories_by_guid(known_guid, output_format='FORM')
907
1039
 
908
1040
  elif object_action == "Create":
909
- is_root = False
1041
+ is_root = True
910
1042
 
911
- if exists:
912
- print(f"\ncategory `{category_name}` already exists and result document updated\n")
1043
+ if category_exists:
1044
+ msg = f"Cannot create`{category_name}` because it already exists; result document written for category update\n"
1045
+ print_msg(WARNING, msg, debug_level)
913
1046
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
914
1047
  else:
915
- category_guid = egeria_client.create_category(glossary_guid, category_name, description, is_root)
916
- category = egeria_client.get_categories_by_guid(category_guid)
1048
+ category_guid = egeria_client.create_category(known_glossary_guid, category_name, description, is_root)
1049
+ category_details = egeria_client.get_categories_by_guid(category_guid)
917
1050
 
918
- if category == NO_CATEGORIES_FOUND:
919
- print(f"{ERROR}Just created with GUID {category_guid} but category not found\n")
1051
+ if category_details == NO_CATEGORIES_FOUND:
1052
+ msg = f"Just created category with GUID {category_guid} but category not found"
1053
+ print_msg(ERROR, msg, debug_level)
920
1054
  return None
921
- qualified_name = category['glossaryCategoryProperties']["qualifiedName"]
1055
+
1056
+ qualified_name = category_details['glossaryCategoryProperties']["qualifiedName"]
922
1057
  update_element_dictionary(qualified_name, {
923
1058
  'guid': category_guid, 'display_name': category_name
924
1059
  })
925
- # return update_a_command(txt, command, object_type, qualified_name, category_guid)
1060
+ print_msg(ALWAYS, f"Created Category `{category_name}` with GUID {category_guid}", debug_level)
926
1061
  return egeria_client.get_categories_by_guid(category_guid, output_format='MD')
927
1062
 
928
1063
 
929
- def process_term_upsert_command(egeria_client: GlossaryManager, element_dictionary: dict, txt: str,
1064
+ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
930
1065
  directive: str = "display") -> Optional[str]:
931
1066
  """
932
1067
  Processes a term create or update command by extracting key attributes such as
@@ -937,276 +1072,154 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
937
1072
  :param directive: an optional string indicating the directive to be used - display, validate or execute
938
1073
  :return: A string summarizing the outcome of the processing.
939
1074
  """
1075
+ valid = True
1076
+ categories_list = None
1077
+ cats_exist = True
940
1078
 
1079
+ known_q_name = None
941
1080
  command = extract_command(txt)
942
1081
  object_type = command.split(' ')[1].strip()
943
1082
  object_action = command.split(' ')[0].strip()
944
1083
 
945
- term_name = extract_attribute(txt, ['Term Name','Display Name'])
946
- summary = extract_attribute(txt, ['Summary'])
947
- description = extract_attribute(txt, ['Description'])
948
- abbreviation = extract_attribute(txt, ['Abbreviation'])
949
- examples = extract_attribute(txt, ['Examples'])
950
- usage = extract_attribute(txt, ['Usage'])
951
- status = extract_attribute(txt, ['Status'])
952
- version = extract_attribute(txt, ['Version', "Version Identifier", "Published Version"])
953
- categories = extract_attribute(txt, ['Categories'])
954
- q_name = extract_attribute(txt, ['Qualified Name'])
955
- # q_name = q_name if q_name else " "
956
-
957
- categories_list = None
958
- cats_exist = True
959
-
960
- glossary_qn = extract_attribute(txt, ['In Glossary','Owning Glossary'])
961
-
962
- print(Markdown(f"{pre_command} `{command}` for term: `\'{term_name}\'` with directive: `{directive}`"))
963
-
964
- def validate_term(obj_action: str) -> tuple[bool, bool, Optional[str], Optional[str]]:
965
- nonlocal version, status, categories, categories_list, cats_exist, q_name, glossary_qn
966
- valid = True
967
- msg = ""
968
- known_term_guid = None
969
- known_q_name = None
970
-
971
- # If the user has specified a qualified_name then use it to look for matching terms.
972
- # If not, use the display_name.
973
- if q_name:
974
- term_details = egeria_client.get_terms_by_name(q_name)
975
- else:
976
- term_details = egeria_client.get_terms_by_name(term_name)
977
-
978
- if term_details == NO_TERMS_FOUND:
979
- term_exists = False
980
- else:
981
- term_exists = True
982
-
983
- if status is None:
984
- msg += f"* {INFO}Term status is missing - will default to DRAFT\n"
985
- status = 'DRAFT'
986
-
987
-
988
- if term_name is None:
989
- msg = f"* {ERROR}Term name is missing\n"
990
- valid = False
991
- if glossary_qn is None:
992
- msg += f"* {ERROR}Glossary qualified name is missing\n"
993
- valid = False
994
- else:
995
- print(f"* {INFO}Glossary qualified name is `{glossary_qn}`")
996
- element_dict = get_element_dictionary()
997
- if glossary_qn not in element_dict:
998
- glossary = egeria_client.get_glossaries_by_name(glossary_qn) #assuming q_name?
999
- if isinstance(glossary,str):
1000
- msg += f"* {ERROR}Glossary `{glossary_qn}` is unknown\n "
1001
- valid = False
1002
- elif len(glossary) != 1:
1003
- msg += f"* {ERROR}Glossary `{glossary_qn}` is ambiguous or not found\n "
1004
- valid = False
1005
- else:
1006
- glossary_qn = glossary[0]['glossaryProperties'].get('qualifiedName', None)
1007
- if glossary_qn is None:
1008
- msg += f"* {ERROR}Glossary `{glossary_qn}` has no qualifiedName\n "
1009
- valid = False
1010
- else:
1011
- update_element_dictionary(glossary_qn, {
1012
- 'guid': glossary[0]['elementHeader'].get('guid', None),
1013
- 'display_name': glossary[0]['glossaryProperties'].get('displayName', None)
1014
- })
1084
+ term_name = process_simple_attribute(txt, ['Term Name', 'Display Name'], ERROR)
1085
+ print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
1086
+ summary = process_simple_attribute(txt, ['Summary'])
1087
+ description = process_simple_attribute(txt, ['Description'])
1088
+ abbreviation = process_simple_attribute(txt, ['Abbreviation'])
1089
+ examples = process_simple_attribute(txt, ['Examples'])
1090
+ usage = process_simple_attribute(txt, ['Usage'])
1091
+ status = process_simple_attribute(txt, ['Status'])
1092
+ status = status.upper() if status else 'DRAFT'
1093
+ version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
1094
+ q_name = process_simple_attribute(txt, ['Qualified Name'])
1095
+
1096
+ # validate term name and get existing qualified_name and guid if they exist
1097
+ if term_name is None:
1098
+ valid = False
1099
+ known_q_name, known_guid, term_exists = None
1100
+ else:
1101
+ element_labels = TERM_NAME_LABELS
1102
+ element_labels.append('Display Name')
1103
+ known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type, element_labels,
1104
+ txt, object_action, version)
1015
1105
 
1016
1106
 
1017
- if categories is None:
1018
- msg += f"* {INFO} No categories found\n"
1107
+ # get the glossary qualified name this term is in
1108
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
1109
+ if glossary_name is None:
1110
+ valid = False
1111
+ known_glossary_guid = None
1112
+ known_glossary_q_name = None
1113
+ glossary_valid = False
1114
+ glossary_exists = False
1115
+ else:
1116
+ known_glossary_q_name, known_glossary_guid, glossary_valid, glossary_exists = process_element_identifiers(
1117
+ egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, "Exists Required", None)
1118
+
1119
+ # process categories, if present
1120
+ categories = process_simple_attribute(txt, ['Glossary Categories', 'Glossary Category', 'Category', 'Categories'])
1121
+ if categories: # Find information about categoriess that classify this term
1122
+ msg = "Checking for categories that classify this term"
1123
+ print_msg("DEBUG-INFO", msg, debug_level)
1124
+ categories_list, cat_q_name_list, cat_valid, cat_exist = process_q_name_list(egeria_client,
1125
+ 'Glossary Categories', txt, CATEGORY_NAME_LABELS)
1126
+ if cat_exist and cat_valid:
1127
+ msg = f"Found valid glossary categories to classify the term:\n\t{term_name}"
1128
+ print_msg("INFO", msg, debug_level)
1019
1129
  else:
1020
- categories_list = re.split(r'[,\n]+', categories)
1021
- categories = ""
1022
- new_cat_list = []
1023
- for category in categories_list:
1024
- category_el = category.strip()
1025
- element_dict = get_element_dictionary()
1026
- if category_el not in element_dict:
1027
- cat = egeria_client.get_categories_by_name(category_el) # assuming qualified name?
1028
- if isinstance(cat,str):
1029
- msg += (f"* {WARNING}Category `{category_el}` not found -> "
1030
- f"categories for this term won't be processed!\n")
1031
- cats_exist = False
1032
- break
1033
- cat_qname = cat[0]['glossaryCategoryProperties'].get('qualifiedName', None)
1034
- category = cat_qname # use the qualified name if found
1035
- if cat_qname not in element_dict:
1036
- cat_guid = cat[0]['elementHeader']['guid']
1037
- cat_display_name = cat[0]['glossaryCategoryProperties'].get('displayName', None)
1038
- update_element_dictionary(cat_qname, {
1039
- 'guid' : cat_guid,
1040
- 'displayName': cat_display_name
1041
- })
1042
- categories = f"{category}, {categories}"
1043
- new_cat_list.append(category)
1044
- if cats_exist:
1045
- categories +='\n'
1046
- categories_list = new_cat_list
1047
- else:
1048
- categories = None
1049
-
1050
-
1051
- if summary is None:
1052
- msg += f"* {INFO}Term summary is missing\n"
1053
-
1054
- if description is None:
1055
- msg += f"* {INFO}Term description is missing\n"
1056
-
1057
- if abbreviation is None:
1058
- msg += f"* {INFO}Term abbreviation is missing\n"
1059
- if examples is None:
1060
- msg += f"* {INFO}Term examples is missing\n"
1061
- if usage is None:
1062
- msg += f"* {INFO}Term usage is missing\n"
1063
- if version is None:
1064
- msg += f"* {INFO}Term version is missing\n"
1065
- # version = "0.0.1"
1066
-
1067
-
1068
- if obj_action == "Update": # check to see if provided information exists and is consistent with existing info
1069
- if not term_exists:
1070
- msg += f"* {ERROR}Term {term_name} does not exist\n"
1071
- valid = False
1072
-
1073
- if len(term_details) > 1 and term_exists:
1074
- msg += (f"* {ERROR}More than one term with name {term_name} found, please specify a "
1075
- f"**Qualified Name**\n")
1076
- valid = False
1077
- elif len(term_details) == 1:
1078
- known_term_guid = term_details[0]['elementHeader'].get('guid', None)
1079
- known_q_name = term_details[0]['glossaryTermProperties'].get('qualifiedName', None)
1080
- if q_name != known_q_name:
1081
- msg += (f"* {ERROR}Term {term_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
1082
- valid = False
1083
- else:
1084
- msg += f"\n--> * Term {term_name} exists and can be updated\n"
1085
- msg += term_display
1086
- update_element_dictionary(known_q_name, {'display_name': term_name, 'guid': known_term_guid})
1087
-
1088
- print(Markdown(msg))
1089
- return valid, term_exists, known_term_guid, known_q_name
1090
-
1091
- elif obj_action == 'Create': # if the command is create, check that it doesn't already exist
1092
- if term_exists:
1093
- msg += f"\n{WARNING}Term \'{term_name}\' already exists.\n"
1094
- elif not valid:
1095
- msg += f"\n-->Validation checks failed in creating Term \'{term_name}\' with: {term_display}\n"
1096
- else:
1097
- msg += f"\n-->It is valid to create Term \'{term_name}\' with: {term_display}\n"
1098
- if q_name is None:
1099
- expected_q_name = egeria_client.__create_qualified_name__('Term',
1100
- term_name, version_identifier=version)
1101
- update_element_dictionary(expected_q_name, {'display_name': term_name})
1102
- else:
1103
- update_element_dictionary(q_name, {'display_name': term_name})
1104
- print(Markdown(msg))
1105
- return valid, term_exists, known_term_guid, known_q_name
1130
+ msg = "No valid glossary categories found."
1131
+ print_msg("INFO", msg, debug_level)
1132
+ else:
1133
+ cat_exist = cat_valid = False
1134
+ cat_q_name_list = None
1106
1135
 
1107
- # Continue processing the upsert
1108
- if object_action == "Update":
1109
- term_guid = extract_attribute(txt, 'GUID')
1110
- term_guid = term_guid if term_guid else None
1111
1136
 
1112
1137
 
1113
- update_description = extract_attribute(txt, 'Update Description')
1114
- update_description = update_description if update_description else " "
1115
- term_display = (f"\n* Command: {command}\n\t* Glossary: {glossary_qn}\n\t"
1138
+ if object_action == "Update": # check to see if provided information exists and is consistent with existing info
1139
+ term_guid = process_simple_attribute(txt, GUID_LABELS)
1140
+ update_description = process_simple_attribute(txt, ['Update Description'])
1141
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
1116
1142
  f"* Term Name: {term_name}\n\t* Qualified Name: {q_name}\n\t* Categories: {categories}\n\t"
1117
1143
  f"* Summary: {summary}\n\t* Description: {description}\n\t"
1118
1144
  f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
1119
- f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}\n\t* Qualified Name: "
1120
- f"{q_name}"
1145
+ f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}"
1121
1146
  f"\n\t* Update Description: {update_description}\n")
1122
- else:
1123
- term_display = (f"\n* Command: {command}\n\t* Glossary: {glossary_qn}\n\t"
1147
+ if not term_exists:
1148
+ msg = f"Update request invalid, Term {term_name} does not exist\n"
1149
+ print_msg(ERROR,msg, debug_level)
1150
+ valid = False
1151
+
1152
+ elif object_action == 'Create': # if the command is create, check that it doesn't already exist
1153
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
1124
1154
  f"* Term Name: {term_name}\n\t* Categories: {categories}\n\t* Summary: {summary}\n\t"
1125
1155
  f"* Qualified Name: {q_name}\n\t* Description: {description}\n\t"
1126
1156
  f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
1127
1157
  f"* Version: {version}\n\t* Status: {status}\n")
1158
+ if term_exists:
1159
+ msg = f"Term `{term_name}` cannot be created since it already exists\n"
1160
+ print_msg(ERROR, msg, debug_level)
1161
+ else:
1162
+ msg = f"It is valid to create Term `{term_name}`"
1163
+ print_msg(ALWAYS,msg, debug_level)
1164
+
1128
1165
 
1129
1166
  if directive == "display":
1130
1167
  print(Markdown(term_display))
1131
1168
  return None
1132
1169
  elif directive == "validate":
1133
- is_valid, exists, known_guid, known_q_name = validate_term(object_action)
1134
- valid = is_valid if is_valid else None
1170
+ print(Markdown(term_display))
1135
1171
  return valid
1136
1172
  elif directive == "process":
1137
1173
  try:
1138
- is_valid, exists, known_guid, known_q_name = validate_term(object_action)
1139
- if not is_valid: # First validate the term before we process it
1174
+ if not valid: # First validate the term before we process it
1140
1175
  return None
1141
1176
 
1142
1177
  if object_action == "Update" and directive == "process":
1143
- if not exists:
1144
- print(f"\n-->Term {term_name} does not exist")
1178
+ if not term_exists:
1145
1179
  return None
1146
1180
  body = {
1147
- "class": "ReferenceableRequestBody",
1148
- "elementProperties": {
1149
- "class": "GlossaryTermProperties",
1150
- "qualifiedName": known_q_name,
1151
- "summary": summary,
1152
- "description": description,
1153
- "abbreviation": abbreviation,
1154
- "examples": examples,
1155
- "usage": usage,
1156
- "publishVersionIdentifier": version,
1157
- "status": status
1158
- },
1159
- "updateDescription": update_description
1181
+ "class": "ReferenceableRequestBody", "elementProperties": {
1182
+ "class": "GlossaryTermProperties", "qualifiedName": known_q_name, "summary": summary,
1183
+ "description": description, "abbreviation": abbreviation, "examples": examples, "usage": usage,
1184
+ "publishVersionIdentifier": version, "status": status
1185
+ }, "updateDescription": update_description
1160
1186
  }
1161
1187
  egeria_client.update_term(known_guid, body_slimmer(body))
1162
- # if cats_exist is True and categories_list is not None:
1163
- # for category in categories_list:
1164
- # cat_guid = element_dictionary.get(f"category.{category}", None)
1165
- # if cat_guid is None:
1166
- # cat_guid = egeria_client.__get_guid__(display_name=category)
1167
- # egeria_client.add_term_to_category(known_guid, cat_guid)
1168
- add_term_to_categories(
1169
- egeria_client, known_guid, cats_exist , categories_list,
1170
- element_dictionary)
1171
- print(f"\n-->Updated Term {term_name} with GUID {known_guid} and categories {categories_list}")
1172
- return egeria_client.get_terms_by_guid(known_guid, 'md')
1173
- # return update_a_command(txt, command, object_type, known_q_name, known_guid)
1174
- elif object_action == "Update" and directive == "validate":
1188
+ if cat_exist and cat_valid:
1189
+ add_term_to_categories(egeria_client, known_guid, cats_exist, cat_q_name_list)
1190
+ print_msg(ALWAYS, f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`", debug_level)
1191
+ return egeria_client.get_terms_by_guid(known_guid,
1192
+ 'md') # return update_a_command(txt, command, object_type,
1193
+ # known_q_name, known_guid)
1194
+ elif object_action == "Update" and directive == "validate": # is sthis reachable?
1175
1195
  return egeria_client.get_terms_by_guid(known_guid, 'md')
1176
1196
 
1177
1197
  elif object_action == "Create":
1178
- guid = None
1179
- if q_name is None:
1180
- q_name = egeria_client.__create_qualified_name__("Term",term_name,
1181
- version_identifier=version)
1182
- if exists:
1183
- print(f"\n{WARNING}Term {term_name} exists and result document updated")
1198
+ if term_exists:
1199
+ msg = f"Term {term_name} exists so result document modifies term create to term update"
1200
+ print_msg(INFO, msg, debug_level)
1184
1201
  return update_a_command(txt, command, object_type, q_name, known_guid)
1185
1202
  else:
1186
- ## get the guid for the glossary from the name - first look locally
1187
- glossary = get_element_dictionary().get(glossary_qn, None)
1203
+ ## get the guid for the glossary from the name - first look in cache
1204
+ cached = get_element_dictionary().get(known_glossary_q_name, None)
1188
1205
 
1189
- if glossary is not None:
1190
- glossary_guid = glossary.get('guid', None)
1206
+ if cached is not None:
1207
+ glossary_guid = cached.get('guid', None)
1191
1208
  if glossary_guid is None:
1192
- print(f"{ERROR}Glossary reference {glossary_qn} not found")
1209
+ msg = f"Glossary GUID for {known_glossary_q_name} not found in cache"
1210
+ print_msg(WARNING, msg, debug_level) # should this ever occur?
1193
1211
  return None
1194
1212
  else:
1195
- glossary_guid = egeria_client.__get_guid__(qualified_name=glossary_qn)
1213
+ glossary_guid = egeria_client.__get_guid__(qualified_name=known_glossary_q_name)
1196
1214
  if glossary_guid == NO_ELEMENTS_FOUND:
1197
- print(f"{ERROR}Glossary {glossary_qn} not found")
1215
+ msg = f"Glossary {known_glossary_q_name} not found"
1216
+ print_msg(WARNING, msg, debug_level)
1198
1217
  return None
1199
1218
  term_body = {
1200
1219
  "class": "ReferenceableRequestBody", "elementProperties": {
1201
- "class": "GlossaryTermProperties",
1202
- "qualifiedName": q_name,
1203
- "displayName": term_name,
1204
- "summary": summary,
1205
- "description": description,
1206
- "abbreviation": abbreviation,
1207
- "examples": examples,
1208
- "usage": usage,
1209
- "publishVersionIdentifier": version
1220
+ "class": "GlossaryTermProperties", "qualifiedName": known_q_name, "displayName": term_name,
1221
+ "summary": summary, "description": description, "abbreviation": abbreviation,
1222
+ "examples": examples, "usage": usage, "publishVersionIdentifier": version
1210
1223
  # "additionalProperties":
1211
1224
  # {
1212
1225
  # "propertyName1": "xxxx",
@@ -1214,23 +1227,23 @@ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictiona
1214
1227
  # }
1215
1228
  }, "initialStatus": status
1216
1229
  }
1217
- term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
1230
+ term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, body_slimmer(term_body))
1218
1231
  if term_guid == NO_ELEMENTS_FOUND:
1219
1232
  print(f"{ERROR}Term {term_name} not created")
1220
1233
  return None
1221
1234
  if cats_exist and categories is not None:
1222
- add_term_to_categories(
1223
- egeria_client, term_guid, cats_exist, categories_list,
1224
- element_dictionary)
1225
- print(f"\n-->Created Term {term_name} with GUID {term_guid}")
1226
- update_element_dictionary(q_name, {'guid': term_guid, 'display_name': term_name})
1227
- return egeria_client.get_terms_by_guid(term_guid, 'MD')
1228
- # return update_a_command(txt, command, object_type, q_name, term_guid)
1235
+ add_term_to_categories(egeria_client, term_guid, cats_exist, cat_q_name_list)
1236
+ update_element_dictionary(known_q_name, {'guid': term_guid, 'display_name': term_name})
1237
+ print_msg(ALWAYS, f"Created term `{term_name}` with GUID {term_guid}", debug_level)
1238
+ return egeria_client.get_terms_by_guid(term_guid,
1239
+ 'MD') # return update_a_command(txt, command,
1240
+ # object_type, q_name, term_guid)
1229
1241
  except Exception as e:
1230
1242
  print(f"{ERROR}Error creating term {term_name}: {e}")
1231
1243
  console.print_exception(show_locals=True)
1232
1244
  return None
1233
1245
 
1246
+
1234
1247
  def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dictionary: dict, txt: str,
1235
1248
  directive: str = "display") -> str | None:
1236
1249
  """
@@ -1247,14 +1260,14 @@ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dicti
1247
1260
  object_type = f"{object[1]} {object[2]}"
1248
1261
  object_action = object[0]
1249
1262
 
1250
- project_name = extract_attribute(txt, ['Project Name'])
1251
- description = extract_attribute(txt, ['Description'])
1252
- project_identifier = extract_attribute(txt, ['Project Identifier'])
1253
- project_status = extract_attribute(txt, ['Project Status'])
1254
- project_phase = extract_attribute(txt, ['Project Phase'])
1255
- project_health = extract_attribute(txt, ['Project Health'])
1256
- start_date = extract_attribute(txt, ['Start Date'])
1257
- planned_end_date = extract_attribute(txt, ['Planned End Date'])
1263
+ project_name = process_simple_attribute(txt, ['Project Name'])
1264
+ description = process_simple_attribute(txt, ['Description'])
1265
+ project_identifier = process_simple_attribute(txt, ['Project Identifier'])
1266
+ project_status = process_simple_attribute(txt, ['Project Status'])
1267
+ project_phase = process_simple_attribute(txt, ['Project Phase'])
1268
+ project_health = process_simple_attribute(txt, ['Project Health'])
1269
+ start_date = process_simple_attribute(txt, ['Start Date'])
1270
+ planned_end_date = process_simple_attribute(txt, ['Planned End Date'])
1258
1271
  print(Markdown(f"{pre_command} `\'{command}\'` for project: `{project_name}` with directive: `{directive}` "))
1259
1272
 
1260
1273
  project_display = (f"\n* Command: {command}\n\t* Project: {project_name}\n\t"
@@ -1305,7 +1318,7 @@ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dicti
1305
1318
  valid = False
1306
1319
 
1307
1320
  if obj_action == "Update":
1308
- q_name = extract_attribute(txt, 'Qualified Name')
1321
+ q_name = process_simple_attribute(txt, 'Qualified Name')
1309
1322
 
1310
1323
  if not project_exists:
1311
1324
  msg += f"* {ERROR}Project {project_name} does not exist\n"
@@ -1360,12 +1373,12 @@ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dicti
1360
1373
  egeria_client.update_project(known_guid, known_q_name, project_identifier, project_name, description,
1361
1374
  project_status, project_phase, project_health, start_date, planned_end_date,
1362
1375
  False)
1363
- print(f"\n-->Updated Project {project_name} with GUID {known_guid}")
1376
+ print_msg(ALWAYS, f"Updated Project `{project_name}` with GUID {known_guid}", debug_level)
1364
1377
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
1365
1378
  elif object_action == "Create":
1366
1379
  guid = None
1367
1380
  if exists:
1368
- print(f"Project {project_name} already exists and update document created")
1381
+ print(f"Project `{project_name}` already exists and update document created")
1369
1382
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
1370
1383
  else:
1371
1384
  guid = egeria_client.create_project(None, None, None, False, project_name, description,
@@ -1378,4 +1391,5 @@ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dicti
1378
1391
 
1379
1392
  q_name = project_g['projectProperties']["qualifiedName"]
1380
1393
  update_element_dictionary(q_name, {'guid': guid, 'display_name': project_name})
1394
+ print_msg(ALWAYS, f"Created project `{project_name}` with GUID {guid}", debug_level)
1381
1395
  return update_a_command(txt, command, object_type, q_name, guid)