diff --git a/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json b/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json index ea5b436513a10..97736f2281fc3 100644 --- a/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json +++ b/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.json @@ -18,9 +18,9 @@ "licenseId" : "LicenseRef-scancode-srgb" } ], "documentNamespace" : "", - "documentDescribes" : [ "SPDXRef-Package-0-root-package" ], + "documentDescribes" : [ "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" ], "packages" : [ { - "SPDXID" : "SPDXRef-Package-0-root-package", + "SPDXID" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1", "copyrightText" : "NOASSERTION", "downloadLocation" : "NOASSERTION", "filesAnalyzed" : false, @@ -29,7 +29,7 @@ "licenseDeclared" : "NOASSERTION", "name" : "Root package" }, { - "SPDXID" : "SPDXRef-Package-1-first-package", + "SPDXID" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1", "copyrightText" : "Copyright 2020 Some copyright holder in VCS\nCopyright 2020 Some copyright holder in source artifact\nCopyright 2020 Some other copyright holder in source artifact", "downloadLocation" : "https://some-host/first-package.jar", "externalRefs" : [ { @@ -45,7 +45,7 @@ "summary" : "A package with all supported attributes set, with a VCS URL containing a user name, and with a scan result containing two copyright finding matched to a license finding.", "versionInfo" : "0.0.1" }, { - "SPDXID" : "SPDXRef-Package-2-first-package-vcs", + "SPDXID" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-vcs", "copyrightText" : "Copyright 2020 Some copyright holder in VCS\nCopyright 2020 Some copyright holder in source artifact\nCopyright 2020 Some other copyright holder in source artifact", "downloadLocation" : "git+ssh://github.com/path/first-package-repo.git@deadbeef#project-path", "externalRefs" : [ { @@ -64,7 +64,7 @@ "summary" : "A package with all supported attributes set, with a VCS URL containing a user name, and with a scan result containing two copyright finding matched to a license finding.", "versionInfo" : "0.0.1" }, { - "SPDXID" : "SPDXRef-Package-3-first-package-source-artifact", + "SPDXID" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-source-artifact", "copyrightText" : "Copyright 2020 Some copyright holder in VCS\nCopyright 2020 Some copyright holder in source artifact\nCopyright 2020 Some other copyright holder in source artifact", "downloadLocation" : "https://some-host/first-package-sources.jar", "externalRefs" : [ { @@ -83,7 +83,7 @@ "summary" : "A package with all supported attributes set, with a VCS URL containing a user name, and with a scan result containing two copyright finding matched to a license finding.", "versionInfo" : "0.0.1" }, { - "SPDXID" : "SPDXRef-Package-4-fourth-package", + "SPDXID" : "SPDXRef-Package-Maven-fourth-package-group-fourth-package-0.0.1", "copyrightText" : "NONE", "downloadLocation" : "NONE", "externalRefs" : [ { @@ -99,7 +99,7 @@ "summary" : "A package with partially mapped declared license.", "versionInfo" : "0.0.1" }, { - "SPDXID" : "SPDXRef-Package-5-second-package", + "SPDXID" : "SPDXRef-Package-Maven-second-package-group-second-package-0.0.1", "copyrightText" : "NONE", "downloadLocation" : "NONE", "externalRefs" : [ { @@ -115,7 +115,7 @@ "summary" : "A package with minimal attributes set.", "versionInfo" : "0.0.1" }, { - "SPDXID" : "SPDXRef-Package-6-sixth-package", + "SPDXID" : "SPDXRef-Package-Maven-sixth-package-group-sixth-package-0.0.1", "copyrightText" : "NONE", "downloadLocation" : "NONE", "externalRefs" : [ { @@ -131,7 +131,7 @@ "summary" : "A package with non-SPDX license IDs in the declared and concluded license.", "versionInfo" : "0.0.1" }, { - "SPDXID" : "SPDXRef-Package-7-third-package", + "SPDXID" : "SPDXRef-Package-Maven-third-package-group-third-package-0.0.1", "copyrightText" : "NONE", "downloadLocation" : "NONE", "externalRefs" : [ { @@ -148,32 +148,32 @@ "versionInfo" : "0.0.1" } ], "relationships" : [ { - "spdxElementId" : "SPDXRef-Package-1-first-package", + "spdxElementId" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1", "relationshipType" : "DEPENDENCY_OF", - "relatedSpdxElement" : "SPDXRef-Package-0-root-package" + "relatedSpdxElement" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" }, { - "spdxElementId" : "SPDXRef-Package-1-first-package", + "spdxElementId" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1", "relationshipType" : "GENERATED_FROM", - "relatedSpdxElement" : "SPDXRef-Package-2-first-package-vcs" + "relatedSpdxElement" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-vcs" }, { - "spdxElementId" : "SPDXRef-Package-1-first-package", + "spdxElementId" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1", "relationshipType" : "GENERATED_FROM", - "relatedSpdxElement" : "SPDXRef-Package-3-first-package-source-artifact" + "relatedSpdxElement" : "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-source-artifact" }, { - "spdxElementId" : "SPDXRef-Package-4-fourth-package", + "spdxElementId" : "SPDXRef-Package-Maven-fourth-package-group-fourth-package-0.0.1", "relationshipType" : "DEPENDENCY_OF", - "relatedSpdxElement" : "SPDXRef-Package-0-root-package" + "relatedSpdxElement" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" }, { - "spdxElementId" : "SPDXRef-Package-5-second-package", + "spdxElementId" : "SPDXRef-Package-Maven-second-package-group-second-package-0.0.1", "relationshipType" : "DEPENDENCY_OF", - "relatedSpdxElement" : "SPDXRef-Package-0-root-package" + "relatedSpdxElement" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" }, { - "spdxElementId" : "SPDXRef-Package-6-sixth-package", + "spdxElementId" : "SPDXRef-Package-Maven-sixth-package-group-sixth-package-0.0.1", "relationshipType" : "DEPENDENCY_OF", - "relatedSpdxElement" : "SPDXRef-Package-0-root-package" + "relatedSpdxElement" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" }, { - "spdxElementId" : "SPDXRef-Package-7-third-package", + "spdxElementId" : "SPDXRef-Package-Maven-third-package-group-third-package-0.0.1", "relationshipType" : "DEPENDENCY_OF", - "relatedSpdxElement" : "SPDXRef-Package-0-root-package" + "relatedSpdxElement" : "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" } ] } \ No newline at end of file diff --git a/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml b/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml index 65cdf8ce8d80f..408ec885aa234 100644 --- a/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml +++ b/reporter/src/funTest/assets/spdx-document-reporter-expected-output.spdx.yml @@ -28,9 +28,9 @@ hasExtractedLicensingInfos: licenseId: "LicenseRef-scancode-srgb" documentNamespace: "" documentDescribes: -- "SPDXRef-Package-0-root-package" +- "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" packages: -- SPDXID: "SPDXRef-Package-0-root-package" +- SPDXID: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" copyrightText: "NOASSERTION" downloadLocation: "NOASSERTION" filesAnalyzed: false @@ -38,7 +38,7 @@ packages: licenseConcluded: "NOASSERTION" licenseDeclared: "NOASSERTION" name: "Root package" -- SPDXID: "SPDXRef-Package-1-first-package" +- SPDXID: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1" copyrightText: "Copyright 2020 Some copyright holder in VCS\nCopyright 2020 Some\ \ copyright holder in source artifact\nCopyright 2020 Some other copyright holder\ \ in source artifact" @@ -56,7 +56,7 @@ packages: \ a user name, and with a scan result containing two copyright finding matched\ \ to a license finding." versionInfo: "0.0.1" -- SPDXID: "SPDXRef-Package-2-first-package-vcs" +- SPDXID: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-vcs" copyrightText: "Copyright 2020 Some copyright holder in VCS\nCopyright 2020 Some\ \ copyright holder in source artifact\nCopyright 2020 Some other copyright holder\ \ in source artifact" @@ -76,7 +76,7 @@ packages: \ a user name, and with a scan result containing two copyright finding matched\ \ to a license finding." versionInfo: "0.0.1" -- SPDXID: "SPDXRef-Package-3-first-package-source-artifact" +- SPDXID: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-source-artifact" copyrightText: "Copyright 2020 Some copyright holder in VCS\nCopyright 2020 Some\ \ copyright holder in source artifact\nCopyright 2020 Some other copyright holder\ \ in source artifact" @@ -96,7 +96,7 @@ packages: \ a user name, and with a scan result containing two copyright finding matched\ \ to a license finding." versionInfo: "0.0.1" -- SPDXID: "SPDXRef-Package-4-fourth-package" +- SPDXID: "SPDXRef-Package-Maven-fourth-package-group-fourth-package-0.0.1" copyrightText: "NONE" downloadLocation: "NONE" externalRefs: @@ -110,7 +110,7 @@ packages: name: "fourth-package" summary: "A package with partially mapped declared license." versionInfo: "0.0.1" -- SPDXID: "SPDXRef-Package-5-second-package" +- SPDXID: "SPDXRef-Package-Maven-second-package-group-second-package-0.0.1" copyrightText: "NONE" downloadLocation: "NONE" externalRefs: @@ -124,7 +124,7 @@ packages: name: "second-package" summary: "A package with minimal attributes set." versionInfo: "0.0.1" -- SPDXID: "SPDXRef-Package-6-sixth-package" +- SPDXID: "SPDXRef-Package-Maven-sixth-package-group-sixth-package-0.0.1" copyrightText: "NONE" downloadLocation: "NONE" externalRefs: @@ -138,7 +138,7 @@ packages: name: "sixth-package" summary: "A package with non-SPDX license IDs in the declared and concluded license." versionInfo: "0.0.1" -- SPDXID: "SPDXRef-Package-7-third-package" +- SPDXID: "SPDXRef-Package-Maven-third-package-group-third-package-0.0.1" copyrightText: "NONE" downloadLocation: "NONE" externalRefs: @@ -153,24 +153,24 @@ packages: summary: "A package with only unmapped declared license." versionInfo: "0.0.1" relationships: -- spdxElementId: "SPDXRef-Package-1-first-package" +- spdxElementId: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1" relationshipType: "DEPENDENCY_OF" - relatedSpdxElement: "SPDXRef-Package-0-root-package" -- spdxElementId: "SPDXRef-Package-1-first-package" + relatedSpdxElement: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" +- spdxElementId: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1" relationshipType: "GENERATED_FROM" - relatedSpdxElement: "SPDXRef-Package-2-first-package-vcs" -- spdxElementId: "SPDXRef-Package-1-first-package" + relatedSpdxElement: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-vcs" +- spdxElementId: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1" relationshipType: "GENERATED_FROM" - relatedSpdxElement: "SPDXRef-Package-3-first-package-source-artifact" -- spdxElementId: "SPDXRef-Package-4-fourth-package" + relatedSpdxElement: "SPDXRef-Package-Maven-first-package-group-first-package-0.0.1-source-artifact" +- spdxElementId: "SPDXRef-Package-Maven-fourth-package-group-fourth-package-0.0.1" relationshipType: "DEPENDENCY_OF" - relatedSpdxElement: "SPDXRef-Package-0-root-package" -- spdxElementId: "SPDXRef-Package-5-second-package" + relatedSpdxElement: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" +- spdxElementId: "SPDXRef-Package-Maven-second-package-group-second-package-0.0.1" relationshipType: "DEPENDENCY_OF" - relatedSpdxElement: "SPDXRef-Package-0-root-package" -- spdxElementId: "SPDXRef-Package-6-sixth-package" + relatedSpdxElement: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" +- spdxElementId: "SPDXRef-Package-Maven-sixth-package-group-sixth-package-0.0.1" relationshipType: "DEPENDENCY_OF" - relatedSpdxElement: "SPDXRef-Package-0-root-package" -- spdxElementId: "SPDXRef-Package-7-third-package" + relatedSpdxElement: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" +- spdxElementId: "SPDXRef-Package-Maven-third-package-group-third-package-0.0.1" relationshipType: "DEPENDENCY_OF" - relatedSpdxElement: "SPDXRef-Package-0-root-package" + relatedSpdxElement: "SPDXRef-Project-Maven-first-project-group-first-project-name-0.0.1" diff --git a/reporter/src/main/kotlin/reporters/spdx/SpdxDocumentModelMapper.kt b/reporter/src/main/kotlin/reporters/spdx/SpdxDocumentModelMapper.kt index 8b62392087b8c..ea82ee6b7f536 100644 --- a/reporter/src/main/kotlin/reporters/spdx/SpdxDocumentModelMapper.kt +++ b/reporter/src/main/kotlin/reporters/spdx/SpdxDocumentModelMapper.kt @@ -49,6 +49,7 @@ import org.ossreviewtoolkit.utils.spdx.model.SpdxExtractedLicenseInfo import org.ossreviewtoolkit.utils.spdx.model.SpdxPackage import org.ossreviewtoolkit.utils.spdx.model.SpdxPackageVerificationCode import org.ossreviewtoolkit.utils.spdx.model.SpdxRelationship +import org.ossreviewtoolkit.utils.spdx.toSpdxId /** * A class for mapping [OrtResult]s to [SpdxDocument]s. @@ -66,12 +67,12 @@ object SpdxDocumentModelMapper { licenseTextProvider: LicenseTextProvider, params: SpdxDocumentParams ): SpdxDocument { - val spdxPackageIdGenerator = SpdxPackageIdGenerator() val packages = mutableListOf() val relationships = mutableListOf() + val rootPackages = ortResult.getProjects(omitExcluded = true, includeSubProjects = false) val rootPackage = SpdxPackage( - spdxId = spdxPackageIdGenerator.nextId("root-package"), + spdxId = rootPackages.first().id.toSpdxId("Project"), copyrightText = SpdxConstants.NOASSERTION, downloadLocation = SpdxConstants.NOASSERTION, filesAnalyzed = false, @@ -87,7 +88,7 @@ object SpdxDocumentModelMapper { val pkg = curatedPackage.pkg val binaryPackage = SpdxPackage( - spdxId = spdxPackageIdGenerator.nextId(pkg.id.name), + spdxId = pkg.id.toSpdxId("Package"), copyrightText = getSpdxCopyrightText(licenseInfoResolver, pkg.id), downloadLocation = pkg.binaryArtifact.url.nullOrBlankToSpdxNone(), externalRefs = pkg.toSpdxExternalReferences(), @@ -123,7 +124,7 @@ object SpdxDocumentModelMapper { // TODO: The copyright text contains copyrights from all scan results. val vcsPackage = binaryPackage.copy( - spdxId = spdxPackageIdGenerator.nextId("${pkg.id.name}-vcs"), + spdxId = "${binaryPackage.spdxId}-vcs", filesAnalyzed = filesAnalyzed, downloadLocation = pkg.vcsProcessed.toSpdxDownloadLocation(provenance?.resolvedRevision), licenseConcluded = SpdxConstants.NOASSERTION, @@ -154,7 +155,7 @@ object SpdxDocumentModelMapper { // TODO: The copyright text contains copyrights from all scan results. val sourceArtifactPackage = binaryPackage.copy( - spdxId = spdxPackageIdGenerator.nextId("${curatedPackage.pkg.id.name}-source-artifact"), + spdxId = "${binaryPackage.spdxId}-source-artifact", filesAnalyzed = filesAnalyzed, downloadLocation = curatedPackage.pkg.sourceArtifact.url.nullOrBlankToSpdxNone(), licenseConcluded = SpdxConstants.NOASSERTION, @@ -190,18 +191,6 @@ object SpdxDocumentModelMapper { } } -private class SpdxPackageIdGenerator { - var nextPackageIndex = 0 - - fun nextId(name: String): String = - buildString { - append("${REF_PREFIX}Package-${nextPackageIndex++}") - if (name.isNotBlank()) { - append("-$name") - } - } -} - private fun getSpdxCopyrightText( licenseInfoResolver: LicenseInfoResolver, id: Identifier @@ -215,6 +204,11 @@ private fun getSpdxCopyrightText( } } +/** + * Convert an [Identifier]'s coordinates to an SPDX reference ID with the specified [infix]. + */ +private fun Identifier.toSpdxId(infix: String) = "$REF_PREFIX$infix-${toCoordinates()}".toSpdxId() + private fun Package.toSpdxExternalReferences(): List { val externalRefs = mutableListOf()