pyegeria 5.3.7.8__py3-none-any.whl → 5.3.8.0__py3-none-any.whl

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