pyegeria 5.3.8.1__py3-none-any.whl → 5.3.8.3__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.
@@ -10,25 +10,23 @@ https://egeria-project.org/concepts/information-supply-chain
10
10
  import asyncio
11
11
  import os
12
12
  import sys
13
+ from datetime import datetime
13
14
 
14
15
  from httpx import Response
15
16
 
16
- from pyegeria.utils import body_slimmer
17
+ from pyegeria import validate_guid
17
18
  from pyegeria._client import Client, max_paging_size
18
19
  from pyegeria._globals import NO_ELEMENTS_FOUND
19
- sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
20
-
20
+ from pyegeria.utils import body_slimmer
21
21
 
22
+ sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
22
23
 
23
24
  DEFAULT_BODY_SKELETON = {
24
- "effective_time": None,
25
- "limitResultsByStatus": ["ACTIVE"],
26
- "asOfTime": None,
27
- "sequencingOrder": None,
28
- "sequencingProperty": None,
29
- "filter": None,
30
- }
25
+ "effective_time": None, "limitResultsByStatus": ["ACTIVE"], "asOfTime": None, "sequencingOrder": None,
26
+ "sequencingProperty": None, "filter": None,
27
+ }
31
28
 
29
+ MD_SEPERATOR = "\n---\n\n"
32
30
 
33
31
  def query_seperator(current_string):
34
32
  if current_string == "":
@@ -37,7 +35,8 @@ def query_seperator(current_string):
37
35
  return "&"
38
36
 
39
37
 
40
- "params are in the form of [(paramName, value), (param2Name, value)] if the value is not None, it will be added to the query string"
38
+ #("params are in the form of [(paramName, value), (param2Name, value)] if the value is not None, it will be added to "
39
+ # "the query string")
41
40
 
42
41
 
43
42
  def query_string(params):
@@ -52,6 +51,9 @@ def base_path(client, view_server: str):
52
51
  return f"{client.platform_url}/servers/{view_server}/api/open-metadata/metadata-explorer"
53
52
 
54
53
 
54
+
55
+
56
+
55
57
  class SolutionArchitect(Client):
56
58
  """SolutionArchitect is a class that extends the Client class. The Solution Architect OMVS provides APIs for
57
59
  searching for architectural elements such as information supply chains, solution blueprints, solution components
@@ -73,70 +75,556 @@ class SolutionArchitect(Client):
73
75
 
74
76
  """
75
77
 
76
- def __init__(
77
- self,
78
- view_server: str,
79
- platform_url: str,
80
- user_id: str = None,
81
- user_pwd: str = None,
82
- token: str = None,
83
- ):
78
+ def __init__(self, view_server: str, platform_url: str, user_id: str = None, user_pwd: str = None,
79
+ token: str = None, ):
84
80
  self.view_server = view_server
85
81
  self.platform_url = platform_url
86
82
  self.user_id = user_id
87
83
  self.user_pwd = user_pwd
88
- self.solution_architect_command_root: str = (
89
- f"{self.platform_url}/servers/{self.view_server}"
90
- f"/api/open-metadata/solution-architect"
91
- )
92
- Client.__init__(
93
- self,
94
- view_server,
95
- platform_url,
96
- user_id=user_id,
97
- user_pwd=user_pwd,
98
- token=token,
99
- )
84
+ self.solution_architect_command_root: str = (f"{self.platform_url}/servers/{self.view_server}"
85
+ f"/api/open-metadata/solution-architect")
86
+ Client.__init__(self, view_server, platform_url, user_id=user_id, user_pwd=user_pwd, token=token, )
100
87
 
101
88
  #
89
+ # Markdown output support
102
90
  #
103
- #
91
+ def generate_info_supply_chain_md(self, elements: list | dict, search_string: str,
92
+ output_format: str = 'MD', include_mermaid: bool = True
93
+ ) -> str:
94
+ """Generate markdown for information supply chains."""
95
+ elements_md, elements_action = self.make_preamble(obj_type="Information Supply Chain",
96
+ search_string=search_string,
97
+ output_format=output_format)
98
+ if isinstance(elements, dict):
99
+ elements = [elements]
100
+
101
+ for element in elements:
102
+ guid = element['elementHeader'].get("guid", None)
103
+ properties = element['properties']
104
+ qualified_name = properties.get("qualifiedName", None)
105
+ display_name = properties.get("displayName", None)
106
+ description = properties.get("description", None)
107
+ scope = properties.get("scope", None)
108
+ purposes = properties.get("purposes", [])
109
+ purpose_md = ""
110
+ if len(purposes) > 0:
111
+ for purpose in purposes:
112
+ purpose_md += f"* {purpose}\n"
113
+ mermaid = element.get('mermaidGraph', None)
114
+
115
+ if output_format in ['FORM', 'MD']:
116
+ elements_md += f"# {elements_action}\n\n"
117
+ elements_md += f"## Information Supply Chain Name \n\n{display_name}\n\n"
118
+
119
+ elif output_format == 'REPORT':
120
+ elements_md += f"# Information Supply Chain Name: {display_name}\n\n"
121
+ else:
122
+ elements_md += f"## Information Supply Chain Name \n\n{display_name}\n\n"
123
+
124
+ elements_md += self.make_md_attribute("description", description, output_format)
125
+ elements_md += self.make_md_attribute("scope", scope, output_format)
126
+ elements_md += self.make_md_attribute("purposes", purpose_md, output_format)
127
+
128
+ elements_md += self.make_md_attribute("qualified name", qualified_name, output_format)
129
+ elements_md += self.make_md_attribute("GUID", guid, output_format)
130
+ if include_mermaid and output_format == 'REPORT':
131
+ elements_md += f"\n```mermaid\n{mermaid}\n```\n"
132
+ elements_md += MD_SEPERATOR
133
+ return elements_md
134
+
135
+ def generate_solution_blueprint_md(self, elements: list | dict, search_string: str,
136
+ output_format: str = 'MD', include_mermaid: bool = True) -> str:
137
+ elements_md, elements_action = self.make_preamble(obj_type="Solution Blueprint", search_string=search_string,
138
+ output_format=output_format)
139
+ if isinstance(elements, dict):
140
+ elements = [elements]
141
+
142
+ for element in elements:
143
+ guid = element['elementHeader'].get("guid", None)
144
+ element_properties = element['properties']
145
+ display_name = element_properties.get("displayName", None)
146
+ description = element_properties.get("description", None)
147
+ version = element_properties.get("version", None)
148
+ qualified_name = element_properties.get("qualifiedName", None)
149
+
150
+ solution_components = element.get('solutionComponents', None)
151
+ solution_components_md = ""
152
+ if solution_components:
153
+ for solution_component in solution_components:
154
+ sol_comp_prop = solution_component['solutionComponent']['properties']
155
+ sol_comp_name = sol_comp_prop.get("displayName", None)
156
+ sol_comp_desc = sol_comp_prop.get("description", None)
157
+ solution_components_md += f"* {sol_comp_name}:\t {sol_comp_desc}\n"
158
+ bp_graph = element.get('mermaidGraph', None)
159
+
160
+ if output_format in ['FORM', 'MD']:
161
+ elements_md += f"# {elements_action}\n\n"
162
+ elements_md += f"## Blueprint Name \n\n{display_name}\n\n"
163
+ elif output_format == 'REPORT':
164
+ elements_md += f"# Blueprint Name: {display_name}\n\n"
165
+ else:
166
+ elements_md += f"## Blueprint Name \n\n{display_name}\n\n"
167
+
168
+ elements_md += self.make_md_attribute("description", description, output_format)
169
+ elements_md += self.make_md_attribute("version", version, output_format)
170
+ if output_format == 'REPORT':
171
+ elements_md += self.make_md_attribute("solution components", solution_components_md, output_format)
172
+ elements_md += self.make_md_attribute("qualified name", qualified_name, output_format)
173
+ elements_md += self.make_md_attribute("GUID", guid, output_format)
174
+ if include_mermaid and output_format == 'REPORT':
175
+ elements_md += f"\n```mermaid\n{bp_graph}\n```\n"
176
+ elements_md += MD_SEPERATOR
177
+
178
+ return elements_md
179
+
180
+ def generate_solution_roles_md(self, elements: list | dict, search_string: str,
181
+ output_format: str = 'MD', include_mermaid: bool = True) -> str:
182
+ elements_md, elements_action = self.make_preamble(obj_type="Categories", search_string=search_string,
183
+ output_format=output_format)
184
+ if isinstance(elements, dict):
185
+ elements = [elements]
186
+
187
+ for element in elements:
188
+ guid = element['elementHeader'].get("guid", None)
189
+ element_properties = element['properties']
190
+ display_name = element_properties.get("title", None)
191
+ role_id = element_properties.get("roleId", None)
192
+ scope = element_properties.get("scope", None)
193
+ description = element_properties.get("description", None)
194
+ domain_identifier = element_properties.get("domainIdentifier", None)
195
+ qualified_name = element_properties.get("qualifiedName", None)
196
+
197
+ solution_components = element.get('solutionComponents', None)
198
+ solution_components_md = ""
199
+ if solution_components:
200
+ for solution_component in solution_components:
201
+ sol_comp_prop = solution_component.get('relationshipProperties',None)
202
+ if sol_comp_prop:
203
+ sol_comp_name = sol_comp_prop.get("role", None)
204
+ sol_comp_desc = sol_comp_prop.get("description", None)
205
+ solution_components_md += f"* {sol_comp_name}:\t {sol_comp_desc}\n"
206
+ solution_roles_graph = element.get('mermaidGraph', None)
207
+
208
+ if output_format in ['FORM', 'MD']:
209
+ elements_md += f"# {elements_action}\n\n"
210
+ elements_md += f"## Blueprint Name \n\n{display_name}\n\n"
211
+ elif output_format == 'REPORT':
212
+ elements_md += f"# Blueprint Name: {display_name}\n\n"
213
+ else:
214
+ elements_md += f"## Blueprint Name \n\n{display_name}\n\n"
215
+ elements_md += self.make_md_attribute("role id", role_id, output_format)
216
+ elements_md += self.make_md_attribute("scope", scope, output_format)
217
+ elements_md += self.make_md_attribute("description", description, output_format)
218
+ elements_md += self.make_md_attribute("domain identifier", domain_identifier, output_format)
219
+ if output_format == 'REPORT':
220
+ elements_md += self.make_md_attribute("solution components", solution_components_md, output_format)
221
+ elements_md += self.make_md_attribute("qualified name", qualified_name, output_format)
222
+ elements_md += self.make_md_attribute("GUID", guid, output_format)
223
+ if include_mermaid and output_format == 'REPORT':
224
+ elements_md += f"\n```mermaid\n{solution_roles_graph}\n```\n"
225
+ elements_md += MD_SEPERATOR
226
+
227
+ return elements_md
228
+
229
+ def generate_solution_components_md(self, elements: list | dict, search_string: str,
230
+ output_format: str = 'MD', include_mermaid: bool = True) -> str:
231
+ """
232
+ Generates a Markdown (MD) or formatted document representation for solution components.
233
+
234
+ Given a set of elements representing solution components (either as a list or a dictionary),
235
+ this function generates a detailed output string compliant with a specified format. The
236
+ resulting output includes various attributes of the solution components, such as their
237
+ names, descriptions, types, and related information like blueprints, parents, and extended
238
+ properties. Optionally, it can include Mermaid graphs for further visualization when needed.
239
+
240
+ Args:
241
+ elements (list | dict): A collection of elements, each representing a solution component.
242
+ Elements can be provided as a list of dictionaries or a single dictionary. Each
243
+ dictionary should contain the required keys, including "elementHeader" and "glossaryCategoryProperties".
244
+ search_string (str): A string to be used for preamble generation or context identification.
245
+ output_format (str, optional): The format of the resulting output string. Defaults to 'MD'.
246
+ Valid values include 'MD', 'FORM', and 'REPORT'.
247
+ include_mermaid (bool, optional): Determines whether Mermaid graphs should be included
248
+ in the output. Defaults to True.
249
+
250
+ Returns:
251
+ str: A string containing the formatted details of solution components in the specified format.
252
+ """
253
+ elements_md, elements_action = self.make_preamble(obj_type="Categories", search_string=search_string,
254
+ output_format=output_format)
255
+
256
+ if isinstance(elements, dict):
257
+ elements = [elements]
258
+
259
+ for element in elements:
260
+ guid = element['elementHeader'].get("guid", None)
261
+ properties = element['glossaryCategoryProperties']
262
+ display_name = properties.get("displayName", None)
263
+ description = properties.get("description", None)
264
+ version = properties.get("version", None)
265
+ component_type = properties.get("solutionComponentType", None)
266
+ qualified_name = properties.get("qualifiedName", None)
267
+
268
+ extended_props = properties.get("extendedProperties", None)
269
+ extended_props_md = ""
270
+ if extended_props:
271
+ for key in extended_props.keys():
272
+ extended_props_md += f"* {key}:\t {extended_props[key]}\n"
273
+
274
+ blueprints_md = ""
275
+ blueprints = element.get('blueprints', None)
276
+ if blueprints:
277
+ for blueprint in blueprints:
278
+ bp_q_name = blueprint["relatedElement"]['properties']['qualifiedName']
279
+ blueprints_md += f"* {bp_q_name}\n"
280
+
281
+ parent_comp_md = ""
282
+ context = element["context"]
283
+ if context:
284
+ for parent in context:
285
+ parent_comp_md += f"* {parent['name']}\n"
286
+ # Todo - This is incomplete - discuss with Mandy
287
+ comp_graph = element.get('mermaidGraph', None)
288
+
289
+ if output_format in ['FORM', 'MD']:
290
+ elements_md += f"# {elements_action}\n\n"
291
+ elements_md += f"## Solution Component Name \n\n{display_name}\n\n"
292
+
293
+ elif output_format == 'REPORT':
294
+ elements_md += f"# Solution Component Name: {display_name}\n\n"
295
+ else:
296
+ elements_md += f"## Solution Component Name \n\n{display_name}\n\n"
297
+
298
+ elements_md += self.make_md_attribute("description", description, output_format)
299
+ elements_md += self.make_md_attribute("component type", component_type, output_format)
300
+ elements_md += self.make_md_attribute("version", version, output_format)
301
+ elements_md += self.make_md_attribute("qualified name/GUID", f"{qualified_name}\n---\n{guid}", output_format)
302
+ elements_md += self.make_md_attribute("blueprints", blueprints_md, output_format)
303
+ elements_md += self.make_md_attribute("parent components", parent_comp_md, output_format)
304
+ elements_md += self.make_md_attribute("extended properties", extended_props_md, output_format)
305
+ if include_mermaid and output_format == 'REPORT':
306
+ elements_md += f"\n```mermaid\n{comp_graph}\n```\n"
307
+ elements_md += MD_SEPERATOR
308
+
309
+ return elements_md
310
+
311
+ async def _async_create_info_supply_chain(self, body: dict) -> str:
312
+ """Create an information supply. Async version.
104
313
 
105
- async def _async_find_information_supply_chains(
106
- self,
107
- filter: str = "*",
108
- add_implementation: bool = True,
109
- starts_with: bool = True,
110
- ends_with: bool = False,
111
- ignore_case: bool = False,
112
- start_from: int = 0,
113
- page_size: int = max_paging_size,
114
- body: dict = None,
115
- ) -> list[dict] | str:
116
- """Retrieve the list of information supply chain metadata elements that contain the search string.
117
- https://egeria-project.org/concepts/information-supply-chain
118
- Async version.
314
+ Parameters
315
+ ----------
316
+ body: dict
317
+ A dictionary containing the definition of the supply chain to create.
318
+
319
+ Returns
320
+ -------
321
+
322
+ str - guid of the supply chain created.
323
+
324
+ Raises
325
+ ------
326
+ Raises
327
+ ------
328
+ InvalidParameterException
329
+ one of the parameters is null or invalid or
330
+ PropertyServerException
331
+ There is a problem adding the element properties to the metadata repository or
332
+ UserNotAuthorizedException
333
+ the requesting user is not authorized to issue this request.
334
+
335
+ Notes
336
+ ----
337
+
338
+ Body structure:
339
+ {
340
+ "class" : "NewInformationSupplyChainRequestBody",
341
+ "externalSourceGUID": "add guid here",
342
+ "externalSourceName": "add qualified name here",
343
+ "effectiveTime" : {{isotime}},
344
+ "forLineage" : false,
345
+ "forDuplicateProcessing" : false,
346
+ "anchorGUID" : "add guid here",
347
+ "isOwnAnchor": false,
348
+ "parentGUID": "add guid here",
349
+ "parentRelationshipTypeName": "add type name here",
350
+ "parentRelationshipProperties": {
351
+ "class": "ElementProperties",
352
+ "propertyValueMap" : {
353
+ "description" : {
354
+ "class": "PrimitiveTypePropertyValue",
355
+ "typeName": "string",
356
+ "primitiveValue" : "New description"
357
+ }
358
+ }
359
+ },
360
+ "parentAtEnd1": false,
361
+ "properties": {
362
+ "qualifiedName": "add unique name here",
363
+ "displayName": "add short name here",
364
+ "description": "add description here",
365
+ "scope": "add scope of this information supply chain's applicability.",
366
+ "purposes": ["purpose1", "purpose2"],
367
+ "additionalProperties": {
368
+ "property1" : "propertyValue1",
369
+ "property2" : "propertyValue2"
370
+ },
371
+ "effectiveFrom": {{isotime}},
372
+ "effectiveTo": {{isotime}}
373
+ }
374
+ }
375
+
376
+ """
377
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
378
+ f"information-supply-chains")
379
+
380
+ response = await self._async_make_request("POST", url, body_slimmer(body))
381
+
382
+ return response.json().get("guid", "Supply Chain not created")
383
+
384
+ def create_info_supply_chain(self, body: dict) -> str:
385
+ """Create an information supply.
119
386
 
