com.metaeffekt.artifact.analysis.bom.spdx.relationship.RelationshipGraph Maven / Gradle / Ivy
The newest version!
package com.metaeffekt.artifact.analysis.bom.spdx.relationship;
import lombok.extern.slf4j.Slf4j;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.model.AssetMetaData;
import org.metaeffekt.core.inventory.processor.model.Constants;
import org.metaeffekt.core.inventory.processor.model.Inventory;
import org.spdx.library.model.enumerations.RelationshipType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This class implements a graph structure which holds an indefinite amount of nodes and edges. The graph maps inventory
* artifacts and their relationships to one another and is meant to be used in conjunction with the SPDX standard.
*/
@Slf4j
public class RelationshipGraph {
private final Map nodes;
private final List relationships;
public RelationshipGraph(Inventory inventory, Map assetToArtifactMap) {
this.nodes = new HashMap<>();
this.relationships = new ArrayList<>();
mapRelationships(inventory, assetToArtifactMap);
}
public void addNode(RelationshipGraphNode node) {
nodes.put(node.getId(), node);
}
public void addRelationship(String fromId, String toId, RelationshipType relationshipType) {
RelationshipGraphNode fromNode = nodes.get(fromId);
RelationshipGraphNode toNode = nodes.get(toId);
boolean edgeExists = false;
for (RelationshipGraphEdge edge : relationships) {
if (edge.getFromNode().getId().equals(fromId)) {
edge.addToNode(toNode);
edgeExists = true;
}
}
if (!edgeExists) {
List toNodes = new ArrayList<>();
toNodes.add(toNode);
relationships.add(new RelationshipGraphEdge(fromNode, toNodes, relationshipType));
}
}
public List getAllRelationships() {
return relationships;
}
private void mapRelationships(Inventory inventory, Map assetToArtifactMap) {
List assetMetaDataList = inventory.getAssetMetaData();
List artifactList = inventory.getArtifacts();
addNode(new RelationshipGraphNode("DOCUMENT"));
// Prepare all Nodes for further relationship tracking.
artifactList.forEach(artifact -> addNode(new RelationshipGraphNode(artifact.getId())));
assetMetaDataList.forEach(assetMetaData -> {
if (!assetToArtifactMap.containsKey(assetMetaData)) {
addNode(new RelationshipGraphNode(assetMetaData.get(AssetMetaData.Attribute.ASSET_ID)));
}
});
// If no assets exist fallback to adding all artifacts
if (assetMetaDataList.isEmpty()) {
for (Artifact artifact : artifactList) {
addRelationship("DOCUMENT", artifact.getId(), RelationshipType.DESCRIBES);
}
return;
}
// If there is no relationship hierarchy at all, add DOCUMENT DESCRIBES relationships for all assets.
if (assetToArtifactMap.isEmpty()) {
for (AssetMetaData assetMetaData : assetMetaDataList) {
addRelationship("DOCUMENT", assetMetaData.get(Constants.KEY_ASSET_ID), RelationshipType.DESCRIBES);
}
}
for (Artifact artifact : artifactList) {
boolean hasContainsMarker = false;
String describesId = null;
for (AssetMetaData assetMetaData : assetMetaDataList) {
String assetId = assetMetaData.get(AssetMetaData.Attribute.ASSET_ID);
// Add a contains relationship if an artifact is marked as CONTAINS in relation to a AssetMetaData element
if (artifact.get(assetId) != null && artifact.get(assetId).equals(Constants.MARKER_CONTAINS)) {
if (!assetToArtifactMap.containsKey(assetMetaData)) {
addRelationship(assetId, artifact.getId(), RelationshipType.CONTAINS);
} else {
addRelationship(assetToArtifactMap.get(assetMetaData).getId(), artifact.getId(),
RelationshipType.CONTAINS);
}
hasContainsMarker = true;
// Prepares for DESCRIBES relationships from DOCUMENT to either an artifact (if an artifact is present which
// represents an asset) or an asset.
} else if ((artifact.get(assetId) != null && artifact.get(assetId).equals(Constants.MARKER_CROSS))) {
if (!assetToArtifactMap.containsKey(assetMetaData)) {
describesId = assetId;
} else {
describesId = assetToArtifactMap.get(assetMetaData).getId();
}
}
}
// Adds the prepared DESCRIBES relationship.
if (describesId != null && !hasContainsMarker) {
addRelationship("DOCUMENT", describesId, RelationshipType.DESCRIBES);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy