pyegeria 5.3.7.2__py3-none-any.whl → 5.3.7.7__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.
@@ -0,0 +1,1103 @@
1
+ """
2
+
3
+ This file contains functions to parse and process Egeria Markdown (Freddie)
4
+
5
+
6
+ """
7
+
8
+ import json
9
+ from jupyter_notebook_parser import JupyterNotebookParser
10
+ import nbformat
11
+ from typing import List, Optional
12
+
13
+ import os
14
+ import re
15
+
16
+ from rich import box, print
17
+ from rich.console import Console
18
+ from rich.markdown import Markdown
19
+
20
+ 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
22
+ from pyegeria.egeria_tech_client import EgeriaTech
23
+ from pyegeria.project_manager_omvs import ProjectManager
24
+ from pyegeria.glossary_manager_omvs import GlossaryManager
25
+
26
+ from datetime import datetime
27
+ EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "200"))
28
+ console = Console(width=EGERIA_WIDTH)
29
+
30
+ command_list = ["Provenance",
31
+ "Create Glossary", "Update Glossary",
32
+ "Create Term", "Update Term",
33
+ "Create Personal Project", "Update Personal Project",
34
+ "Create Category", "Update Category",
35
+ "Create Solution Blueprint", "Update Solution Blueprint"]
36
+
37
+ ERROR = "ERROR-> "
38
+ INFO = "INFO- "
39
+ WARNING = "WARNING-> "
40
+ pre_command = "\n---\n==> Processing command:"
41
+
42
+ element_dictionary = {}
43
+
44
+ def render_markdown(markdown_text: str) -> None:
45
+ """Renders the given markdown text in the console."""
46
+ console.print(Markdown(markdown_text))
47
+
48
+
49
+ def is_valid_iso_date(date_text) -> bool:
50
+ """Checks if the given string is a valid ISO date."""
51
+ try:
52
+ datetime.strptime(date_text, '%Y-%m-%d')
53
+ return True
54
+ except ValueError:
55
+ return False
56
+
57
+
58
+ def get_current_datetime_string():
59
+ """Returns the current date and time as a human-readable string."""
60
+ now = datetime.now().strftime('%Y-%m-%d %H:%M')
61
+ return now
62
+
63
+
64
+ def add_term_to_categories(egeria_client: GlossaryManager, term_guid: str, categories_exist: bool,
65
+ categories_list: List[str], element_dictionary: dict) -> None:
66
+ if categories_exist is True and categories_list is not None:
67
+ for category in categories_list:
68
+ cat_guid = None
69
+ cat_el = category.strip()
70
+ if cat_el in element_dictionary:
71
+ cat= element_dictionary.get(cat_el, None)
72
+ cat_guid = cat.get('guid', None) if cat else None
73
+ if cat_guid is None:
74
+ cat_guid = egeria_client.__get_guid__(qualified_name=cat_el)
75
+ egeria_client.add_term_to_category(term_guid, cat_guid)
76
+
77
+
78
+ def extract_command_plus(block: str) -> tuple[str, str] | None:
79
+ match = re.search(r"#(.*?)(?:##|\n|$)", block) # Using a non capturing group
80
+ if match:
81
+ clean_match = match.group(1).strip()
82
+ parts = clean_match.split(' ')
83
+ object_action = parts[0].strip()
84
+ # Join the rest of the parts to allow object_type to be one or two words
85
+ object_type = ' '.join(parts[1:]).strip()
86
+ return object_type, object_action
87
+ return None
88
+
89
+ def extract_command(block: str) -> str | None:
90
+ match = re.search(r"#(.*?)(?:##|\n|$)", block) # Using a non capturing group
91
+ if match:
92
+ return match.group(1).strip()
93
+ return None
94
+
95
+ def extract_attribute(text: str, labels: List[str]) -> Optional[str]:
96
+ """
97
+ Extracts the glossary name from a string.
98
+
99
+ Args:
100
+ text: The input string.
101
+ labels: List of equivalent labels to search for
102
+
103
+ Returns:
104
+ The glossary name, or None if not found.
105
+ """
106
+ # Iterate over the list of labels
107
+ for label in labels:
108
+ # Construct pattern for the current label
109
+ pattern = rf"## {re.escape(label)}\n(.*?)(?:#|---|$)"
110
+ match = re.search(pattern, text, re.DOTALL)
111
+ if match:
112
+ # Extract matched text and replace consecutive \n with a single \n
113
+ extracted_text = re.sub(r'\n+', '\n', match.group(1).strip())
114
+ if not extracted_text.isspace() and extracted_text:
115
+ return extracted_text # Return the cleaned text
116
+
117
+
118
+
119
+ def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid: str) -> str:
120
+ u_guid = u_guid if u_guid else " "
121
+ verb = command.split(' ')[0].strip()
122
+ action = "Update" if (verb == "Create" and u_guid is not None) else "Create"
123
+ txt = txt.replace(f"{command}", f'{action} {obj_type}\n') # update the command
124
+ txt = txt.replace('<GUID>', f'GUID\n{u_guid}') # update with GUID
125
+ txt = txt.replace('<Qualified Name>', f"Qualified Name\n{q_name}")
126
+ if "Qualified Name" not in txt:
127
+ txt += f"\n## Qualified Name\n{q_name}\n"
128
+ if "GUID" not in txt:
129
+ txt += f"\n## GUID\n{u_guid}\n"
130
+
131
+ # if (command in {"Update Term", "Update Category", 'Update Glossary'}) and ("Update Description" not in txt):
132
+ # txt += '\n** Update Description\n\n\n'
133
+ # elif "Update Description" in txt:
134
+ # pattern = r"(## Update Description\n).*?(#)"
135
+ # replacement = r"\1\n\n\2"
136
+ # txt += re.sub(pattern, replacement, txt)
137
+
138
+ status = extract_attribute(txt, ["Status"])
139
+ if command in ["Create Term", "Update Term"] and status is None:
140
+ pattern = r"(## Status\s*\n)(.*?)(#)"
141
+ replacement = r"\1\n DRAFT\n\n\3"
142
+ txt = re.sub(pattern, replacement, txt)
143
+ return txt
144
+
145
+ def process_provenance_command(file_path: str, txt: [str]) -> str:
146
+ """This commands processes a provenence command by pre-pending the current file name and time to the provenance
147
+ output"""
148
+ output = (f"* Derived from processing file {file_path} on "
149
+ f"{get_current_datetime_string()}\n")
150
+ pattern = rf"# {re.escape('Provenance')}\n(.*?)(?:#|---|$)"
151
+ match = re.search(pattern, txt, re.DOTALL)
152
+ if match:
153
+ # Extract matched text and replace consecutive \n with a single \n
154
+ extracted_text = re.sub(r'\n+', '\n', match.group(1).strip())
155
+ if not extracted_text.isspace() and extracted_text:
156
+ existing_prov = extracted_text # Return the cleaned text
157
+ else:
158
+ existing_prov = None
159
+ print(f"txt is: {txt}, existing_prov: {existing_prov}")
160
+ existing_prov = existing_prov if existing_prov else " "
161
+ return f"\n# Provenance:\n{existing_prov}\n{output}\n"
162
+
163
+ def process_element_identifiers(egeria_client: EgeriaTech, txt: str) -> tuple[str, str, str, bool, bool]:
164
+ """
165
+ Processes element identifiers by extracting display name and qualified name from the input text,
166
+ checking if the element exists in Egeria, and validating the information.
167
+
168
+ Parameters:
169
+ egeria_client: EgeriaTech
170
+ Client object for interacting with Egeria.
171
+ txt: str
172
+ A string representing the input text to be processed for extracting element identifiers.
173
+
174
+ Returns: tuple[str, str, str, bool, bool]
175
+ A tuple containing:
176
+ - qualified_name: Empty string or element identifier
177
+ - guid: Empty string or additional element information
178
+ - msg: Information or error messages about the processing
179
+ - Valid: Boolean indicating if the element information is valid
180
+ - Exists: Boolean indicating if the element exists in Egeria
181
+ """
182
+
183
+ msg = ""
184
+ known_guid = None
185
+ valid = True
186
+ exists = False
187
+ display_name = extract_attribute(txt, ["Display Name"])
188
+ if display_name is None:
189
+ msg = f"* {ERROR}Display name is missing\n"
190
+ valid = False
191
+ return "","", msg, valid, exists
192
+ qualified_name = extract_attribute(txt, ["Qualified Name"])
193
+ if qualified_name:
194
+ element_details = egeria_client.get_terms_by_name(qualified_name)
195
+ else:
196
+ element_details = egeria_client.get_terms_by_name(display_name)
197
+
198
+ if element_details == NO_TERMS_FOUND:
199
+ exists = False
200
+ else:
201
+ exists = True
202
+
203
+ if len(element_details) > 1 and exists:
204
+ msg += (f"* {ERROR}More than one element with name {display_name} found, please specify a "
205
+ f"**Qualified Name**\n")
206
+ valid = False
207
+ elif len(element_details) == 1:
208
+ known_guid = element_details[0]['elementHeader'].get('guid', None)
209
+ known_q_name = element_details[0]['glossaryTermProperties'].get('qualifiedName', None)
210
+ if qualified_name != known_q_name:
211
+ msg += (f"* {ERROR}Element {display_name} qualifiedName mismatch between {qualified_name} and {known_q_name}\n")
212
+ valid = False
213
+ else:
214
+ msg += f"\n--> * Element {display_name} exists and can be updated\n"
215
+ # msg += term_display
216
+ # element_dictionary[known_q_name] = {'display_name': display_name, 'guid': known_guid}
217
+ return qualified_name, known_guid, msg, valid, exists
218
+
219
+ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
220
+ directive: str = "display") -> Optional[str]:
221
+ """
222
+ Processes a blueprint create or update command by extracting key attributes such as
223
+ blueprint name, description, and version from the given cell.
224
+
225
+ Parameters:
226
+ egeria_client: SolutionArchitect
227
+ Client object for interacting with Egeria.
228
+ txt: str
229
+ A string representing the input cell to be processed for
230
+ extracting glossary-related attributes.
231
+ directive: str, optional, default "display"
232
+ An optional string indicating the directive to be used - display, validate or execute
233
+
234
+ Returns: str
235
+ A string summarizing the outcome of the processing.
236
+ """
237
+
238
+ object_type, object_action = extract_command_plus(txt)
239
+ element_display = ""
240
+ display_name = extract_attribute(txt, ['Display Name','Blueprint Name'])
241
+ description = extract_attribute(txt, ['Description'])
242
+ version = extract_attribute(txt, ['Version', "Version Identifier", "Published Version"])
243
+
244
+ print(Markdown(f"{pre_command} `{object_type}{object_action}` for Blueprint: `\'{display_name}\'` with directive: `{directive}`"))
245
+
246
+ def validate_blueprint(obj_action: str) -> tuple[bool, bool, Optional[str], Optional[str]]:
247
+ nonlocal display_name, description, version, element_dictionary, element_display
248
+
249
+ known_q_name, known_guid, msg, valid, exists = process_element_identifiers(egeria_client, txt)
250
+
251
+ if description is None:
252
+ msg += f"* {INFO}Description is missing\n"
253
+
254
+ if version is None:
255
+ msg += f"* {INFO}Term version is missing\n"
256
+
257
+ update_description = extract_attribute(txt, ['Update Description'])
258
+ if update_description is None:
259
+ msg += f"* {INFO}Update Description is missing\n"
260
+ update_description = "---"
261
+ element_display = (f"\n* Command: {object_type}{object_action}\n\t* Blueprint: {display_name}\n\t"
262
+ f"* Term Name: {display_name}\n\t* Description: {description}\n\t"
263
+ f"* Version: {version}\n\t* Qualified Name:{known_q_name}\n\t* GUID: {known_guid} "
264
+ f"\n\t* Update Description: {update_description}\n")
265
+
266
+ if obj_action == "Update": # check to see if provided information exists and is consistent with existing info
267
+ if not exists:
268
+ msg += f"* {ERROR}Element {display_name} does not exist\n"
269
+ valid = False
270
+ element_dictionary[known_q_name] = {'display_name': display_name, 'guid': known_guid}
271
+
272
+ elif obj_action == 'Create': # if the command is create, check that it doesn't already exist
273
+ if exists:
274
+ msg += f"\n{WARNING}Element \'{display_name}\' already exists.\n"
275
+ elif not valid:
276
+ msg += f"\n-->Validation checks failed in creating element \'{display_name}\' with: {element_display}\n"
277
+ else: # valid to create - update element_dictionary
278
+ msg += f"\n-->It is valid to create element \'{display_name}\' with: {element_display}\n"
279
+ if known_q_name is None:
280
+ known_q_name = egeria_client.__create_qualified_name__(object_type, display_name)
281
+ element_dictionary[known_q_name] = {'display_name': display_name}
282
+ print(Markdown(msg))
283
+ return valid, exists, known_guid, known_q_name
284
+
285
+
286
+ if directive == "display":
287
+ print(Markdown(element_display))
288
+ return None
289
+ elif directive == "validate":
290
+ is_valid, exists, known_guid, known_q_name = validate_blueprint(object_action)
291
+ valid = is_valid if is_valid else None
292
+ return valid
293
+ elif directive == "process":
294
+ try:
295
+ is_valid, exists, known_guid, known_q_name = validate_blueprint(object_action)
296
+ if not is_valid: # First validate the term before we process it
297
+ return None
298
+
299
+ if object_action == "Update" and directive == "process":
300
+ if not exists:
301
+ print(f"\n-->Blueprint {display_name} does not exist")
302
+ return None
303
+
304
+ # call update blueprint here
305
+
306
+ print(f"\n-->Updated Blueprint {display_name} with GUID {known_guid}")
307
+ # update with get blueprint by guid
308
+ return 'Would return get blueprint by guid and return md' #egeria_client.get_terms_by_guid(known_guid, 'md')
309
+
310
+ elif object_action == "Update" and directive == "validate":
311
+ return 'Would call get_blueprint_by_guid and return md' #egeria_client.get_terms_by_guid(known_guid, 'md')
312
+
313
+ elif object_action == "Create":
314
+ if exists:
315
+ print(f"\n{WARNING}Blueprint {display_name} exists and result document updated")
316
+ return update_a_command(txt, f"{object_type}{object_action}",
317
+ object_type, known_q_name, known_guid)
318
+ else:
319
+ # create the blueprint
320
+ #term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
321
+ # if term_guid == NO_ELEMENTS_FOUND:
322
+ # print(f"{ERROR}Term {term_name} not created")
323
+ # return None
324
+
325
+ print(f"\n-->Created Blueprint {display_name} with GUID {known_guid}")
326
+ element_dictionary[known_q_name] = {'guid': known_guid, 'display_name': display_name}
327
+ return 'Would return get blueprint by guid results as md' #egeria_client.get_terms_by_guid(term_guid, 'MD')
328
+
329
+ except Exception as e:
330
+ print(f"{ERROR}Error creating term {display_name}: {e}")
331
+ console.print_exception(show_locals=True)
332
+ return None
333
+
334
+
335
+
336
+
337
+
338
+ def process_glossary_upsert_command(egeria_client: GlossaryManager, element_dictionary: dict, txt: str,
339
+ directive: str = "display") -> Optional[str]:
340
+ """
341
+ Processes a glossary create or update command by extracting key attributes such as
342
+ glossary name, language, description, and usage from the given text.
343
+
344
+ :param txt: A string representing the input cell to be processed for
345
+ extracting glossary-related attributes.
346
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
347
+ :return: A string summarizing the outcome of the processing.
348
+ """
349
+ command = extract_command(txt)
350
+ object_type = command.split(' ')[1].strip()
351
+ object_action = command.split(' ')[0].strip()
352
+
353
+ glossary_name = extract_attribute(txt, ['Glossary Name'])
354
+ print(Markdown(f"{pre_command} `{command}` for glossary: `\'{glossary_name}\'` with directive: `{directive}` "))
355
+ language = extract_attribute(txt, ['Language'])
356
+ description = extract_attribute(txt, ['Description'])
357
+ usage = extract_attribute(txt, ['Usage'])
358
+
359
+ glossary_display = (f"\n* Command: {command}\n\t* Glossary Name: {glossary_name}\n\t"
360
+ f"* Language: {language}\n\t* Description:\n{description}\n"
361
+ f"* Usage: {usage}\n")
362
+
363
+ if object_action == 'Update':
364
+ q_name = extract_attribute(txt, ['Qualified Name'])
365
+ guid = extract_attribute(txt, ['GUID', 'guid', 'Guid'])
366
+ glossary_display += f"* Qualified Name: {q_name}\n\t* GUID: {guid}\n\n"
367
+
368
+ def validate_glossary(obj_action: str) -> tuple[bool, bool, Optional[str], Optional[str]]:
369
+ valid = True
370
+ msg = ""
371
+ known_glossary_guid = None
372
+ known_q_name = None
373
+
374
+ glossary_details = egeria_client.get_glossaries_by_name(glossary_name)
375
+ if glossary_details == NO_GLOSSARIES_FOUND:
376
+ glossary_exists = False
377
+ else:
378
+ glossary_exists = True
379
+
380
+ if glossary_name is None:
381
+ msg = f"* {ERROR}Glossary name is missing\n"
382
+ valid = False
383
+ if language is None:
384
+ msg += f"* {ERROR}Language is missing\n"
385
+ valid = False
386
+ if description is None:
387
+ msg += f"* {INFO}Description is missing\n"
388
+
389
+ if len(glossary_details) > 1 and glossary_exists:
390
+ msg += f"* {ERROR}More than one glossary with name {glossary_name} found\n"
391
+ valid = False
392
+ if len(glossary_details) == 1:
393
+ known_glossary_guid = glossary_details[0]['elementHeader'].get('guid', None)
394
+ known_q_name = glossary_details[0]['glossaryProperties'].get('qualifiedName', None).strip()
395
+
396
+ if obj_action == "Update":
397
+
398
+ if not glossary_exists:
399
+ msg += f"* {ERROR}Glossary {glossary_name} does not exist\n"
400
+ valid = False
401
+
402
+ if q_name is None:
403
+ msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
404
+ valid = True
405
+ elif q_name != known_q_name:
406
+ msg += (
407
+ f"* {ERROR}Glossary `{glossary_name}` qualifiedName mismatch between {q_name} and {known_q_name}\n")
408
+ valid = False
409
+ if valid:
410
+ msg += glossary_display
411
+ msg += f"* -->Glossary `{glossary_name}` exists and can be updated\n"
412
+ element_dictionary[known_q_name] = {'display_name': glossary_name, 'guid': known_glossary_guid}
413
+ else:
414
+ msg += f"* --> validation failed\n"
415
+
416
+ print(Markdown(msg))
417
+ return valid, glossary_exists, known_glossary_guid, known_q_name
418
+
419
+ elif obj_action == "Create":
420
+ if glossary_exists:
421
+ msg += f"{ERROR}Glossary {glossary_name} already exists\n"
422
+
423
+ elif valid:
424
+ msg += f"-->It is valid to create Glossary \'{glossary_name}\' with:\n"
425
+ msg += glossary_display
426
+ expected_q_name = egeria_client.__create_qualified_name__('Glossary', glossary_name)
427
+ element_dictionary[expected_q_name] = {'display_name': glossary_name}
428
+
429
+ print(Markdown(msg))
430
+ return valid, glossary_exists, known_glossary_guid, known_q_name
431
+
432
+ if directive == "display":
433
+ print(Markdown(glossary_display))
434
+ return None
435
+
436
+ elif directive == "validate":
437
+ is_valid, exists, known_guid, known_q_name = validate_glossary(object_action)
438
+ valid = is_valid if is_valid else None
439
+ return valid
440
+
441
+ elif directive == "process":
442
+ is_valid, exists, known_guid, known_q_name = validate_glossary(object_action)
443
+ if not is_valid:
444
+ return None
445
+ if object_action == "Update":
446
+ if not exists:
447
+ print(
448
+ f"\n{ERROR}Glossary {glossary_name} does not exist! Updating result document with Create command\n")
449
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
450
+
451
+ body = {
452
+ "class": "ReferenceableRequestBody", "elementProperties": {
453
+ "class": "GlossaryProperties", "qualifiedName": known_q_name, "description": description,
454
+ "language": language, "usage": usage
455
+ }
456
+ }
457
+ egeria_client.update_glossary(known_guid, body)
458
+ print(f"\n-->Updated Glossary {glossary_name} with GUID {known_guid}")
459
+ element_dictionary[known_q_name] = {
460
+ 'guid': known_guid, 'display_name': glossary_name
461
+ }
462
+ # return update_a_command(txt, command, object_type, known_q_name, known_guid)
463
+ return egeria_client.get_glossary_by_guid(known_guid, output_format='MD')
464
+ elif object_action == "Create":
465
+ glossary_guid = None
466
+
467
+ if exists:
468
+ print(f"\nGlossary {glossary_name} already exists and result document updated\n")
469
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
470
+ else:
471
+ glossary_guid = egeria_client.create_glossary(glossary_name, description, language, usage)
472
+ glossary = egeria_client.get_glossary_by_guid(glossary_guid)
473
+ if glossary == NO_GLOSSARIES_FOUND:
474
+ print(f"{ERROR}Just created with GUID {glossary_guid} but Glossary not found\n")
475
+ return None
476
+ qualified_name = glossary['glossaryProperties']["qualifiedName"]
477
+ element_dictionary[qualified_name] = {
478
+ 'guid': glossary_guid, 'display_name': glossary_name
479
+ }
480
+ # return update_a_command(txt, command, object_type, qualified_name, glossary_guid)
481
+ return egeria_client.get_glossary_by_guid(glossary_guid, output_format = 'MD')
482
+
483
+
484
+ def process_categories_upsert_command(egeria_client: GlossaryManager, element_dictionary: dict, txt: str,
485
+ directive: str = "display") -> Optional[str]:
486
+ """
487
+ Processes a glossary category create or update command by extracting key attributes such as
488
+ category name, qualified, description, and anchor glossary from the given txt..
489
+
490
+ :param txt: A string representing the input cell to be processed for
491
+ extracting category-related attributes.
492
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
493
+ :return: A string summarizing the outcome of the processing.
494
+ """
495
+ command = extract_command(txt)
496
+ object_type = command.split(' ')[1].strip()
497
+ object_action = command.split(' ')[0].strip()
498
+
499
+ category_name = extract_attribute(txt, ['Category Name', 'category_name', 'Cat'])
500
+ print(Markdown(f"{pre_command} `{command}` for category: `\'{category_name}\'` with directive: `{directive}` "))
501
+ owning_glossary_qn = extract_attribute(txt, ['Owning Glossary', '[In Glossary'])
502
+ description = extract_attribute(txt, ['Description'])
503
+ q_name = extract_attribute(txt, ['Qualified Name'])
504
+
505
+ category_display = (f"\n* Command: {command}\n\t* Category: {category_name}\n\t* In Glossary: {owning_glossary_qn}\n\t"
506
+ f"* Description:\n{description}\n\t* Qualified Name: {q_name}\n\t")
507
+ update_description = None
508
+
509
+ if object_action == 'Update':
510
+ guid = extract_attribute(txt, ['GUID','guid','Guid'])
511
+ update_description = extract_attribute(txt, 'Update Description')
512
+ category_display += (f"* GUID: {guid}\n\n"
513
+ f"* Update Description: \n {update_description}\n\t")
514
+
515
+ def validate_category(obj_action: str) -> tuple[bool, bool, Optional[str], Optional[str], Optional[str]]:
516
+ valid = True
517
+ msg = ""
518
+ known_category_guid = None
519
+ known_q_name = None
520
+ glossary_guid = None
521
+
522
+ category_details = egeria_client.get_categories_by_name(category_name)
523
+ if category_details == NO_CATEGORIES_FOUND:
524
+ category_exists = False
525
+ else:
526
+ category_exists = True
527
+
528
+ if owning_glossary_qn is None:
529
+ msg += f"* {ERROR}Owning Glossary Qualified Name is missing\n"
530
+ valid = False
531
+
532
+ elif owning_glossary_qn in element_dictionary: # Check to see if we already know about this glossary
533
+ glossary_name = element_dictionary[owning_glossary_qn].get('display_name', None)
534
+ glossary_guid = element_dictionary[owning_glossary_qn].get('guid', None)
535
+
536
+ else:
537
+ # need to ask Egeria if it knows the Glossary Name
538
+ glossary = egeria_client.get_glossaries_by_name(owning_glossary_qn)
539
+ if glossary == NO_GLOSSARIES_FOUND:
540
+ msg += f"* {ERROR}Glossary `{owning_glossary_qn}` does not exist\n\n"
541
+ valid = False
542
+ else:
543
+ msg += f"* {INFO}Glossary `{owning_glossary_qn}` exists\n\n"
544
+ glossary_guid = glossary[0]['elementHeader'].get('guid', None)
545
+ glossary_name = glossary[0]['glossaryProperties'].get('displayName', None)
546
+ glossary_qn = glossary[0]['glossaryProperties'].get('qualifiedName', None)
547
+ if glossary_qn != owning_glossary_qn: # we were given the right qualified name - maybe a display_name
548
+ msg += f"* {ERROR}Glossary `{owning_glossary_qn}` is known by qualifiedName `{glossary_qn}`\n\n"
549
+ valid = False
550
+ else:
551
+ element_dictionary[owning_glossary_qn] = {
552
+ 'guid': glossary_guid, 'display_name': glossary_name
553
+ }
554
+
555
+ if category_name is None:
556
+ msg = f"* {ERROR}Category name is missing\n"
557
+ valid = False
558
+
559
+ if description is None:
560
+ msg += f"* {INFO}Description is missing\n"
561
+
562
+ if len(category_details) > 1 and category_exists:
563
+ msg += f"* {ERROR}More than one category with name `{category_name}` found\n"
564
+ valid = False
565
+ if len(category_details) == 1:
566
+ known_category_guid = category_details[0]['elementHeader'].get('guid', None)
567
+ known_q_name = category_details[0]['glossaryCategoryProperties'].get('qualifiedName', None)
568
+
569
+ if obj_action == "Update":
570
+ if not category_exists:
571
+ msg += f"* {ERROR}category `{category_name}` does not exist\n"
572
+ valid = False
573
+ if q_name is None:
574
+ msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
575
+ valid = True
576
+ elif q_name != known_q_name:
577
+ msg += (
578
+ f"* {ERROR}category `{category_name}` qualifiedName mismatch between {q_name} and {known_q_name}\n")
579
+ valid = False
580
+ if valid:
581
+ msg += category_display
582
+ msg += f"* -->category `{category_name}` exists and can be updated\n"
583
+ element_dictionary[known_q_name] = {'display_name': glossary_name, 'guid': known_category_guid}
584
+ else:
585
+ msg += f"* --> validation failed\n"
586
+
587
+ print(Markdown(msg))
588
+ return valid, category_exists, known_category_guid, known_q_name, glossary_guid
589
+
590
+ elif obj_action == "Create":
591
+ if category_exists:
592
+ msg += f"{ERROR}category `{category_name}` already exists\n"
593
+
594
+ elif valid:
595
+ msg += f"-->It is valid to create category `{category_name}` with:\n"
596
+ msg += category_display
597
+ expected_q_name = egeria_client.__create_qualified_name__('Category', category_name)
598
+ element_dictionary[expected_q_name] = {'display_name': category_name}
599
+
600
+ print(Markdown(msg))
601
+ return valid, category_exists, known_category_guid, known_q_name, glossary_guid
602
+
603
+ if directive == "display":
604
+ print(Markdown(category_display))
605
+ return None
606
+
607
+ elif directive == "validate":
608
+ is_valid, exists, known_guid, known_q_name, glossary_guid = validate_category(object_action)
609
+ valid = is_valid if is_valid else None
610
+ return valid
611
+
612
+ elif directive == "process":
613
+ is_valid, exists, known_guid, known_q_name, glossary_guid = validate_category(object_action)
614
+ if not is_valid:
615
+ print(f"{ERROR}Validation checks failed in creating category `{category_name}`")
616
+ return None
617
+
618
+ if object_action == "Update":
619
+ if not exists:
620
+ print(
621
+ f"\n{ERROR}category `{category_name}` does not exist! Updating result document with Create "
622
+ f"command\n")
623
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
624
+
625
+ egeria_client.update_category(glossary_guid, category_name, description, known_q_name, None,
626
+ update_description)
627
+ print(f"\n-->Updated category `{category_name}`with GUID {known_guid}")
628
+ element_dictionary[known_q_name] = {
629
+ 'guid': known_guid, 'display_name': category_name
630
+ }
631
+ # return update_a_command(txt, command, object_type, known_q_name, known_guid)
632
+ return egeria_client.get_categories_by_guid(known_guid, output_format='FORM')
633
+
634
+ elif object_action == "Create":
635
+ is_root = False
636
+
637
+ if exists:
638
+ print(f"\ncategory `{category_name}` already exists and result document updated\n")
639
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
640
+ else:
641
+ category_guid = egeria_client.create_category(glossary_guid, category_name, description, is_root)
642
+ category = egeria_client.get_categories_by_guid(category_guid)
643
+
644
+ if category == NO_CATEGORIES_FOUND:
645
+ print(f"{ERROR}Just created with GUID {category_guid} but category not found\n")
646
+ return None
647
+ qualified_name = category['glossaryCategoryProperties']["qualifiedName"]
648
+ element_dictionary[qualified_name] = {
649
+ 'guid': category_guid, 'display_name': category_name
650
+ }
651
+ # return update_a_command(txt, command, object_type, qualified_name, category_guid)
652
+ return egeria_client.get_categories_by_guid(category_guid, output_format='MD')
653
+
654
+
655
+ def process_term_upsert_command(egeria_client: GlossaryManager, element_dictionary: dict, txt: str,
656
+ directive: str = "display") -> Optional[str]:
657
+ """
658
+ Processes a term create or update command by extracting key attributes such as
659
+ term name, summary, description, abbreviation, examples, usage, version, and status from the given cell.
660
+
661
+ :param txt: A string representing the input cell to be processed for
662
+ extracting glossary-related attributes.
663
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
664
+ :return: A string summarizing the outcome of the processing.
665
+ """
666
+
667
+ command = extract_command(txt)
668
+ object_type = command.split(' ')[1].strip()
669
+ object_action = command.split(' ')[0].strip()
670
+
671
+ term_name = extract_attribute(txt, ['Term Name'])
672
+ summary = extract_attribute(txt, ['Summary'])
673
+ description = extract_attribute(txt, ['Description'])
674
+ abbreviation = extract_attribute(txt, ['Abbreviation'])
675
+ examples = extract_attribute(txt, ['Examples'])
676
+ usage = extract_attribute(txt, ['Usage'])
677
+ status = extract_attribute(txt, ['Status'])
678
+ version = extract_attribute(txt, ['Version', "Version Identifier", "Published Version"])
679
+ categories = extract_attribute(txt, ['Categories'])
680
+ q_name = extract_attribute(txt, ['Qualified Name'])
681
+ # q_name = q_name if q_name else " "
682
+
683
+ categories_list = None
684
+ cats_exist = True
685
+
686
+ glossary_qn = extract_attribute(txt, ['In Glossary','Owning Glossary'])
687
+
688
+ print(Markdown(f"{pre_command} `{command}` for term: `\'{term_name}\'` with directive: `{directive}`"))
689
+
690
+ def validate_term(obj_action: str) -> tuple[bool, bool, Optional[str], Optional[str]]:
691
+ nonlocal version, status, categories, categories_list, cats_exist, q_name, glossary_qn
692
+ valid = True
693
+ msg = ""
694
+ known_term_guid = None
695
+ known_q_name = None
696
+
697
+ # If the user has specified a qualified_name then use it to look for matching terms.
698
+ # If not, use the display_name.
699
+ if q_name:
700
+ term_details = egeria_client.get_terms_by_name(q_name)
701
+ else:
702
+ term_details = egeria_client.get_terms_by_name(term_name)
703
+
704
+ if term_details == NO_TERMS_FOUND:
705
+ term_exists = False
706
+ else:
707
+ term_exists = True
708
+
709
+ if status is None:
710
+ msg += f"* {INFO}Term status is missing - will default to DRAFT\n"
711
+ status = 'DRAFT'
712
+
713
+
714
+ if term_name is None:
715
+ msg = f"* {ERROR}Term name is missing\n"
716
+ valid = False
717
+ if glossary_qn is None:
718
+ msg += f"* {ERROR}Glossary qualified name is missing\n"
719
+ valid = False
720
+ else:
721
+ print(f"* {INFO}Glossary qualified name is `{glossary_qn}`")
722
+ if glossary_qn not in element_dictionary:
723
+ glossary = egeria_client.get_glossaries_by_name(glossary_qn) #assuming q_name?
724
+ if isinstance(glossary,str):
725
+ msg += f"* {ERROR}Glossary `{glossary_qn}` is unknown\n "
726
+ valid = False
727
+ elif len(glossary) != 1:
728
+ msg += f"* {ERROR}Glossary `{glossary_qn}` is ambiguous or not found\n "
729
+ valid = False
730
+ else:
731
+ glossary_qn = glossary[0]['glossaryProperties'].get('qualifiedName', None)
732
+ if glossary_qn is None:
733
+ msg += f"* {ERROR}Glossary `{glossary_qn}` has no qualifiedName\n "
734
+ valid = False
735
+ else:
736
+ element_dictionary[glossary_qn] = {
737
+ 'guid': glossary[0]['elementHeader'].get('guid', None),
738
+ 'display_name': glossary[0]['glossaryProperties'].get('displayName', None)
739
+ }
740
+
741
+
742
+ if categories is None:
743
+ msg += f"* {INFO} No categories found\n"
744
+ else:
745
+ categories_list = re.split(r'[,\n]+', categories)
746
+ categories = ""
747
+ new_cat_list = []
748
+ for category in categories_list:
749
+ category_el = category.strip()
750
+ if category_el not in element_dictionary:
751
+ cat = egeria_client.get_categories_by_name(category_el) # assuming qualified name?
752
+ if isinstance(cat,str):
753
+ msg += (f"* {WARNING}Category `{category_el}` not found -> "
754
+ f"categories for this term won't be processed!\n")
755
+ cats_exist = False
756
+ break
757
+ cat_qname = cat[0]['glossaryCategoryProperties'].get('qualifiedName', None)
758
+ category = cat_qname # use the qualified name if found
759
+ if cat_qname not in element_dictionary:
760
+ cat_guid = cat[0]['elementHeader']['guid']
761
+ cat_display_name = cat[0]['glossaryCategoryProperties'].get('displayName', None)
762
+ element_dictionary[cat_qname] = {
763
+ 'guid' : cat_guid,
764
+ 'displayName': cat_display_name
765
+ }
766
+ categories = f"{category}, {categories}"
767
+ new_cat_list.append(category)
768
+ if cats_exist:
769
+ categories +='\n'
770
+ categories_list = new_cat_list
771
+ else:
772
+ categories = None
773
+
774
+
775
+ if summary is None:
776
+ msg += f"* {INFO}Term summary is missing\n"
777
+
778
+ if description is None:
779
+ msg += f"* {INFO}Term description is missing\n"
780
+
781
+ if abbreviation is None:
782
+ msg += f"* {INFO}Term abbreviation is missing\n"
783
+ if examples is None:
784
+ msg += f"* {INFO}Term examples is missing\n"
785
+ if usage is None:
786
+ msg += f"* {INFO}Term usage is missing\n"
787
+ if version is None:
788
+ msg += f"* {INFO}Term version is missing\n"
789
+ # version = "0.0.1"
790
+
791
+
792
+ if obj_action == "Update": # check to see if provided information exists and is consistent with existing info
793
+ if not term_exists:
794
+ msg += f"* {ERROR}Term {term_name} does not exist\n"
795
+ valid = False
796
+
797
+ if len(term_details) > 1 and term_exists:
798
+ msg += (f"* {ERROR}More than one term with name {term_name} found, please specify a "
799
+ f"**Qualified Name**\n")
800
+ valid = False
801
+ elif len(term_details) == 1:
802
+ known_term_guid = term_details[0]['elementHeader'].get('guid', None)
803
+ known_q_name = term_details[0]['glossaryTermProperties'].get('qualifiedName', None)
804
+ if q_name != known_q_name:
805
+ msg += (f"* {ERROR}Term {term_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
806
+ valid = False
807
+ else:
808
+ msg += f"\n--> * Term {term_name} exists and can be updated\n"
809
+ msg += term_display
810
+ element_dictionary[known_q_name] = {'display_name': term_name, 'guid': known_term_guid}
811
+
812
+ print(Markdown(msg))
813
+ return valid, term_exists, known_term_guid, known_q_name
814
+
815
+ elif obj_action == 'Create': # if the command is create, check that it doesn't already exist
816
+ if term_exists:
817
+ msg += f"\n{WARNING}Term \'{term_name}\' already exists.\n"
818
+ elif not valid:
819
+ msg += f"\n-->Validation checks failed in creating Term \'{term_name}\' with: {term_display}\n"
820
+ else:
821
+ msg += f"\n-->It is valid to create Term \'{term_name}\' with: {term_display}\n"
822
+ if q_name is None:
823
+ expected_q_name = egeria_client.__create_qualified_name__('Term', term_name)
824
+ element_dictionary[expected_q_name] = {'display_name': term_name}
825
+ else:
826
+ element_dictionary[q_name] = {'display_name': term_name}
827
+ print(Markdown(msg))
828
+ return valid, term_exists, known_term_guid, known_q_name
829
+
830
+ # Continue processing the upsert
831
+ if object_action == "Update":
832
+ term_guid = extract_attribute(txt, 'GUID')
833
+ term_guid = term_guid if term_guid else None
834
+
835
+
836
+ update_description = extract_attribute(txt, 'Update Description')
837
+ update_description = update_description if update_description else " "
838
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {glossary_qn}\n\t"
839
+ f"* Term Name: {term_name}\n\t* Qualified Name: {q_name}\n\t* Categories: {categories}\n\t"
840
+ f"* Summary: {summary}\n\t* Description: {description}\n\t"
841
+ f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
842
+ f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}\n\t* Qualified Name: "
843
+ f"{q_name}"
844
+ f"\n\t* Update Description: {update_description}\n")
845
+ else:
846
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {glossary_qn}\n\t"
847
+ f"* Term Name: {term_name}\n\t* Categories: {categories}\n\t* Summary: {summary}\n\t"
848
+ f"* Qualified Name: {q_name}\n\t* Description: {description}\n\t"
849
+ f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
850
+ f"* Version: {version}\n\t* Status: {status}\n")
851
+
852
+ if directive == "display":
853
+ print(Markdown(term_display))
854
+ return None
855
+ elif directive == "validate":
856
+ is_valid, exists, known_guid, known_q_name = validate_term(object_action)
857
+ valid = is_valid if is_valid else None
858
+ return valid
859
+ elif directive == "process":
860
+ try:
861
+ is_valid, exists, known_guid, known_q_name = validate_term(object_action)
862
+ if not is_valid: # First validate the term before we process it
863
+ return None
864
+
865
+ if object_action == "Update" and directive == "process":
866
+ if not exists:
867
+ print(f"\n-->Term {term_name} does not exist")
868
+ return None
869
+ body = {
870
+ "class": "ReferenceableRequestBody",
871
+ "elementProperties": {
872
+ "class": "GlossaryTermProperties",
873
+ "qualifiedName": known_q_name,
874
+ "summary": summary,
875
+ "description": description,
876
+ "abbreviation": abbreviation,
877
+ "examples": examples,
878
+ "usage": usage,
879
+ "publishVersionIdentifier": version,
880
+ "status": status
881
+ },
882
+ "updateDescription": update_description
883
+ }
884
+ egeria_client.update_term(known_guid, body_slimmer(body))
885
+ # if cats_exist is True and categories_list is not None:
886
+ # for category in categories_list:
887
+ # cat_guid = element_dictionary.get(f"category.{category}", None)
888
+ # if cat_guid is None:
889
+ # cat_guid = egeria_client.__get_guid__(display_name=category)
890
+ # egeria_client.add_term_to_category(known_guid, cat_guid)
891
+ add_term_to_categories(
892
+ egeria_client, known_guid, cats_exist , categories_list,
893
+ element_dictionary)
894
+ print(f"\n-->Updated Term {term_name} with GUID {known_guid} and categories {categories_list}")
895
+ return egeria_client.get_terms_by_guid(known_guid, 'md')
896
+ # return update_a_command(txt, command, object_type, known_q_name, known_guid)
897
+ elif object_action == "Update" and directive == "validate":
898
+ return egeria_client.get_terms_by_guid(known_guid, 'md')
899
+
900
+ elif object_action == "Create":
901
+ guid = None
902
+ if q_name is None:
903
+ q_name = egeria_client.__create_qualified_name__("Term",term_name)
904
+ if exists:
905
+ print(f"\n{WARNING}Term {term_name} exists and result document updated")
906
+ return update_a_command(txt, command, object_type, q_name, known_guid)
907
+ else:
908
+ ## get the guid for the glossary from the name - first look locally
909
+ glossary = element_dictionary.get(glossary_qn, None)
910
+
911
+ if glossary is not None:
912
+ glossary_guid = glossary.get('guid', None)
913
+ if glossary_guid is None:
914
+ print(f"{ERROR}Glossary reference {glossary_qn} not found")
915
+ return None
916
+ else:
917
+ glossary_guid = egeria_client.__get_guid__(qualified_name=glossary_qn)
918
+ if glossary_guid == NO_ELEMENTS_FOUND:
919
+ print(f"{ERROR}Glossary {glossary_qn} not found")
920
+ return None
921
+ term_body = {
922
+ "class": "ReferenceableRequestBody", "elementProperties": {
923
+ "class": "GlossaryTermProperties",
924
+ "qualifiedName": q_name,
925
+ "displayName": term_name,
926
+ "summary": summary,
927
+ "description": description,
928
+ "abbreviation": abbreviation,
929
+ "examples": examples,
930
+ "usage": usage,
931
+ "publishVersionIdentifier": version
932
+ # "additionalProperties":
933
+ # {
934
+ # "propertyName1": "xxxx",
935
+ # "propertyName2": "xxxx"
936
+ # }
937
+ }, "initialStatus": status
938
+ }
939
+ term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
940
+ if term_guid == NO_ELEMENTS_FOUND:
941
+ print(f"{ERROR}Term {term_name} not created")
942
+ return None
943
+ if cats_exist and categories is not None:
944
+ add_term_to_categories(
945
+ egeria_client, term_guid, cats_exist, categories_list,
946
+ element_dictionary)
947
+ print(f"\n-->Created Term {term_name} with GUID {term_guid}")
948
+ element_dictionary[q_name] = {'guid': term_guid, 'display_name': term_name}
949
+ return egeria_client.get_terms_by_guid(term_guid, 'MD')
950
+ # return update_a_command(txt, command, object_type, q_name, term_guid)
951
+ except Exception as e:
952
+ print(f"{ERROR}Error creating term {term_name}: {e}")
953
+ console.print_exception(show_locals=True)
954
+ return None
955
+
956
+ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dictionary: dict, txt: str,
957
+ directive: str = "display") -> str | None:
958
+ """
959
+ Processes a personal project create or update command by extracting key attributes such as
960
+ glossary name, language, description, and usage from the given cell.
961
+
962
+ :param txt: A string representing the input cell to be processed for
963
+ extracting glossary-related attributes.
964
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
965
+ :return: A string summarizing the outcome of the processing.
966
+ """
967
+ command = extract_command(txt)
968
+ object = command.split()
969
+ object_type = f"{object[1]} {object[2]}"
970
+ object_action = object[0]
971
+
972
+ project_name = extract_attribute(txt, ['Project Name'])
973
+ description = extract_attribute(txt, ['Description'])
974
+ project_identifier = extract_attribute(txt, ['Project Identifier'])
975
+ project_status = extract_attribute(txt, ['Project Status'])
976
+ project_phase = extract_attribute(txt, ['Project Phase'])
977
+ project_health = extract_attribute(txt, ['Project Health'])
978
+ start_date = extract_attribute(txt, ['Start Date'])
979
+ planned_end_date = extract_attribute(txt, ['Planned End Date'])
980
+ print(Markdown(f"{pre_command} `\'{command}\'` for project: `{project_name}` with directive: `{directive}` "))
981
+
982
+ project_display = (f"\n* Command: {command}\n\t* Project: {project_name}\n\t"
983
+ f"* Status: {project_status}\n\t* Description: {description}\n\t"
984
+ f"* Phase: {project_phase}\n\t* Health: {project_health}\n\t"
985
+ f"* Start Date: {start_date}\n\t* Planned End Date: {planned_end_date}\n")
986
+
987
+ def validate_project(obj_action: str) -> tuple[bool, bool, str, str]:
988
+ valid = True
989
+ msg = ""
990
+ known_guid = None
991
+ known_q_name = None
992
+
993
+ project_details = egeria_client.get_projects_by_name(project_name)
994
+ if project_details == NO_PROJECTS_FOUND:
995
+ project_exists = False
996
+ else:
997
+ project_exists = True
998
+
999
+ if project_name is None:
1000
+ msg = f"* {ERROR}Project name is missing\n"
1001
+ valid = False
1002
+ if project_status is None:
1003
+ msg += f"* {INFO}No Project status found\n"
1004
+
1005
+ if description is None:
1006
+ msg += f"* {INFO}No Description found\n"
1007
+
1008
+ if project_identifier is None:
1009
+ msg += f"* {INFO}No Project Identifier found\n"
1010
+
1011
+ if project_phase is None:
1012
+ msg += f"* {INFO}No Project Phase found\n"
1013
+
1014
+ if project_health is None:
1015
+ msg += f"* {INFO}No Project Health found\n"
1016
+
1017
+ if start_date is None:
1018
+ msg += f"* {INFO}No Start Date found\n"
1019
+ elif not is_valid_iso_date(start_date):
1020
+ msg += f"* {ERROR}Start Date is not a valid ISO date of form YYYY-MM-DD\n"
1021
+ valid = False
1022
+
1023
+ if planned_end_date is None:
1024
+ msg += f"* {INFO} No Planned End Date found\n"
1025
+ elif not is_valid_iso_date(planned_end_date):
1026
+ msg += f"* {ERROR}Planned End Date is not a valid ISO date of form YYYY-MM-DD\n"
1027
+ valid = False
1028
+
1029
+ if obj_action == "Update":
1030
+ q_name = extract_attribute(txt, 'Qualified Name')
1031
+
1032
+ if not project_exists:
1033
+ msg += f"* {ERROR}Project {project_name} does not exist\n"
1034
+ valid = False
1035
+ if len(project_details) > 1 and project_exists:
1036
+ msg += f"* {ERROR}More than one project with name {project_name} found\n"
1037
+ valid = False
1038
+ if len(project_details) == 1:
1039
+ known_guid = project_details[0]['elementHeader'].get('guid', None)
1040
+ known_q_name = project_details[0]['glossaryProperties'].get('qualifiedName', None)
1041
+ if q_name is None:
1042
+ msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
1043
+ valid = True
1044
+ elif q_name != known_q_name:
1045
+ msg += (f"* {ERROR}Project {project_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
1046
+ valid = False
1047
+ if valid:
1048
+ msg += project_display
1049
+ msg += f"* -->Project {project_name} exists and can be updated\n"
1050
+ else:
1051
+ msg += f"* --> validation failed\n"
1052
+ msg += '---'
1053
+ print(Markdown(msg))
1054
+ return valid, project_exists, known_guid, known_q_name
1055
+
1056
+ elif obj_action == "Create":
1057
+ if project_exists:
1058
+ msg += f"\n{ERROR}Project {project_name} already exists"
1059
+ else:
1060
+ msg += f"\n-->It is valid to create Project \'{project_name}\' with:\n"
1061
+ print(Markdown(msg))
1062
+ return valid, project_exists, known_guid, known_q_name
1063
+
1064
+ if directive == "display":
1065
+ print(Markdown(project_display))
1066
+ return None
1067
+
1068
+ elif directive == "validate":
1069
+ is_valid, exists, known_guid, known_q_name = validate_project(object_action)
1070
+ valid = is_valid if is_valid else None
1071
+ return valid
1072
+
1073
+ elif directive == "process":
1074
+ is_valid, exists, known_guid, known_q_name = validate_project(object_action)
1075
+ if not is_valid:
1076
+ return None
1077
+ if object_action == "Update":
1078
+ if not exists:
1079
+ print(f"\n\n-->Project {project_name} does not exist")
1080
+ return None
1081
+
1082
+ egeria_client.update_project(known_guid, known_q_name, project_identifier, project_name, description,
1083
+ project_status, project_phase, project_health, start_date, planned_end_date,
1084
+ False)
1085
+ print(f"\n-->Updated Project {project_name} with GUID {known_guid}")
1086
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
1087
+ elif object_action == "Create":
1088
+ guid = None
1089
+ if exists:
1090
+ print(f"Project {project_name} already exists and update document created")
1091
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
1092
+ else:
1093
+ guid = egeria_client.create_project(None, None, None, False, project_name, description,
1094
+ "PersonalProject", project_identifier, True, project_status,
1095
+ project_phase, project_health, start_date, planned_end_date)
1096
+ project_g = egeria_client.get_project(guid)
1097
+ if project_g == NO_GLOSSARIES_FOUND:
1098
+ print(f"Just created with GUID {guid} but Project not found")
1099
+ return None
1100
+
1101
+ q_name = project_g['projectProperties']["qualifiedName"]
1102
+ element_dictionary[q_name] = {'guid': guid, 'display_name': project_name}
1103
+ return update_a_command(txt, command, object_type, q_name, guid)