120
387
  Parameters
121
388
  ----------
122
- filter : str
123
- - search_filter string to search for.
124
- add_implementation : bool, [default=True], optional
125
- - add_implementation flag to include information supply chain implementations details..
126
- starts_with : bool, [default=False], optional
127
- Starts with the supplied string.
128
- ends_with : bool, [default=False], optional
129
- Ends with the supplied string
130
- ignore_case : bool, [default=False], optional
131
- Ignore case when searching
132
- body: dict, optional, default = None
133
- - additional optional specifications for the search.
389
+ body: dict
390
+ A dictionary containing the definition of the supply chain to create.
134
391
 
135
392
  Returns
136
393
  -------
137
- list[dict] | str
138
- A list of information supply chain structures or a string if there are no elements found.
139
394
 
395
+ str - guid of the supply chain created.
396
+
397
+ Raises
398
+ ------
399
+ Raises
400
+ ------
401
+ InvalidParameterException
402
+ one of the parameters is null or invalid or
403
+ PropertyServerException
404
+ There is a problem adding the element properties to the metadata repository or
405
+ UserNotAuthorizedException
406
+ the requesting user is not authorized to issue this request.
407
+
408
+ Notes
409
+ ----
410
+
411
+ Body structure:
412
+ {
413
+ "class" : "NewInformationSupplyChainRequestBody",
414
+ "externalSourceGUID": "add guid here",
415
+ "externalSourceName": "add qualified name here",
416
+ "effectiveTime" : {{isotime}},
417
+ "forLineage" : false,
418
+ "forDuplicateProcessing" : false,
419
+ "anchorGUID" : "add guid here",
420
+ "isOwnAnchor": false,
421
+ "parentGUID": "add guid here",
422
+ "parentRelationshipTypeName": "add type name here",
423
+ "parentRelationshipProperties": {
424
+ "class": "ElementProperties",
425
+ "propertyValueMap" : {
426
+ "description" : {
427
+ "class": "PrimitiveTypePropertyValue",
428
+ "typeName": "string",
429
+ "primitiveValue" : "New description"
430
+ }
431
+ }
432
+ },
433
+ "parentAtEnd1": false,
434
+ "properties": {
435
+ "qualifiedName": "add unique name here",
436
+ "displayName": "add short name here",
437
+ "description": "add description here",
438
+ "scope": "add scope of this information supply chain's applicability.",
439
+ "purposes": ["purpose1", "purpose2"],
440
+ "additionalProperties": {
441
+ "property1" : "propertyValue1",
442
+ "property2" : "propertyValue2"
443
+ },
444
+ "effectiveFrom": {{isotime}},
445
+ "effectiveTo": {{isotime}}
446
+ }
447
+ }
448
+
449
+ """
450
+
451
+ loop = asyncio.get_event_loop()
452
+ response = loop.run_until_complete(self._async_create_info_supply_chain(body))
453
+ return response
454
+
455
+ async def _async_create_info_supply_chain_from_template(self, body: dict) -> str:
456
+ """ Create a new metadata element to represent an information supply chain using an existing metadata element
457
+ as a template. The template defines additional classifications and relationships that should be added to
458
+ the new element. Async Version.
459
+
460
+
461
+ Parameters
462
+ ----------
463
+ body: dict
464
+ A dictionary containing the definition of the supply chain to create.
465
+
466
+ Returns
467
+ -------
468
+
469
+ str - guid of the supply chain created.
470
+
471
+ Raises
472
+ ------
473
+ Raises
474
+ ------
475
+ InvalidParameterException
476
+ one of the parameters is null or invalid or
477
+ PropertyServerException
478
+ There is a problem adding the element properties to the metadata repository or
479
+ UserNotAuthorizedException
480
+ the requesting user is not authorized to issue this request.
481
+
482
+ Notes
483
+ ----
484
+
485
+ Body structure:
486
+ {
487
+ "class" : "TemplateRequestBody",
488
+ "externalSourceGUID": "add guid here",
489
+ "externalSourceName": "add qualified name here",
490
+ "effectiveTime" : {{isotime}},
491
+ "forLineage" : false,
492
+ "forDuplicateProcessing" : false,
493
+ "anchorGUID" : "add guid here",
494
+ "isOwnAnchor": false,
495
+ "parentGUID": "add guid here",
496
+ "parentRelationshipTypeName": "add type name here",
497
+ "parentRelationshipProperties": {
498
+ "class": "ElementProperties",
499
+ "propertyValueMap" : {
500
+ "description" : {
501
+ "class": "PrimitiveTypePropertyValue",
502
+ "typeName": "string",
503
+ "primitiveValue" : "New description"
504
+ }
505
+ }
506
+ },
507
+ "parentAtEnd1": false,
508
+ "templateGUID": "add guid here",
509
+ "replacementProperties": {
510
+ "class": "ElementProperties",
511
+ "propertyValueMap" : {
512
+ "description" : {
513
+ "class": "PrimitiveTypePropertyValue",
514
+ "typeName": "string",
515
+ "primitiveValue" : "New description"
516
+ }
517
+ }
518
+ },
519
+ "placeholderPropertyValues": {
520
+ "placeholder1" : "propertyValue1",
521
+ "placeholder2" : "propertyValue2"
522
+ }
523
+ }
524
+
525
+ """
526
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
527
+ f"information-supply-chains/from-template")
528
+
529
+ response = await self._async_make_request("POST", url, body_slimmer(body))
530
+
531
+ return response.json().get("guid", "Supply Chain not created")
532
+
533
+ def create_info_supply_chain_from_template(self, body: dict) -> str:
534
+ """ Create a new metadata element to represent an information supply chain using an existing metadata element
535
+ as a template. The template defines additional classifications and relationships that should be added to
536
+ the new element.
537
+
538
+ Parameters
539
+ ----------
540
+ body: dict
541
+ A dictionary containing the definition of the supply chain to create.
542
+
543
+ Returns
544
+ -------
545
+
546
+ str - guid of the supply chain created.
547
+
548
+ Raises
549
+ ------
550
+ Raises
551
+ ------
552
+ InvalidParameterException
553
+ one of the parameters is null or invalid or
554
+ PropertyServerException
555
+ There is a problem adding the element properties to the metadata repository or
556
+ UserNotAuthorizedException
557
+ the requesting user is not authorized to issue this request.
558
+
559
+ Notes
560
+ ----
561
+
562
+ Body structure:
563
+ {
564
+ "class" : "TemplateRequestBody",
565
+ "externalSourceGUID": "add guid here",
566
+ "externalSourceName": "add qualified name here",
567
+ "effectiveTime" : {{isotime}},
568
+ "forLineage" : false,
569
+ "forDuplicateProcessing" : false,
570
+ "anchorGUID" : "add guid here",
571
+ "isOwnAnchor": false,
572
+ "parentGUID": "add guid here",
573
+ "parentRelationshipTypeName": "add type name here",
574
+ "parentRelationshipProperties": {
575
+ "class": "ElementProperties",
576
+ "propertyValueMap" : {
577
+ "description" : {
578
+ "class": "PrimitiveTypePropertyValue",
579
+ "typeName": "string",
580
+ "primitiveValue" : "New description"
581
+ }
582
+ }
583
+ },
584
+ "parentAtEnd1": false,
585
+ "templateGUID": "add guid here",
586
+ "replacementProperties": {
587
+ "class": "ElementProperties",
588
+ "propertyValueMap" : {
589
+ "description" : {
590
+ "class": "PrimitiveTypePropertyValue",
591
+ "typeName": "string",
592
+ "primitiveValue" : "New description"
593
+ }
594
+ }
595
+ },
596
+ "placeholderPropertyValues": {
597
+ "placeholder1" : "propertyValue1",
598
+ "placeholder2" : "propertyValue2"
599
+ }
600
+ }
601
+
602
+ """
603
+
604
+ loop = asyncio.get_event_loop()
605
+ response = loop.run_until_complete(self._async_create_info_supply_chain_from_template(body))
606
+ return response
607
+
608
+ async def _async_update_info_supply_chain(self, guid: str, body: dict,
609
+ replace_all_properties: bool = False) -> None:
610
+ """ Update the properties of an information supply chain. Async Version.
611
+
612
+ Parameters
613
+ ----------
614
+ guid: str
615
+ guid of the information supply chain to update.
616
+ body: dict
617
+ A dictionary containing the updates to the supply chain.
618
+ replace_all_properties: bool, optional
619
+ Whether to replace all properties with those provided in the body or to merge with existing properties.
620
+
621
+ Returns
622
+ -------
623
+
624
+ None
625
+
626
+ Raises
627
+ ------
140
628
  Raises
