Skip to content

Commit

Permalink
Merge pull request #8522 from mandy-chessell/oak2024
Browse files Browse the repository at this point in the history
Add mermaid visualizations to Metadata Explorer OMVS
  • Loading branch information
mandy-chessell authored Dec 4, 2024
2 parents 6d0003a + 25cbeb8 commit f851ae6
Show file tree
Hide file tree
Showing 58 changed files with 1,915 additions and 1,260 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
implementation project(':open-metadata-implementation:frameworks:governance-action-framework')
implementation project(':open-metadata-implementation:common-services:ffdc-services')
implementation project(':open-metadata-implementation:admin-services:admin-services-api')
implementation project(':open-metadata-implementation:common-services:mermaid-services')
implementation project(':open-metadata-implementation:common-services:repository-handler')
implementation project(':open-metadata-implementation:common-services:metadata-security:metadata-security-server')
implementation project(':open-metadata-implementation:common-services:generic-handlers')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
/* Copyright Contributors to the ODPi Egeria project. */
package org.odpi.openmetadata.accessservices.assetconsumer.server;

import org.odpi.openmetadata.commonservices.mermaid.AssetGraphMermaidGraphBuilder;
import org.odpi.openmetadata.commonservices.mermaid.AssetLineageGraphMermaidGraphBuilder;
import org.odpi.openmetadata.frameworks.connectors.ffdc.InvalidParameterException;
import org.odpi.openmetadata.frameworks.connectors.ffdc.PropertyServerException;
import org.odpi.openmetadata.frameworks.connectors.ffdc.UserNotAuthorizedException;
Expand Down Expand Up @@ -320,7 +322,9 @@ public AssetGraphResponse getAssetGraph(String serverName,
assetGraph.setRelationships(metadataRelationships);
}

assetGraph.setMermaidGraph(this.getAssetMermaidGraph(assetGraph));
AssetGraphMermaidGraphBuilder graphBuilder = new AssetGraphMermaidGraphBuilder(assetGraph);
assetGraph.setMermaidGraph(graphBuilder.getMermaidGraph());

response.setAssetGraph(assetGraph);
}
}
Expand All @@ -334,232 +338,6 @@ public AssetGraphResponse getAssetGraph(String serverName,
}


/**
* Constructing the mermaid graph for the retrieved asset.
*
* @param assetGraph retrieved asset graph
* @return mermaid string
*/
private String getAssetMermaidGraph(AssetGraph assetGraph)
{
StringBuilder mermaidGraph = new StringBuilder();

mermaidGraph.append("---\n");
mermaidGraph.append("title: Asset - ");
mermaidGraph.append(assetGraph.getProperties().getDisplayName());
mermaidGraph.append(" [");
mermaidGraph.append(assetGraph.getElementHeader().getGUID());
mermaidGraph.append("]\n---\nflowchart LR\n%%{init: {\"flowchart\": {\"htmlLabels\": false}} }%%\n\n");

List<String> usedQualifiedNames = new ArrayList<>();

String currentQualifiedName = assetGraph.getProperties().getQualifiedName();
String currentDisplayName = assetGraph.getProperties().getDisplayName();

appendMermaidNode(mermaidGraph,
currentQualifiedName,
currentDisplayName,
assetGraph.getElementHeader().getType().getTypeName());

usedQualifiedNames.add(currentQualifiedName);

if (assetGraph.getAnchoredElements() != null)
{
for (MetadataElementSummary node : assetGraph.getAnchoredElements())
{
if (node != null)
{
currentQualifiedName = node.getProperties().get(OpenMetadataProperty.QUALIFIED_NAME.name);
currentDisplayName = node.getProperties().get(OpenMetadataProperty.DISPLAY_NAME.name);
if (currentDisplayName == null)
{
currentDisplayName = node.getProperties().get(OpenMetadataProperty.NAME.name);
}
if (currentDisplayName == null)
{
currentDisplayName = node.getProperties().get(OpenMetadataProperty.RESOURCE_NAME.name);
}
if (currentDisplayName == null)
{
currentDisplayName = node.getProperties().get(OpenMetadataProperty.QUALIFIED_NAME.name);
}

if (!usedQualifiedNames.contains(currentQualifiedName))
{
appendMermaidNode(mermaidGraph,
currentQualifiedName,
currentDisplayName,
node.getElementHeader().getType().getTypeName());

usedQualifiedNames.add(currentQualifiedName);
}
}
}

for (MetadataRelationship line : assetGraph.getRelationships())
{
if (line != null)
{
mermaidGraph.append(this.removeSpaces(line.getEnd1().getUniqueName()));
mermaidGraph.append("-->|");
mermaidGraph.append(line.getType().getTypeName());
mermaidGraph.append("|");
mermaidGraph.append(this.removeSpaces(line.getEnd2().getUniqueName()));
mermaidGraph.append("\n");
}
}
}

return mermaidGraph.toString();
}


