diff --git a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json index ba9f4876ed8ec..9ddc9622e09ef 100644 --- a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json +++ b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json @@ -240,10 +240,6 @@ "spdxElementId" : "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1", "relationshipType" : "GENERATED_FROM", "relatedSpdxElement" : "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1-source-artifact" - }, { - "spdxElementId" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1", - "relationshipType" : "DEPENDS_ON", - "relatedSpdxElement" : "SPDXRef-Package-Maven-fifth-package-group-fifth-package-0.0.1" }, { "spdxElementId" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1", "relationshipType" : "DEPENDS_ON", diff --git a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml index e2ad5bdfedfc6..9eefa75bb61a2 100644 --- a/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml +++ b/plugins/reporters/spdx/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml @@ -241,9 +241,6 @@ relationships: - spdxElementId: "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1" relationshipType: "GENERATED_FROM" relatedSpdxElement: "SPDXRef-Package-Maven-seventh-package-group-seventh-package-0.0.1-source-artifact" -- spdxElementId: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" - relationshipType: "DEPENDS_ON" - relatedSpdxElement: "SPDXRef-Package-Maven-fifth-package-group-fifth-package-0.0.1" - spdxElementId: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" relationshipType: "DEPENDS_ON" relatedSpdxElement: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1" diff --git a/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt b/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt index b01d0de2a9e86..6eef3eca19d1c 100644 --- a/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt +++ b/plugins/reporters/spdx/src/main/kotlin/SpdxDocumentModelMapper.kt @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger import org.apache.logging.log4j.kotlin.Logging +import org.ossreviewtoolkit.model.Identifier import org.ossreviewtoolkit.model.OrtResult import org.ossreviewtoolkit.model.SourceCodeOrigin.ARTIFACT import org.ossreviewtoolkit.model.SourceCodeOrigin.VCS @@ -64,21 +65,21 @@ internal object SpdxDocumentModelMapper : Logging { val projects = ortResult.getProjects(omitExcluded = true, includeSubProjects = false).sortedBy { it.id } val projectPackages = projects.map { project -> - val spdxProjectPackage = project.toPackage().toSpdxPackage( + project.toPackage().toSpdxPackage( SpdxPackageType.PROJECT, licenseInfoResolver, ortResult ) + } - ortResult.getDependencies(project.id, 1).mapTo(relationships) { dependency -> - SpdxRelationship( - spdxElementId = spdxProjectPackage.spdxId, + ortResult.getRootProjectsForFirstLevelDependencies().forEach { (pkgId, rootProjectIds) -> + rootProjectIds.forEach { rootProjectId -> + relationships += SpdxRelationship( + spdxElementId = rootProjectId.toSpdxId(SpdxPackageType.PROJECT), relationshipType = SpdxRelationship.Type.DEPENDS_ON, - relatedSpdxElement = dependency.toSpdxId() + relatedSpdxElement = pkgId.toSpdxId(SpdxPackageType.BINARY_PACKAGE) ) } - - spdxProjectPackage } val files = mutableListOf() @@ -169,3 +170,25 @@ internal object SpdxDocumentModelMapper : Logging { ).addExtractedLicenseInfo(licenseTextProvider) } } + +/** + * Return a mapping from the identifiers of all non-excluded first level dependencies to the identifiers of the + * non-excluded root projects they correspond to. + */ +private fun OrtResult.getRootProjectsForFirstLevelDependencies(): Map> { + val result = mutableMapOf>() + + getProjects(omitExcluded = true).map { it.id }.forEach { rootProjectId -> + val subProjectIds = getDependencies(rootProjectId).filter { isProject(it) && !isExcluded(it) } + + val firstLevelDependencies = (subProjectIds + rootProjectId).flatMapTo(mutableSetOf()) { projectId -> + getDependencies(projectId, maxLevel = 1).filter { isPackage(it) && !isExcluded(it) } + } + + firstLevelDependencies.forEach { pkgId -> + result.getOrPut(pkgId) { mutableSetOf() } += rootProjectId + } + } + + return result +}