141
629
  ------
142
630
  InvalidParameterException
@@ -145,18 +633,434 @@ class SolutionArchitect(Client):
145
633
  There is a problem adding the element properties to the metadata repository or
146
634
  UserNotAuthorizedException
147
635
  the requesting user is not authorized to issue this request.
636
+
637
+ Notes
638
+ ----
639
+
640
+ Body structure:
641
+ {
642
+ "class" : "UpdateInformationSupplyChainRequestBody",
643
+ "externalSourceGUID": "add guid here",
644
+ "externalSourceName": "add qualified name here",
645
+ "effectiveTime" : {{isotime}},
646
+ "forLineage" : false,
647
+ "forDuplicateProcessing" : false,
648
+ "properties": {
649
+ "qualifiedName": "add unique name here",
650
+ "displayName": "add short name here",
651
+ "description": "add description here",
652
+ "scope": "add scope of this information supply chain's applicability.",
653
+ "purposes": ["purpose1", "purpose2"],
654
+ "additionalProperties": {
655
+ "property1" : "propertyValue1",
656
+ "property2" : "propertyValue2"
657
+ },
658
+ "effectiveFrom": {{isotime}},
659
+ "effectiveTo": {{isotime}}
660
+ }
661
+ }
148
662
  """
663
+ validate_guid(guid)
664
+ replace_all_properties_s = str(replace_all_properties).lower()
665
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
666
+ f"information-supply-chains/{guid}/update?replaceAllProperties={replace_all_properties_s}")
667
+
668
+ await self._async_make_request("POST", url, body_slimmer(body))
669
+
670
+ def update_info_supply_chain(self, guid: str, body: dict, replace_all_properties: bool = False) -> None:
671
+ """ Update the properties of an information supply chain. Async Version.
672
+
673
+ Parameters
674
+ ----------
675
+ guid: str
676
+ guid of the information supply chain to update.
677
+ body: dict
678
+ A dictionary containing the updates to the supply chain.
679
+ replace_all_properties: bool, optional
680
+ Whether to replace all properties with those provided in the body or to merge with existing properties.
681
+
682
+ Returns
683
+ -------
684
+
685
+ None
686
+
687
+ Raises
688
+ ------
689
+ Raises
690
+ ------
691
+ InvalidParameterException
692
+ one of the parameters is null or invalid or
693
+ PropertyServerException
694
+ There is a problem adding the element properties to the metadata repository or
695
+ UserNotAuthorizedException
696
+ the requesting user is not authorized to issue this request.
697
+
698
+ Notes
699
+ ----
700
+
701
+ Body structure:
702
+ {
703
+ "class" : "UpdateInformationSupplyChainRequestBody",
704
+ "externalSourceGUID": "add guid here",
705
+ "externalSourceName": "add qualified name here",
706
+ "effectiveTime" : {{isotime}},
707
+ "forLineage" : false,
708
+ "forDuplicateProcessing" : false,
709
+ "properties": {
710
+ "qualifiedName": "add unique name here",
711
+ "displayName": "add short name here",
712
+ "description": "add description here",
713
+ "scope": "add scope of this information supply chain's applicability.",
714
+ "purposes": ["purpose1", "purpose2"],
715
+ "additionalProperties": {
716
+ "property1" : "propertyValue1",
717
+ "property2" : "propertyValue2"
718
+ },
719
+ "effectiveFrom": {{isotime}},
720
+ "effectiveTo": {{isotime}}
721
+ }
722
+ }
723
+ """
724
+ loop = asyncio.get_event_loop()
725
+ loop.run_until_complete(self._async_update_info_supply_chain(guid, body, replace_all_properties))
726
+
727
+ async def _async_delete_info_supply_chain(self, guid: str, body: dict = None) -> None:
728
+ """Delete an information supply chain. Async Version.
729
+
730
+ Parameters
731
+ ----------
732
+ guid: str
733
+ guid of the information supply chain to delete.
734
+ body: dict, optional
735
+ A dictionary containing parameters of the deletion.
736
+
737
+ Returns
738
+ -------
739
+ None
740
+
741
+ Raises
742
+ ------
743
+ Raises
744
+ ------
745
+ InvalidParameterException
746
+ one of the parameters is null or invalid or
747
+ PropertyServerException
748
+ There is a problem adding the element properties to the metadata repository or
749
+ UserNotAuthorizedException
750
+ the requesting user is not authorized to issue this request.
751
+
752
+ Notes
753
+ ----
754
+
755
+ Body structure:
756
+ {
757
+ "class" : "MetadataSourceRequestBody",
758
+ "externalSourceGUID": "add guid here",
759
+ "externalSourceName": "add qualified name here",
760
+ "effectiveTime" : {{isotime}},
761
+ "forLineage" : false,
762
+ "forDuplicateProcessing" : false
763
+ }
764
+ """
765
+ validate_guid(guid)
766
+
767
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
768
+ f"information-supply-chains/{guid}/delete")
769
+
770
+ await self._async_make_request("POST", url, body_slimmer(body))
771
+
772
+ def delete_info_supply_chain(self, guid: str, body: dict = None) -> None:
773
+ """ Delete an information supply chain.
774
+
775
+ Parameters
776
+ ----------
777
+ guid: str
778
+ guid of the information supply chain to delete.
779
+ body: dict, optional
780
+ A dictionary containing parameters of the deletion.
781
+
782
+ Returns
783
+ -------
784
+ None
785
+
786
+ Raises
787
+ ------
788
+ InvalidParameterException
789
+ one of the parameters is null or invalid or
790
+ PropertyServerException
791
+ There is a problem adding the element properties to the metadata repository or
792
+ UserNotAuthorizedException
793
+ the requesting user is not authorized to issue this request.
794
+
795
+ Notes
796
+ ----
797
+
798
+ Body structure:
799
+ {
800
+ "class" : "MetadataSourceRequestBody",
801
+ "externalSourceGUID": "add guid here",
802
+ "externalSourceName": "add qualified name here",
803
+ "effectiveTime" : {{isotime}},
804
+ "forLineage" : false,
805
+ "forDuplicateProcessing" : false
806
+ }
807
+ """
808
+ loop = asyncio.get_event_loop()
809
+ loop.run_until_complete(self._async_delete_info_supply_chain(guid, body))
810
+
811
+ async def _async_get_info_supply_chain_by_guid(self, guid: str, body: dict = None,
812
+ add_implementation: bool = True) -> dict | str:
813
+ """Return the properties of a specific information supply chain. Async Version.
814
+
815
+ Parameters
816
+ ----------
817
+ guid: str
818
+ guid of the information supply chain to retrieve.
819
+ body: dict, optional
820
+ A dictionary containing parameters of the retrieval.
821
+ add_implementation: bool, optional
822
+ Whether to add the implementation details to the response.
823
+
824
+ Returns
825
+ -------
826
+ None
827
+
828
+ Raises
829
+ ------
830
+ InvalidParameterException
831
+ one of the parameters is null or invalid or
832
+ PropertyServerException
833
+ There is a problem adding the element properties to the metadata repository or
834
+ UserNotAuthorizedException
835
+ the requesting user is not authorized to issue this request.
836
+
837
+ Notes
838
+ -----
839
+ Body structure:
840
+ {
841
+ "class" : "AnyTimeRequestBody",
842
+ "asOfTime" : {{isotime}},
843
+ "effectiveTime" : {{isotime}},
844
+ "forLineage" : false,
845
+ "forDuplicateProcessing" : false
846
+ }
149
847
 