/**
* Create a node in the mermaid graph.
*
* @param mermaidGraph current state of the graph
* @param currentNodeName unique name/identifier
* @param currentDisplayName display name
* @param currentType type of element
*/
private void appendMermaidNode(StringBuilder mermaidGraph,
String currentNodeName,
String currentDisplayName,
String currentType)
{
mermaidGraph.append(this.removeSpaces(currentNodeName));
mermaidGraph.append("(\"`*");
mermaidGraph.append(currentType);
mermaidGraph.append("*\n**");
mermaidGraph.append(currentDisplayName);
mermaidGraph.append("**`\")\n");
}


/**
* Remove all the spaces from the qualifiedName along with the curly braces - found in the templates.
*
* @param currentQualifiedName qualifiedName
* @return qualified name without spaces
*/
private String removeSpaces(String currentQualifiedName)
{
String noSpaces = currentQualifiedName.replaceAll("\\s+","");
return noSpaces.replaceAll("[\\[\\](){}]", "");
}


/**
* Constructing the mermaid graph for the retrieved asset.
*
* @param assetLineageGraph retrieved asset graph
* @return mermaid string
*/
private String getAssetLineageMermaidGraph(AssetLineageGraph assetLineageGraph)
{
StringBuilder mermaidGraph = new StringBuilder();

mermaidGraph.append("---\n");
mermaidGraph.append("title: Lineage Graph for Asset - ");
mermaidGraph.append(assetLineageGraph.getProperties().getDisplayName());
mermaidGraph.append(" [");
mermaidGraph.append(assetLineageGraph.getElementHeader().getGUID());
mermaidGraph.append("]\n---\nflowchart TD\n%%{init: {\"flowchart\": {\"htmlLabels\": false}} }%%\n\n");

List<String> usedNodeNames = new ArrayList<>();

String currentNodeName = assetLineageGraph.getElementHeader().getGUID();
String currentDisplayName = assetLineageGraph.getProperties().getDisplayName();

appendMermaidNode(mermaidGraph,
currentNodeName,
currentDisplayName,
assetLineageGraph.getElementHeader().getType().getTypeName());

usedNodeNames.add(currentNodeName);

if (assetLineageGraph.getLinkedAssets() != null)
{
for (AssetLineageGraphNode node : assetLineageGraph.getLinkedAssets())
{
if (node != null)
{
currentNodeName = node.getElementHeader().getGUID();
currentDisplayName = node.getProperties().getDisplayName();
if (currentDisplayName == null)
{
currentDisplayName = node.getProperties().getName();
}
if (currentDisplayName == null)
{
currentDisplayName = node.getProperties().getResourceName();
}
if (currentDisplayName == null)
{
currentDisplayName = node.getProperties().getQualifiedName();
}

if (!usedNodeNames.contains(currentNodeName))
{
appendMermaidNode(mermaidGraph,
currentNodeName,
currentDisplayName,
node.getElementHeader().getType().getTypeName());

usedNodeNames.add(currentNodeName);
}
}
}

for (AssetLineageGraphRelationship line : assetLineageGraph.getLineageRelationships())
{
if (line != null)
{
mermaidGraph.append(line.getEnd1AssetGUID());
mermaidGraph.append("-->|");
mermaidGraph.append(this.getListLabel(line.getRelationshipTypes()));
mermaidGraph.append("|");
mermaidGraph.append(line.getEnd2AssetGUID());
mermaidGraph.append("\n");
}
}
}

return mermaidGraph.toString();
}


/**
* Convert an array into a comma separated string.
*
* @param labelValues array of labels
* @return string value without square brackets (Mermaid does not allow them)
*/
private String getListLabel(List<String> labelValues)
{
if (labelValues != null)
{
StringBuilder stringBuilder = new StringBuilder();
boolean firstValue = true;

for (String labelValue : labelValues)
{
if (! firstValue)
{
stringBuilder.append(",");
}

firstValue = false;
stringBuilder.append(labelValue);
}

return stringBuilder.toString();
}

return "";
}


