All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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