848
+ """
849
+ validate_guid(guid)
850
+ add_impl = str(add_implementation).lower()
851
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
852
+ f"information-supply-chains/{guid}/retrieve?addImplementation={add_impl}")
853
+
854
+ if body is None:
855
+ response = await self._async_make_request("POST", url)
856
+ else:
857
+ response = await self._async_make_request("POST", url, body_slimmer(body))
858
+ return response.json().get("element", NO_ELEMENTS_FOUND)
859
+
860
+ def get_info_supply_chain_by_guid(self, guid: str, body: dict = None,
861
+ add_implementation: bool = True) -> dict | str:
862
+ """ Return the properties of a specific information supply chain.
863
+
864
+ Parameters
865
+ ----------
866
+ guid: str
867
+ guid of the information supply chain to retrieve.
868
+ body: dict, optional
869
+ A dictionary containing parameters of the retrieval.
870
+ add_implementation: bool, optional
871
+ Whether to add the implementation details to the response.
872
+
873
+ Returns
874
+ -------
875
+ None
876
+
877
+ Raises
878
+ ------
879
+ InvalidParameterException
880
+ one of the parameters is null or invalid or
881
+ PropertyServerException
882
+ There is a problem adding the element properties to the metadata repository or
883
+ UserNotAuthorizedException
884
+ the requesting user is not authorized to issue this request.
885
+
886
+ Notes
887
+ -----
888
+ Body structure:
889
+ {
890
+ "class" : "AnyTimeRequestBody",
891
+ "asOfTime" : {{isotime}},
892
+ "effectiveTime" : {{isotime}},
893
+ "forLineage" : false,
894
+ "forDuplicateProcessing" : false
895
+ }
896
+
897
+ """
898
+ loop = asyncio.get_event_loop()
899
+ response = loop.run_until_complete(self._async_get_info_supply_chain_by_guid(guid, body, add_implementation))
900
+ return response
901
+
902
+ async def _async_get_info_supply_chain_by_name(self, search_filter: str, body: dict = None,
903
+ add_implementation: bool = True, start_from: int = 0,
904
+ page_size: int = max_paging_size) -> dict | str:
905
+ """ Returns the list of information supply chains with a particular name. Async Version.
906
+
907
+ Parameters
908
+ ----------
909
+ search_filter: str
910
+ name of the information supply chain to retrieve.
911
+ body: dict, optional
912
+ A dictionary containing parameters of the retrieval.
913
+ add_implementation: bool, optional
914
+ Whether to add the implementation details to the response.
915
+
916
+ Returns
917
+ -------
918
+ [dict] | str
919
+ A list of information supply chains matching the name.
920
+
921
+ Raises
922
+ ------
923
+ InvalidParameterException
924
+ one of the parameters is null or invalid or
925
+ PropertyServerException
926
+ There is a problem adding the element properties to the metadata repository or
927
+ UserNotAuthorizedException
928
+ the requesting user is not authorized to issue this request.
929
+
930
+ Notes
931
+ -----
932
+ Body structure:
933
+ {
934
+ "class" : "FilterRequestBody",
935
+ "asOfTime" : {{isotime}},
936
+ "effectiveTime" : {{isotime}},
937
+ "forLineage" : false,
938
+ "forDuplicateProcessing" : false,
939
+ "limitResultsByStatus" : ["ACTIVE"],
940
+ "sequencingOrder" : "PROPERTY_ASCENDING",
941
+ "sequencingProperty" : "qualifiedName",
942
+ "filter" : "Add name here"
943
+ }
944
+
945
+ """
946
+ add_impl = str(add_implementation).lower()
150
947
  possible_query_params = query_string(
151
- [
152
- ("addImplementation", add_implementation),
153
- ("startFrom", start_from),
154
- ("pageSize", page_size),
155
- ("startsWith", starts_with),
156
- ("endsWith", ends_with),
157
- ("ignoreCase", ignore_case),
158
- ]
159
- )
948
+ [("addImplementation", add_impl), ("startFrom", start_from), ("pageSize", page_size)])
949
+
950
+ if body is None:
951
+ body = {
952
+ "filter": search_filter,
953
+ }
954
+ else:
955
+ body["filter"] = search_filter
956
+
957
+ url = (f"{self.solution_architect_command_root}/information-supply-chains/by-name"
958
+ f"{possible_query_params}")
959
+ response: Response = await self._async_make_request("POST", url, body_slimmer(body))
960
+ return response.json().get("elements", NO_ELEMENTS_FOUND)
961
+
962
+ def get_info_supply_chain_by_name(self, search_filter: str, body: dict = None, add_implementation: bool = True,
963
+ start_from: int = 0, page_size: int = max_paging_size) -> dict | str:
964
+ """ Returns the list of information supply chains with a particular name. Async Version.
965
+
966
+ Parameters
967
+ ----------
968
+ search_filter: str
969
+ name of the information supply chain to retrieve.
970
+ body: dict, optional
971
+ A dictionary containing parameters of the retrieval.
972
+ add_implementation: bool, optional
973
+ Whether to add the implementation details to the response.
974
+ start_from: int, [default=0], optional
975
+ When multiple pages of results are available, the page number to start from.
976
+ page_size: int, [default=max_paging_size], optional
977
+ The number of items to return in a single page. If not specified, the default will be taken from
978
+ the class instance.
979
+
980
+ Returns
981
+ -------
982
+ [dict] | str
983
+ A list of information supply chains matching the name.
984
+
985
+ Raises
986
+ ------
987
+ InvalidParameterException
988
+ one of the parameters is null or invalid or
989
+ PropertyServerException
990
+ There is a problem adding the element properties to the metadata repository or
991
+ UserNotAuthorizedException
992
+ the requesting user is not authorized to issue this request.
993
+
994
+ Notes
995
+ -----
996
+ Body structure:
997
+ {
998
+ "class" : "FilterRequestBody",
999
+ "asOfTime" : {{isotime}},
1000
+ "effectiveTime" : {{isotime}},
1001
+ "forLineage" : false,
1002
+ "forDuplicateProcessing" : false,
1003
+ "limitResultsByStatus" : ["ACTIVE"],
1004
+ "sequencingOrder" : "PROPERTY_ASCENDING",
1005
+ "sequencingProperty" : "qualifiedName",
1006
+ "filter" : "Add name here"
1007
+ }
1008
+
1009
+ """
1010
+ loop = asyncio.get_event_loop()
1011
+ response = loop.run_until_complete(
1012
+ self._async_get_info_supply_chain_by_name(search_filter, body, add_implementation, start_from, page_size))
1013
+ return response
1014
+
1015
+ async def _async_find_information_supply_chains(self, filter: str = "*", add_implementation: bool = True,
1016
+ starts_with: bool = True, ends_with: bool = False, ignore_case: bool = False, start_from: int = 0,
1017
+ page_size: int = max_paging_size, body: dict = None,
1018
+ output_format: str = 'JSON', include_mermaid: bool = False ) -> list[dict] | str:
1019
+ """Retrieve the list of information supply chain metadata elements that contain the search string.
1020
+ https://egeria-project.org/concepts/information-supply-chain
1021
+ Async version.
1022
+
1023
+ Parameters
1024
+ ----------
1025
+ filter : str
1026
+ - search_filter string to search for.
1027
+ add_implementation : bool, [default=True], optional
1028
+ - add_implementation flag to include information supply chain implementations details..
1029
+ starts_with : bool, [default=False], optional
1030
+ Starts with the supplied string.
1031
+ ends_with : bool, [default=False], optional
1032
+ Ends with the supplied string
1033
+ ignore_case : bool, [default=False], optional
1034
+ Ignore case when searching
1035
+ body: dict, optional, default = None
1036
+ - additional optional specifications for the search.
1037
+ output_format: str, default = 'JSON'
1038
+ Type of output to produce:
1039
+ JSON - output standard json
1040
+ MD - output standard markdown with no preamble
1041
+ FORM - output markdown with a preamble for a form
1042
+ REPORT - output markdown with a preamble for a report
1043
+ include_mermaid: bool, default = False
1044
+ Include mermaid diagrams?
1045
+
1046
+ Returns
1047
+ -------
1048
+ list[dict] | str
1049
+ A list of information supply chain structures or a string if there are no elements found.
1050
+
1051
+ Raises
1052
+ ------
1053
+ InvalidParameterException
1054
+ one of the parameters is null or invalid or
1055
+ PropertyServerException
1056
+ There is a problem adding the element properties to the metadata repository or
1057
+ UserNotAuthorizedException
1058
+ the requesting user is not authorized to issue this request.
1059
+ """
1060
+
1061
+ possible_query_params = query_string(
1062
+ [("addImplementation", add_implementation), ("startFrom", start_from), ("pageSize", page_size),
1063
+ ("startsWith", starts_with), ("endsWith", ends_with), ("ignoreCase", ignore_case), ])
160
1064
 
161
1065
  if filter is None or filter == "*":
162
1066
  search_filter = None
@@ -166,30 +1070,24 @@ class SolutionArchitect(Client):
166
1070
  if body is None:
167
1071
  body = {
168
1072
  "filter": search_filter,
169
- }
1073
+ }
170
1074
  else:
171
1075
  body["filter"] = search_filter
172
1076
 
173
- url = (
174
- f"{self.solution_architect_command_root}/information-supply-chains/by-search-string"
175
- f"{possible_query_params}"
176
- )
177
- response: Response = await self._async_make_request(
178
- "POST", url, body_slimmer(body)
179
- )
1077
+ url = (f"{self.solution_architect_command_root}/information-supply-chains/by-search-string"
1078
+ f"{possible_query_params}")
1079
+
1080
+ response: Response = await self._async_make_request("POST", url, body_slimmer(body))
1081
+ element = response.json().get("elements", NO_ELEMENTS_FOUND)
1082
+ if element == NO_ELEMENTS_FOUND:
1083
+ return NO_ELEMENTS_FOUND
1084
+ if output_format != 'JSON': # return a simplified markdown representation
1085
+ return self.generate_info_supply_chain_md(element, filter, output_format, include_mermaid)
180
1086
  return response.json().get("elements", NO_ELEMENTS_FOUND)
181
1087
 
182
- def find_information_supply_chains(
183
- self,
184
- filter: str = "*",
185
- add_implementation: bool = True,
186
- starts_with: bool = True,
187
- ends_with: bool = False,
188
- ignore_case: bool = False,
189
- start_from: int = 0,
190
- page_size: int = max_paging_size,
191
- body: dict = None,
192
- ) -> list[dict] | str:
1088
+ def find_information_supply_chains(self, filter: str = "*", add_implementation: bool = True, starts_with: bool = True,
1089
+ ends_with: bool = False, ignore_case: bool = False, start_from: int = 0, page_size: int = max_paging_size,
1090
+ body: dict = None, output_format: str = 'JSON', include_mermaid: bool = False ) -> list[dict] | str:
193
1091
  """Retrieve the list of information supply chain metadata elements that contain the search string.