/**
* Return all the elements that are linked to an asset using lineage relationships. The relationships are
* retrieved both from the asset, and the anchored schema elements
Expand Down Expand Up @@ -624,7 +402,9 @@ public AssetLineageGraphResponse getAssetLineageGraph(String serverName,
}

assetLineageGraph.setLineageRelationships(this.deDupLineageRelationships(lineageRelationships));
assetLineageGraph.setMermaidGraph(this.getAssetLineageMermaidGraph(assetLineageGraph));

AssetLineageGraphMermaidGraphBuilder graphBuilder = new AssetLineageGraphMermaidGraphBuilder(assetLineageGraph);
assetLineageGraph.setMermaidGraph(graphBuilder.getMermaidGraph());

response.setAssetLineageGraph(assetLineageGraph);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2005,7 +2005,7 @@ protected List<RelatedMetadataElementSummary> getRelatedElements(String
UserNotAuthorizedException,
PropertyServerException
{
List<RelatedMetadataElement> relatedMetadataElements = openMetadataStoreClient.getRelatedMetadataElements(userId,
RelatedMetadataElementList relatedMetadataElements = openMetadataStoreClient.getRelatedMetadataElements(userId,
startingElementGUID,
startingAtEnd,
relationshipTypeName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
import org.odpi.openmetadata.frameworks.connectors.ffdc.InvalidParameterException;
import org.odpi.openmetadata.frameworks.connectors.ffdc.PropertyServerException;
import org.odpi.openmetadata.frameworks.connectors.ffdc.UserNotAuthorizedException;
import org.odpi.openmetadata.frameworks.governanceaction.properties.OpenMetadataElement;
import org.odpi.openmetadata.frameworks.governanceaction.properties.OpenMetadataRelationship;
import org.odpi.openmetadata.frameworks.governanceaction.properties.RelatedMetadataElement;
import org.odpi.openmetadata.frameworks.governanceaction.properties.*;
import org.odpi.openmetadata.frameworks.governanceaction.search.ElementProperties;
import org.odpi.openmetadata.frameworks.governanceaction.search.PropertyComparisonOperator;
import org.odpi.openmetadata.frameworks.governanceaction.search.PropertyValue;
Expand Down Expand Up @@ -2602,7 +2600,7 @@ public List<RelatedMetadataElementSummary> getRelatedElements(String
{
final String methodName = "getRelatedElements";

List<RelatedMetadataElement> relatedMetadataElements;
RelatedMetadataElementList relatedMetadataElements;

if (findProperties == null)
{
Expand Down Expand Up @@ -2641,7 +2639,7 @@ public List<RelatedMetadataElementSummary> getRelatedElements(String
{
List<RelatedMetadataElementSummary> results = new ArrayList<>();

for (RelatedMetadataElement relatedMetadataElement : relatedMetadataElements)
for (RelatedMetadataElement relatedMetadataElement : relatedMetadataElements.getElementList())
{
if (relatedMetadataElement != null)
{
Expand Down Expand Up @@ -2705,7 +2703,7 @@ public List<RelatedMetadataElementSummary> getRelatedElementsWithPropertyValue(S
invalidParameterHandler.validateObject(findProperties.getPropertyValue(), propertyValueProperty, methodName);
invalidParameterHandler.validateObject(findProperties.getPropertyNames(), propertyNamesProperty, methodName);

List<RelatedMetadataElement> relatedMetadataElements = openMetadataStoreClient.getRelatedMetadataElements(userId,
RelatedMetadataElementList relatedMetadataElements = openMetadataStoreClient.getRelatedMetadataElements(userId,
elementGUID,
startingAtEnd,
relationshipTypeName,
Expand All @@ -2723,7 +2721,7 @@ public List<RelatedMetadataElementSummary> getRelatedElementsWithPropertyValue(S
{
List<RelatedMetadataElementSummary> results = new ArrayList<>();

for (RelatedMetadataElement relatedMetadataElement : relatedMetadataElements)
for (RelatedMetadataElement relatedMetadataElement : relatedMetadataElements.getElementList())
{
if (relatedMetadataElement != null)
{
Expand Down Expand Up @@ -2807,7 +2805,7 @@ public List<RelatedMetadataElementSummary> findRelatedElementsWithPropertyValue(
invalidParameterHandler.validateObject(findProperties.getPropertyValue(), propertyValueProperty, methodName);
invalidParameterHandler.validateObject(findProperties.getPropertyNames(), propertyNamesProperty, methodName);

List<RelatedMetadataElement> relatedMetadataElements = openMetadataStoreClient.getRelatedMetadataElements(userId,
RelatedMetadataElementList relatedMetadataElements = openMetadataStoreClient.getRelatedMetadataElements(userId,
elementGUID,
startingAtEnd,
relationshipTypeName,
Expand All @@ -2825,7 +2823,7 @@ public List<RelatedMetadataElementSummary> findRelatedElementsWithPropertyValue(
{
List<RelatedMetadataElementSummary> results = new ArrayList<>();

for (RelatedMetadataElement relatedMetadataElement : relatedMetadataElements)
for (RelatedMetadataElement relatedMetadataElement : relatedMetadataElements.getElementList())
{
if (relatedMetadataElement != null)
{
Expand Down Expand Up @@ -2893,7 +2891,7 @@ public List<MetadataRelationshipSummary> getRelationships(String use
{
final String methodName = "getRelationships";

List<OpenMetadataRelationship> openMetadataRelationships;
OpenMetadataRelationshipList openMetadataRelationships;

if (findProperties == null)
{
Expand Down Expand Up @@ -2967,7 +2965,7 @@ public List<MetadataRelationshipSummary> getRelationshipsWithPropertyValue(Strin
{
final String methodName = "getRelationships";

List<OpenMetadataRelationship> openMetadataRelationships;
OpenMetadataRelationshipList openMetadataRelationships;

if (findProperties == null)
{
Expand Down Expand Up @@ -3044,7 +3042,7 @@ public List<MetadataRelationshipSummary> findRelationshipsWithPropertyValue(Stri
{
final String methodName = "getRelationships";

List<OpenMetadataRelationship> openMetadataRelationships;
OpenMetadataRelationshipList openMetadataRelationships;

if (findProperties == null)
{
Expand Down
Loading

0 comments on commit f851ae6

Please sign in to comment.