194
1092
  https://egeria-project.org/concepts/information-supply-chain
195
1093
 
@@ -205,6 +1103,11 @@ class SolutionArchitect(Client):
205
1103
  Ends with the supplied string
206
1104
  ignore_case : bool, [default=False], optional
207
1105
  Ignore case when searching
1106
+ start_from: int, [default=0], optional
1107
+ When multiple pages of results are available, the page number to start from.
1108
+ page_size: int, [default=max_paging_size], optional
1109
+ The number of items to return in a single page. If not specified, the default will be taken from
1110
+ the class instance.
208
1111
  body: dict, optional, default = None
209
1112
  - additional optional specifications for the search.
210
1113
 
@@ -225,40 +1128,573 @@ class SolutionArchitect(Client):
225
1128
 
226
1129
  loop = asyncio.get_event_loop()
227
1130
  response = loop.run_until_complete(
228
- self._async_find_information_supply_chains(
229
- filter,
230
- add_implementation,
231
- starts_with,
232
- ends_with,
233
- ignore_case,
234
- start_from,
235
- page_size,
236
- body,
237
- )
238
- )
1131
+ self._async_find_information_supply_chains(filter, add_implementation, starts_with, ends_with, ignore_case,
1132
+ start_from, page_size, body, output_format, include_mermaid ))
239
1133
  return response
240
1134
 
241
- def find_all_information_supply_chains(
242
- self, start_from: int = 0, page_size: int = max_paging_size
243
- ) -> list[dict] | str:
1135
+
1136
+ def find_all_information_supply_chains(self, start_from: int = 0, page_size: int = max_paging_size) -> list[dict] | str:
244
1137
  """Retrieve a list of all information supply chains
245
1138
  https://egeria-project.org/concepts/information-supply-chain
246
1139
  """
247
1140
 
248
- return self.find_information_supply_chains(
249
- "*", start_from=start_from, page_size=page_size
250
- )
251
-
252
- async def _async_find_solution_blueprints(
253
- self,
254
- filter: str = "*",
255
- starts_with: bool = True,
256
- ends_with: bool = False,
257
- ignore_case: bool = False,
258
- start_from: int = 0,
259
- page_size: int = max_paging_size,
260
- body: dict = None,
261
- ) -> list[dict] | str:
1141
+ return self.find_information_supply_chains("*", start_from=start_from, page_size=page_size)
1142
+
1143
+
1144
+ #
1145
+ # Segments
1146
+ #
1147
+ async def _async_create_info_supply_chain_segment(self, guid: str, body: dict) -> str:
1148
+ """Create an information supply chain segment and link it to its owning information supply chain.
1149
+ Async version.
1150
+
1151
+ Parameters
1152
+ ----------
1153
+ guid: str
1154
+ guid of the owning information supply chain.
1155
+ body: dict
1156
+ A dictionary containing the definition of the supply chain to create.
1157
+
1158
+ Returns
1159
+ -------
1160
+
1161
+ str - guid of the supply chain segment created.
1162
+
1163
+ Raises
1164
+ ------
1165
+ Raises
1166
+ ------
1167
+ InvalidParameterException
1168
+ one of the parameters is null or invalid or
1169
+ PropertyServerException
1170
+ There is a problem adding the element properties to the metadata repository or
1171
+ UserNotAuthorizedException
1172
+ the requesting user is not authorized to issue this request.
1173
+
1174
+ Notes
1175
+ ----
1176
+
1177
+ Body structure:
1178
+ {
1179
+ "class" : "InformationSupplyChainSegmentRequestBody",
1180
+ "externalSourceGUID": "add guid here",
1181
+ "externalSourceName": "add qualified name here",
1182
+ "effectiveTime" : {{isotime}},
1183
+ "forLineage" : false,
1184
+ "forDuplicateProcessing" : false,
1185
+ "properties": {
1186
+ "qualifiedName": "add unique name here",
1187
+ "displayName": "add short name here",
1188
+ "description": "add description here",
1189
+ "scope": "add scope of this information supply chain's applicability.",
1190
+ "integrationStyle": "style",
1191
+ "estimatedVolumetrics": {
1192
+ "property1" : "propertyValue1",
1193
+ "property2" : "propertyValue2"
1194
+ },
1195
+ "additionalProperties": {
1196
+ "property1" : "propertyValue1",
1197
+ "property2" : "propertyValue2"
1198
+ },
1199
+ "effectiveFrom": {{isotime}},
1200
+ "effectiveTo": {{isotime}}
1201
+ }
1202
+ }
1203
+
1204
+ """
1205
+ validate_guid(guid)
1206
+
1207
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
1208
+ f"information-supply-chains/{guid}/segments")
1209
+
1210
+ response = await self._async_make_request("POST", url, body_slimmer(body))
1211
+
1212
+ return response.json().get("guid", "Supply Chain segment not created")
1213
+
1214
+
1215
+ def create_info_supply_chain_segment(self, guid: str, body: dict) -> str:
1216
+ """Create an information supply chain segment and link it to its owning information supply chain.
1217
+
1218
+ Parameters
1219
+ ----------
1220
+ guid: str
1221
+ The guid of the information supply chain you are adding a segment to.
1222
+ body: dict
1223
+ A dictionary containing the definition of the supply chain to create.
1224
+
1225
+ Returns
1226
+ -------
1227
+
1228
+ str - guid of the supply chain segment created.
1229
+
1230
+ Raises
1231
+ ------
1232
+ Raises
1233
+ ------
1234
+ InvalidParameterException
1235
+ one of the parameters is null or invalid or
1236
+ PropertyServerException
1237
+ There is a problem adding the element properties to the metadata repository or
1238
+ UserNotAuthorizedException
1239
+ the requesting user is not authorized to issue this request.
1240
+
1241
+ Notes
1242
+ ----
1243
+
1244
+ Body structure:
1245
+ {
1246
+ "class" : "InformationSupplyChainSegmentRequestBody",
1247
+ "externalSourceGUID": "add guid here",
1248
+ "externalSourceName": "add qualified name here",
1249
+ "effectiveTime" : {{isotime}},
1250
+ "forLineage" : false,
1251
+ "forDuplicateProcessing" : false,
1252
+ "properties": {
1253
+ "qualifiedName": "add unique name here",
1254
+ "displayName": "add short name here",
1255
+ "description": "add description here",
1256
+ "scope": "add scope of this information supply chain's applicability.",
1257
+ "integrationStyle": "style",
1258
+ "estimatedVolumetrics": {
1259
+ "property1" : "propertyValue1",
1260
+ "property2" : "propertyValue2"
1261
+ },
1262
+ "additionalProperties": {
1263
+ "property1" : "propertyValue1",
1264
+ "property2" : "propertyValue2"
1265
+ },
1266
+ "effectiveFrom": {{isotime}},
1267
+ "effectiveTo": {{isotime}}
1268
+ }
1269
+ }
1270
+
1271
+ """
1272
+
1273
+ loop = asyncio.get_event_loop()
1274
+ response = loop.run_until_complete(self._async_create_info_supply_chain_segment(guid, body))
1275
+ return response
1276
+
1277
+
1278
+ async def _async_update_info_supply_chain_segment(self, guid: str, body: dict,
1279
+ replace_all_properties: bool = False) -> None:
1280
+ """ Update the properties of an information supply chain segment. Async Version.
1281
+
1282
+ Parameters
1283
+ ----------
1284
+ guid: str
1285
+ guid of the information supply chain segment to update.
1286
+ body: dict
1287
+ A dictionary containing the updates to the supply chain segment.
1288
+ replace_all_properties: bool, optional
1289
+ Whether to replace all properties with those provided in the body or to merge with existing properties.
1290
+
1291
+ Returns
1292
+ -------
1293
+ None
1294
+
1295
+ Raises
1296
+ ------
1297
+ InvalidParameterException
1298
+ one of the parameters is null or invalid or
1299
+ PropertyServerException
1300
+ There is a problem adding the element properties to the metadata repository or
1301
+ UserNotAuthorizedException
1302
+ the requesting user is not authorized to issue this request.
1303
+
1304
+ Notes
1305
+ ----
1306
+
1307
+ Body structure:
1308
+ {
1309
+ "class" : "InformationSupplyChainSegmentRequestBody",
1310
+ "externalSourceGUID": "add guid here",
1311
+ "externalSourceName": "add qualified name here",
1312
+ "effectiveTime" : {{isotime}},
1313
+ "forLineage" : false,
1314
+ "forDuplicateProcessing" : false,
1315
+ "properties": {
1316
+ "qualifiedName": "add unique name here",
1317
+ "displayName": "add short name here",
1318
+ "description": "add description here",
1319
+ "scope": "add scope of this information supply chain's applicability.",
1320
+ "integrationStyle": "style",
1321
+ "estimatedVolumetrics": {
1322
+ "property1" : "propertyValue1",
1323
+ "property2" : "propertyValue2"
1324
+ },
1325
+ "additionalProperties": {
1326
+ "property1" : "propertyValue1",
1327
+ "property2" : "propertyValue2"
1328
+ },
1329
+ "effectiveFrom": {{isotime}},
1330
+ "effectiveTo": {{isotime}}
1331
+ }
1332
+ }
1333
+ """
1334
+ validate_guid(guid)
1335
+ replace_all_properties_s = str(replace_all_properties).lower()
1336
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
1337
+ f"information-supply-chains/segments/{guid}/update?replaceAllProperties={replace_all_properties_s}")
1338
+
1339
+ await self._async_make_request("POST", url, body_slimmer(body))
1340
+
1341
+
1342
+ def update_info_supply_chain_segment(self, guid: str, body: dict, replace_all_properties: bool = False) -> None:
1343
+ """ Update the properties of an information supply chain segment. Async Version.
1344
+
1345
+ Parameters
1346
+ ----------
1347
+ guid: str
1348
+ guid of the information supply chain segment to update.
1349
+ body: dict
1350
+ A dictionary containing the updates to the supply chain segment .
1351
+ replace_all_properties: bool, optional
1352
+ Whether to replace all properties with those provided in the body or to merge with existing properties.
1353
+
1354
+ Returns
1355
+ -------
1356
+
1357
+ None
1358
+
1359
+ Raises
1360
+ ------
1361
+ Raises
1362
+ ------
1363
+ InvalidParameterException
1364
+ one of the parameters is null or invalid or
1365
+ PropertyServerException
1366
+ There is a problem adding the element properties to the metadata repository or
1367
+ UserNotAuthorizedException
1368
+ the requesting user is not authorized to issue this request.
1369
+
1370
+ Notes
1371
+ ----
1372
+
1373
+ Body structure:
1374
+ {
1375
+ "class" : "InformationSupplyChainSegmentRequestBody",
1376
+ "externalSourceGUID": "add guid here",
1377
+ "externalSourceName": "add qualified name here",
1378
+ "effectiveTime" : {{isotime}},
1379
+ "forLineage" : false,
1380
+ "forDuplicateProcessing" : false,
1381
+ "properties": {
1382
+ "qualifiedName": "add unique name here",
1383
+ "displayName": "add short name here",
1384
+ "description": "add description here",
1385
+ "scope": "add scope of this information supply chain's applicability.",
1386
+ "integrationStyle": "style",
1387
+ "estimatedVolumetrics": {
1388
+ "property1" : "propertyValue1",
1389
+ "property2" : "propertyValue2"
1390
+ },
1391
+ "additionalProperties": {
1392
+ "property1" : "propertyValue1",
1393
+ "property2" : "propertyValue2"
1394
+ },
1395
+ "effectiveFrom": {{isotime}},
1396
+ "effectiveTo": {{isotime}}
1397
+ }
1398
+ }
1399
+ """
1400
+ loop = asyncio.get_event_loop()
1401
+ loop.run_until_complete(self._async_update_info_supply_chain_segment(guid, body, replace_all_properties))
1402
+
1403
+
1404
+ async def _async_delete_info_supply_chain_segment(self, guid: str, body: dict = None) -> None:
1405
+ """Delete an information supply chain segment. Async Version.
1406
+
1407
+ Parameters
1408
+ ----------
1409
+ guid: str
1410
+ guid of the information supply chain segment to delete.
1411
+ body: dict, optional
1412
+ A dictionary containing parameters of the deletion.
1413
+
1414
+ Returns
1415
+ -------
1416
+ None
1417
+
1418
+ Raises
1419
+ ------
1420
+ Raises
1421
+ ------
1422
+ InvalidParameterException
1423
+ one of the parameters is null or invalid or
1424
+ PropertyServerException
1425
+ There is a problem adding the element properties to the metadata repository or
1426
+ UserNotAuthorizedException
1427
+ the requesting user is not authorized to issue this request.
1428
+
1429
+ Notes
1430
+ ----
1431
+
1432
+ Body structure:
1433
+ {
1434
+ "class" : "MetadataSourceRequestBody",
1435
+ "externalSourceGUID": "add guid here",
1436
+ "externalSourceName": "add qualified name here",
1437
+ "effectiveTime" : {{isotime}},
1438
+ "forLineage" : false,
1439
+ "forDuplicateProcessing" : false
1440
+ }
1441
+ """
1442
+ validate_guid(guid)
1443
+
1444
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
1445
+ f"information-supply-chains/segments/{guid}/delete")
1446
+
1447
+ await self._async_make_request("POST", url, body_slimmer(body))
1448
+
1449
+
1450
+ def delete_info_supply_chain_segment(self, guid: str, body: dict = None) -> None:
1451
+ """ Delete an information supply chain segment. Async Version.
1452
+
1453
+ Parameters
1454
+ ----------
1455
+ guid: str
1456
+ guid of the information supply chain segment to delete.
1457
+ body: dict, optional
1458
+ A dictionary containing parameters of the deletion.
1459
+
1460
+ Returns
1461
+ -------
1462
+ None
1463
+
1464
+ Raises
1465
+ ------
1466
+ Raises
1467
+ ------
1468
+ InvalidParameterException
1469
+ one of the parameters is null or invalid or
1470
+ PropertyServerException
1471
+ There is a problem adding the element properties to the metadata repository or
1472
+ UserNotAuthorizedException
1473
+ the requesting user is not authorized to issue this request.
1474
+
1475
+ Notes
1476
+ ----
1477
+
1478
+ Body structure:
1479
+ {
1480
+ "class" : "MetadataSourceRequestBody",
1481
+ "externalSourceGUID": "add guid here",
1482
+ "externalSourceName": "add qualified name here",
1483
+ "effectiveTime" : {{isotime}},
1484
+ "forLineage" : false,
1485
+ "forDuplicateProcessing" : false
1486
+ }
1487
+ """
1488
+ loop = asyncio.get_event_loop()
1489
+ loop.run_until_complete(self._async_delete_info_supply_chain_segment(guid, body))
1490
+
1491
+
1492
+ async def _async_link_info_supply_chain_segments(self, segment_guid1: str, segment_guid2: str, body: dict) -> None:
1493
+ """ Connect the information supply chain segments. Async Version.
1494
+
1495
+ Parameters
1496
+ ----------
1497
+ segment_guid1: str
1498
+ guid of the first information supply chain segment to link.
1499
+ segment_guid2: str
1500
+ guid of the second information supply chain segment to link.
1501
+ body: dict
1502
+ The body describing the link between the two segments.
1503
+
1504
+ Returns
1505
+ -------
1506
+ None
1507
+
1508
+ Raises
1509
+ ------
1510
+ InvalidParameterException
1511
+ one of the parameters is null or invalid or
1512
+ PropertyServerException
1513
+ There is a problem adding the element properties to the metadata repository or
1514
+ UserNotAuthorizedException
1515
+ the requesting user is not authorized to issue this request.
1516
+
1517
+ Notes
1518
+ ----
1519
+
1520
+ Body structure:
1521
+ {
1522
+ "class" : "InformationSupplyChainLinkRequestBody",
1523
+ "externalSourceGUID": "add guid here",
1524
+ "externalSourceName": "add qualified name here",
1525
+ "effectiveTime" : {{isotime}},
1526
+ "forLineage" : false,
1527
+ "forDuplicateProcessing" : false,
1528
+ "properties": {
1529
+ "label": "add label here",
1530
+ "description": "add description here",
1531
+ "effectiveFrom": {{isotime}},
1532
+ "effectiveTo": {{isotime}}
1533
+ }
1534
+ }
1535
+ """
1536
+ validate_guid(segment_guid1)
1537
+ validate_guid(segment_guid2)
1538
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
1539
+ f"information-supply-chains/segments/{segment_guid1}/link-to{segment_guid2}/attach")
1540
+
1541
+ await self._async_make_request("POST", url, body_slimmer(body))
1542
+
1543
+
1544
+ def link_info_supply_chain_segments(self, segment_guid1: str, segment_guid2: str, body: dict) -> None:
1545
+ """ Connect the information supply chain segments.
1546
+
1547
+ Parameters
1548
+ ----------
1549
+ segment_guid1: str
1550
+ guid of the first information supply chain segment to link.
1551
+ segment_guid2: str
1552
+ guid of the second information supply chain segment to link.
1553
+ body: dict
1554
+ The body describing the link between the two segments.
1555
+
1556
+ Returns
1557
+ -------
1558
+ None
1559
+
1560
+ Raises
1561
+ ------
1562
+ InvalidParameterException
1563
+ one of the parameters is null or invalid or
1564
+ PropertyServerException
1565
+ There is a problem adding the element properties to the metadata repository or
1566
+ UserNotAuthorizedException
1567
+ the requesting user is not authorized to issue this request.
1568
+
1569
+ Notes
1570
+ ----
1571
+
1572
+ Body structure:
1573
+ {
1574
+ "class" : "InformationSupplyChainLinkRequestBody",
1575
+ "externalSourceGUID": "add guid here",
1576
+ "externalSourceName": "add qualified name here",
1577
+ "effectiveTime" : {{isotime}},
1578
+ "forLineage" : false,
1579
+ "forDuplicateProcessing" : false,
1580
+ "properties": {
1581
+ "label": "add label here",
1582
+ "description": "add description here",
1583
+ "effectiveFrom": {{isotime}},
1584
+ "effectiveTo": {{isotime}}
1585
+ }
1586
+ }
1587
+ """
1588
+ loop = asyncio.get_event_loop()
1589
+ loop.run_until_complete(self._async_link_info_supply_chain_segments(segment_guid1, segment_guid2, body))
1590
+
1591
+
1592
+ async def _async_detach_info_supply_chain_segments(self, segment_guid1: str, segment_guid2: str,
1593
+ body: dict = None) -> None:
1594
+ """ Detach two information supply chain segments from one another. Request body is optional.
1595
+ Async Version.
1596
+
1597
+ Parameters
1598
+ ----------
1599
+ segment_guid1: str
1600
+ guid of the first information supply chain segment to link.
1601
+ segment_guid2: str
1602
+ guid of the second information supply chain segment to link.
1603
+ body: dict, optional
1604
+ The body describing the link between the two segments.
1605
+
1606
+ Returns
1607
+ -------
1608
+ None
1609
+
1610
+ Raises
1611
+ ------
1612
+ InvalidParameterException
1613
+ one of the parameters is null or invalid or
1614
+ PropertyServerException
1615
+ There is a problem adding the element properties to the metadata repository or
1616
+ UserNotAuthorizedException
1617
+ the requesting user is not authorized to issue this request.
1618
+
1619
+ Notes
1620
+ ----
1621
+
1622
+ Body structure:
1623
+ {
1624
+ "class" : "MetadataSourceRequestBody",
1625
+ "externalSourceGUID": "add guid here",
1626
+ "externalSourceName": "add qualified name here",
1627
+ "effectiveTime" : {{isotime}},
1628
+ "forLineage" : false,
1629
+ "forDuplicateProcessing" : false
1630
+ }
1631
+
1632
+ """
1633
+ validate_guid(segment_guid1)
1634
+ validate_guid(segment_guid2)
1635
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/solution-architect/"
1636
+ f"information-supply-chains/segments/{segment_guid1}/link-to{segment_guid2}/detach")
1637
+
1638
+ await self._async_make_request("POST", url, body_slimmer(body))
1639
+
1640
+
1641
+ def detach_info_supply_chain_segments(self, segment_guid1: str, segment_guid2: str, body: dict = None) -> None:
1642
+ """ Detach two information supply chain segments from one another. Request body is optional.
1643
+
1644
+ Parameters
1645
+ ----------
1646
+ segment_guid1: str
1647
+ guid of the first information supply chain segment to link.
1648
+ segment_guid2: str
1649
+ guid of the second information supply chain segment to link.
1650
+ body: dict
1651
+ The body describing the link between the two segments.
1652
+
1653
+ Returns
1654
+ -------
1655
+ None
1656
+
1657
+ Raises
1658
+ ------
1659
+ InvalidParameterException
1660
+ one of the parameters is null or invalid or
1661
+ PropertyServerException
1662
+ There is a problem adding the element properties to the metadata repository or
1663
+ UserNotAuthorizedException
1664
+ the requesting user is not authorized to issue this request.
1665
+
1666
+ Notes
1667
+ ----
1668
+
1669
+ Body structure:
1670
+ {
1671
+ "class" : "InformationSupplyChainLinkRequestBody",
1672
+ "externalSourceGUID": "add guid here",
1673
+ "externalSourceName": "add qualified name here",
1674
+ "effectiveTime" : {{isotime}},
1675
+ "forLineage" : false,
1676
+ "forDuplicateProcessing" : false,
1677
+ "properties": {
1678
+ "label": "add label here",
1679
+ "description": "add description here",
1680
+ "effectiveFrom": {{isotime}},
1681
+ "effectiveTo": {{isotime}}
1682
+ }
1683
+ }
1684
+ """
1685
+ loop = asyncio.get_event_loop()
1686
+ loop.run_until_complete(self._async_detach_info_supply_chain_segments(segment_guid1, segment_guid2, body))
1687
+
1688
+
1689
+ #
1690
+ # Blueprints
1691
+ #
1692
+
1693
+
1694
+ async def _async_find_solution_blueprints(self, filter: str = "*", starts_with: bool = True, ends_with: bool = False,
1695
+ ignore_case: bool = False, start_from: int = 0, page_size: int = max_paging_size, body: dict = None,
1696
+ output_format: str = "JSON", include_mermaid: bool = False) -> list[
1697
+ dict] | str:
262
1698
  """Retrieve the solution blueprint elements that contain the search string.
263
1699
  https://egeria-project.org/concepts/solution-blueprint
264
1700
  Async version.
@@ -275,6 +1711,14 @@ class SolutionArchitect(Client):
275
1711
  Ignore case when searching
276
1712
  body: dict, optional, default = None
277
1713
  - additional optional specifications for the search.
1714
+ output_format: str, default = 'JSON'
1715
+ Type of output to produce:
1716
+ JSON - output standard json
1717
+ MD - output standard markdown with no preamble
1718
+ FORM - output markdown with a preamble for a form
1719
+ REPORT - output markdown with a preamble for a report
1720
+ include_mermaid: bool, default = False
1721
+ Include mermaid diagrams?
278
1722
 
279
1723
  Returns
280
1724
  -------
@@ -292,14 +1736,8 @@ class SolutionArchitect(Client):
292
1736
  """
293
1737
 
294
1738
  possible_query_params = query_string(
295
- [
296
- ("startFrom", start_from),
297
- ("pageSize", page_size),
298
- ("startsWith", starts_with),
299
- ("endsWith", ends_with),
300
- ("ignoreCase", ignore_case),
301
- ]
302
- )
1739
+ [("startFrom", start_from), ("pageSize", page_size), ("startsWith", starts_with), ("endsWith", ends_with),
1740
+ ("ignoreCase", ignore_case), ])
303
1741
 
304
1742
  if filter is None or filter == "*":
305
1743
  search_filter = None
@@ -309,29 +1747,24 @@ class SolutionArchitect(Client):
309
1747
  if body is None:
310
1748
  body = {
311
1749
  "filter": search_filter,
312
- }
1750
+ }
313
1751
  else:
314
1752
  body["filter"] = search_filter
315
1753
 
316
- url = (
317
- f"{self.solution_architect_command_root}/solution-blueprints/by-search-string"
318
- f"{possible_query_params}"
319
- )
320
- response: Response = await self._async_make_request(
321
- "POST", url, body_slimmer(body)
322
- )
1754
+ url = (f"{self.solution_architect_command_root}/solution-blueprints/by-search-string"
1755
+ f"{possible_query_params}")
1756
+ response: Response = await self._async_make_request("POST", url, body_slimmer(body))
1757
+ element = response.json().get("elements", NO_ELEMENTS_FOUND)
1758
+ if element == NO_ELEMENTS_FOUND:
1759
+ return NO_ELEMENTS_FOUND
1760
+ if output_format != 'JSON': # return a simplified markdown representation
1761
+ return self.generate_solution_blueprint_md(element, filter, output_format, include_mermaid)
323
1762
  return response.json().get("elements", NO_ELEMENTS_FOUND)
324
1763
 
325
- def find_solution_blueprints(
326
- self,
327
- filter: str = "*",
328
- starts_with: bool = True,
329
- ends_with: bool = False,
330
- ignore_case: bool = False,
331
- start_from: int = 0,
332
- page_size: int = max_paging_size,
333
- body: dict = None,
334
- ) -> list[dict] | str:
1764
+
1765
+ def find_solution_blueprints(self, filter: str = "*", starts_with: bool = True, ends_with: bool = False,
1766
+ ignore_case: bool = False, start_from: int = 0, page_size: int = max_paging_size, body: dict = None,
1767
+ output_format: str = 'JSON', include_mermaid: bool= False) -> list[dict] | str:
335
1768
  """Retrieve the list of solution blueprint elements that contain the search string.
336
1769
  https://egeria-project.org/concepts/solution-blueprint
337
1770
 
@@ -345,8 +1778,21 @@ class SolutionArchitect(Client):
345
1778
  Ends with the supplied string
346
1779
  ignore_case : bool, [default=False], optional
347
1780
  Ignore case when searching
1781
+ start_from: int, [default=0], optional
1782
+ When multiple pages of results are available, the page number to start from.
1783
+ page_size: int, [default=max_paging_size], optional
1784
+ The number of items to return in a single page. If not specified, the default will be taken from
1785
+ the class instance.
348
1786
  body: dict, optional, default = None
349
1787
  - additional optional specifications for the search.
1788
+ output_format: str, default = 'JSON'
1789
+ Type of output to produce:
1790
+ JSON - output standard json
1791
+ MD - output standard markdown with no preamble
1792
+ FORM - output markdown with a preamble for a form
1793
+ REPORT - output markdown with a preamble for a report
1794
+ include_mermaid: bool, default = False
1795
+ Include mermaid diagrams?
350
1796
 
351
1797
  Returns
352
1798
  -------
@@ -365,38 +1811,28 @@ class SolutionArchitect(Client):
365
1811
 
366
1812
  loop = asyncio.get_event_loop()
367
1813
  response = loop.run_until_complete(
368
- self._async_find_solution_blueprints(
369
- filter,
370
- starts_with,
371
- ends_with,
372
- ignore_case,
373
- start_from,
374
- page_size,
375
- body,
376
- )
377
- )
1814
+ self._async_find_solution_blueprints(filter, starts_with, ends_with, ignore_case,
1815
+ start_from, page_size, body,
1816
+ output_format, include_mermaid)
1817
+ )
378
1818
  return response
379
1819
 
380
- def find_all_solution_blueprints(
381
- self, start_from: int = 0, page_size: int = max_paging_size
382
- ) -> list[dict] | str:
1820
+
1821
+ def find_all_solution_blueprints(self, start_from: int = 0, page_size: int = max_paging_size) -> list[dict] | str:
383
1822
  """Retrieve a list of all solution blueprint elements
384
1823
  https://egeria-project.org/concepts/solution-blueprint
385
1824
  """
386
- return self.find_solution_blueprints(
387
- "*", start_from=start_from, page_size=page_size
388
- )
389
-
390
- async def _async_find_solution_roles(
391
- self,
392
- filter: str = "*",
393
- starts_with: bool = True,
394
- ends_with: bool = False,
395
- ignore_case: bool = False,
396
- start_from: int = 0,
397
- page_size: int = max_paging_size,
398
- body: dict = None,
399
- ) -> list[dict] | str:
1825
+ return self.find_solution_blueprints("*", start_from=start_from, page_size=page_size)
1826
+
1827
+
1828
+ #
1829
+ # Roles
1830
+ #
1831
+
1832
+ async def _async_find_solution_roles(self, filter: str = "*", starts_with: bool = True, ends_with: bool = False,
1833
+ ignore_case: bool = False, start_from: int = 0, page_size: int = max_paging_size, body: dict = None,
1834
+ output_format: str = "JSON", include_mermaid: bool = False) -> list[
1835
+ dict] | str:
400
1836
  """Retrieve the solutio nrole elements that contain the search string.
401
1837
  https://egeria-project.org/concepts/actor
402
1838
  Async version.
@@ -413,6 +1849,14 @@ class SolutionArchitect(Client):
413
1849
  Ignore case when searching
414
1850
  body: dict, optional, default = None
415
1851
  - additional optional specifications for the search.
1852
+ output_format: str, default = 'JSON'
1853
+ Type of output to produce:
1854
+ JSON - output standard json
1855
+ MD - output standard markdown with no preamble
1856
+ FORM - output markdown with a preamble for a form
1857
+ REPORT - output markdown with a preamble for a report
1858
+ include_mermaid: bool, default = False
1859
+ Include mermaid diagrams?
416
1860
 
417
1861
  Returns
418
1862
  -------
@@ -430,14 +1874,8 @@ class SolutionArchitect(Client):
430
1874
  """
431
1875
 
432
1876
  possible_query_params = query_string(
433
- [
434
- ("startFrom", start_from),
435
- ("pageSize", page_size),
436
- ("startsWith", starts_with),
437
- ("endsWith", ends_with),
438
- ("ignoreCase", ignore_case),
439
- ]
440
- )
1877
+ [("startFrom", start_from), ("pageSize", page_size), ("startsWith", starts_with), ("endsWith", ends_with),
1878
+ ("ignoreCase", ignore_case), ])
441
1879
 
442
1880
  if filter is None or filter == "*":
443
1881
  search_filter = None
@@ -447,29 +1885,24 @@ class SolutionArchitect(Client):
447
1885
  if body is None:
448
1886
  body = {
449
1887
  "filter": search_filter,
450
- }
1888
+ }
451
1889
  else:
452
1890
  body["filter"] = search_filter
453
1891
 
454
- url = (
455
- f"{self.solution_architect_command_root}/solution-roles/by-search-string"
456
- f"{possible_query_params}"
457
- )
458
- response: Response = await self._async_make_request(
459
- "POST", url, body_slimmer(body)
460
- )
1892
+ url = (f"{self.solution_architect_command_root}/solution-roles/by-search-string"
1893
+ f"{possible_query_params}")
1894
+ response: Response = await self._async_make_request("POST", url, body_slimmer(body))
1895
+ element = response.json().get("elements", NO_ELEMENTS_FOUND)
1896
+ if element == NO_ELEMENTS_FOUND:
1897
+ return NO_ELEMENTS_FOUND
1898
+ if output_format != 'JSON': # return a simplified markdown representation
1899
+ return self.generate_solution_roles_md(element, filter, output_format, include_mermaid)
461
1900
  return response.json().get("elements", NO_ELEMENTS_FOUND)
462
1901
 
463
- def find_solution_roles(
464
- self,
465
- filter: str = "*",
466
- starts_with: bool = True,
467
- ends_with: bool = False,
468
- ignore_case: bool = False,
469
- start_from: int = 0,
470
- page_size: int = max_paging_size,
471
- body: dict = None,
472
- ) -> list[dict] | str:
1902
+
1903
+ def find_solution_roles(self, filter: str = "*", starts_with: bool = True, ends_with: bool = False,
1904
+ ignore_case: bool = False, start_from: int = 0, page_size: int = max_paging_size, body: dict = None,
1905
+ output_format: str = "JSON", include_mermaid: bool = False) -> list[dict] | str:
473
1906
  """Retrieve the list of solution role elements that contain the search string.
474
1907
  https://egeria-project.org/concepts/actor
475
1908
 
@@ -483,8 +1916,21 @@ class SolutionArchitect(Client):
483
1916
  Ends with the supplied string
484
1917
  ignore_case : bool, [default=False], optional
485
1918
  Ignore case when searching
1919
+ start_from: int, [default=0], optional
1920
+ When multiple pages of results are available, the page number to start from.
1921
+ page_size: int, [default=max_paging_size], optional
1922
+ The number of items to return in a single page. If not specified, the default will be taken from
1923
+ the class instance.
486
1924
  body: dict, optional, default = None
487
1925
  - additional optional specifications for the search.
1926
+ output_format: str, default = 'JSON'
1927
+ Type of output to produce:
1928
+ JSON - output standard json
1929
+ MD - output standard markdown with no preamble
1930
+ FORM - output markdown with a preamble for a form
1931
+ REPORT - output markdown with a preamble for a report
1932
+ include_mermaid: bool, default = False
1933
+ Include mermaid diagrams?
488
1934
 
489
1935
  Returns
490
1936
  -------
@@ -503,36 +1949,26 @@ class SolutionArchitect(Client):
503
1949
 
504
1950
  loop = asyncio.get_event_loop()
505
1951
  response = loop.run_until_complete(
506
- self._async_find_solution_roles(
507
- filter,
508
- starts_with,
509
- ends_with,
510
- ignore_case,
511
- start_from,
512
- page_size,
513
- body,
1952
+ self._async_find_solution_roles(filter, starts_with, ends_with, ignore_case,
1953
+ start_from, page_size, body,
1954
+ output_format=output_format, include_mermaid=include_mermaid )
514
1955
  )
515
- )
516
1956
  return response
517
1957
 
518
- def find_all_solution_roles(
519
- self, start_from: int = 0, page_size: int = max_paging_size
520
- ) -> list[dict] | str:
1958
+
1959
+ def find_all_solution_roles(self, start_from: int = 0, page_size: int = max_paging_size) -> list[dict] | str:
521
1960
  """Retrieve a list of all solution blueprint elements
522
1961
  https://egeria-project.org/concepts/actor
523
1962
  """
524
1963
  return self.find_solution_roles("*", start_from=start_from, page_size=page_size)
525
1964
 
526
- async def _async_find_solution_components(
527
- self,
528
- filter: str = "*",
529
- starts_with: bool = True,
530
- ends_with: bool = False,
531
- ignore_case: bool = False,
532
- start_from: int = 0,
533
- page_size: int = max_paging_size,
534
- body: dict = None,
535
- ) -> list[dict] | str:
1965
+
1966
+ #
1967
+ # Components
1968
+ #
1969
+ async def _async_find_solution_components(self, filter: str = "*", starts_with: bool = True, ends_with: bool = False,
1970
+ ignore_case: bool = False, start_from: int = 0, page_size: int = max_paging_size, body: dict = None, ) -> list[
1971
+ dict] | str:
536
1972
  """Retrieve the solution component elements that contain the search string.
537
1973
  https://egeria-project.org/concepts/solution-components
538
1974
  Async version.
@@ -566,14 +2002,8 @@ class SolutionArchitect(Client):
566
2002
  """
567
2003
 
568
2004
  possible_query_params = query_string(
569
- [
570
- ("startFrom", start_from),
571
- ("pageSize", page_size),
572
- ("startsWith", starts_with),
573
- ("endsWith", ends_with),
574
- ("ignoreCase", ignore_case),
575
- ]
576
- )
2005
+ [("startFrom", start_from), ("pageSize", page_size), ("startsWith", starts_with), ("endsWith", ends_with),
2006
+ ("ignoreCase", ignore_case), ])
577
2007
 
578
2008
  if filter is None or filter == "*":
579
2009
  search_filter = None
@@ -583,29 +2013,19 @@ class SolutionArchitect(Client):
583
2013
  if body is None:
584
2014
  body = {
585
2015
  "filter": search_filter,
586
- }
2016
+ }
587
2017
  else:
588
2018
  body["filter"] = search_filter
589
2019
 
590
- url = (
591
- f"{self.solution_architect_command_root}/solution-components/by-search-string"
592
- f"{possible_query_params}"
593
- )
594
- response: Response = await self._async_make_request(
595
- "POST", url, body_slimmer(body)
596
- )
2020
+ url = (f"{self.solution_architect_command_root}/solution-components/by-search-string"
2021
+ f"{possible_query_params}")
2022
+ response: Response = await self._async_make_request("POST", url, body_slimmer(body))
597
2023
  return response.json().get("elements", NO_ELEMENTS_FOUND)
598
2024
 
599
- def find_solution_components(
600
- self,
601
- filter: str = "*",
602
- starts_with: bool = True,
603
- ends_with: bool = False,
604
- ignore_case: bool = False,
605
- start_from: int = 0,
606
- page_size: int = max_paging_size,
607
- body: dict = None,
608
- ) -> list[dict] | str:
2025
+
2026
+ def find_solution_components(self, filter: str = "*", starts_with: bool = True, ends_with: bool = False,
2027
+ ignore_case: bool = False, start_from: int = 0, page_size: int = max_paging_size, body: dict = None, ) -> list[
2028
+ dict] | str:
609
2029
  """Retrieve the list of solution component elements that contain the search string.
610
2030
  https://egeria-project.org/concepts/solution-components
611
2031
 
@@ -619,6 +2039,11 @@ class SolutionArchitect(Client):
619
2039
  Ends with the supplied string
620
2040
  ignore_case : bool, [default=False], optional
621
2041
  Ignore case when searching
2042
+ start_from: int, [default=0], optional
2043
+ When multiple pages of results are available, the page number to start from.
2044
+ page_size: int, [default=max_paging_size], optional
2045
+ The number of items to return in a single page. If not specified, the default will be taken from
2046
+ the class instance.
622
2047
  body: dict, optional, default = None
623
2048
  - additional optional specifications for the search.
624
2049
 
@@ -639,27 +2064,92 @@ class SolutionArchitect(Client):
639
2064
 
640
2065
  loop = asyncio.get_event_loop()
641
2066
  response = loop.run_until_complete(
642
- self._async_find_solution_components(
643
- filter,
644
- starts_with,
645
- ends_with,
646
- ignore_case,
647
- start_from,
648
- page_size,
649
- body,
650
- )
651
- )
2067
+ self._async_find_solution_components(filter, starts_with, ends_with, ignore_case, start_from, page_size,
2068
+ body, ))
652
2069
  return response
653
2070
 
654
- def find_all_solution_components(
655
- self, start_from: int = 0, page_size: int = max_paging_size
656
- ) -> list[dict] | str:
2071
+
2072
+ def find_all_solution_components(self, start_from: int = 0, page_size: int = max_paging_size) -> list[dict] | str:
657
2073
  """Retrieve a list of all solution component elements
658
2074
  https://egeria-project.org/concepts/solution-components
659
2075
  """
660
- return self.find_solution_components(
661
- "*", start_from=start_from, page_size=page_size
662
- )
2076
+ return self.find_solution_components("*", start_from=start_from, page_size=page_size)
2077
+
2078
+
2079
+ async def _async_get_solution_component_implementations(self, guid: str, body: dict = None, start_from: int = 0,
2080
+ page_size: int = max_paging_size, ) -> list[dict] | str:
2081
+ """ Retrieve the list of metadata elements that are associated with the solution component via
2082
+ the ImplementedBy relationship.
2083
+ Async version.
2084
+
2085
+ Parameters
2086
+ ----------
2087
+ guid: str
2088
+ - identifier of the solution component to retrieve the implementations for.
2089
+ body: dict, optional, default = None
2090
+ - additional optional specifications for the search.
2091
+ start_from : int, default = 0
2092
+ page_size : int, default = max_paging_size
2093
+
2094
+ Returns
2095
+ -------
2096
+ list[dict] | str
2097
+ A list of implementation elements or a string if there are no elements found.
2098
+
2099
+ Raises
2100
+ ------
2101
+ InvalidParameterException
2102
+ one of the parameters is null or invalid or
2103
+ PropertyServerException
2104
+ There is a problem adding the element properties to the metadata repository or
2105
+ UserNotAuthorizedException
2106
+ the requesting user is not authorized to issue this request.
2107
+ """
2108
+
2109
+ possible_query_params = query_string([("startFrom", start_from), ("pageSize", page_size)])
2110
+
2111
+ validate_guid(guid)
2112
+
2113
+ url = (f"{self.solution_architect_command_root}/solution-components/{guid}/implementations"
2114
+ f"{possible_query_params}")
2115
+ response: Response = await self._async_make_request("POST", url, body_slimmer(body))
2116
+ return response.json().get("elementList", NO_ELEMENTS_FOUND)
2117
+
2118
+
2119
+ def get_solution_component_implementations(self, guid: str, body: dict = None, start_from: int = 0,
2120
+ page_size: int = max_paging_size, ) -> list[dict] | str:
2121
+ """Retrieve the list of metadata elements that are associated with the solution component via
2122
+ the ImplementedBy relationship.
2123
+ Async version.
2124
+
2125
+ Parameters
2126
+ ----------
2127
+ guid: str
2128
+ - identifier of the solution component to retrieve the implementations for.
2129
+ body: dict, optional, default = None
2130
+ - additional optional specifications for the search.
2131
+ start_from : int, default = 0
2132
+ page_size : int, default = max_paging_size
2133
+
2134
+ Returns
2135
+ -------
2136
+ list[dict] | str
2137
+ A list of implementation elements or a string if there are no elements found.
2138
+
2139
+ Raises
2140
+ ------
2141
+ InvalidParameterException
2142
+ one of the parameters is null or invalid or
2143
+ PropertyServerException
2144
+ There is a problem adding the element properties to the metadata repository or
2145
+ UserNotAuthorizedException
2146
+ the requesting user is not authorized to issue this request.
2147
+ """
2148
+
2149
+ loop = asyncio.get_event_loop()
2150
+ response = loop.run_until_complete(
2151
+ self._async_get_solution_component_implementations(guid, body, start_from, page_size))
2152
+ return response
663
2153
 
664
2154
 
665
2155
  if __name__ == "__main__":