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

toolkit.plugins.reporters.gitlab-reporter.40.0.0.source-code.GitLabLicenseModelMapper.kt Maven / Gradle / Ivy

/*
 * Copyright (C) 2020 The ORT Project Authors (see )
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 * License-Filename: LICENSE
 */

package org.ossreviewtoolkit.plugins.reporters.gitlab

import org.apache.logging.log4j.kotlin.logger

import org.ossreviewtoolkit.model.Identifier
import org.ossreviewtoolkit.model.OrtResult
import org.ossreviewtoolkit.model.Package
import org.ossreviewtoolkit.plugins.reporters.gitlab.GitLabLicenseModel.Dependency
import org.ossreviewtoolkit.plugins.reporters.gitlab.GitLabLicenseModel.License
import org.ossreviewtoolkit.utils.spdx.SpdxLicense
import org.ossreviewtoolkit.utils.spdx.SpdxLicenseIdExpression
import org.ossreviewtoolkit.utils.spdx.SpdxLicenseWithExceptionExpression
import org.ossreviewtoolkit.utils.spdx.SpdxSingleLicenseExpression

/**
 * Maps an [OrtResult] to a [GitLabLicenseModel].
 */
internal object GitLabLicenseModelMapper {
    fun map(ortResult: OrtResult, skipExcluded: Boolean): GitLabLicenseModel {
        val packagesWithDefinitionFilePaths = ortResult.getTargetPackagesWithDefinitionFiles(skipExcluded)

        return GitLabLicenseModel(
            licenses = packagesWithDefinitionFilePaths.keys.toLicenses(),
            dependencies = packagesWithDefinitionFilePaths.toDependencies()
        )
    }
}

private fun Collection.toLicenses(): Set {
    val decomposedLicenses = flatMapTo(mutableSetOf()) { pkg ->
        pkg.declaredLicensesProcessed.decompose()
    }

    return decomposedLicenses.mapTo(mutableSetOf()) { singleLicenseExpression ->
        License(
            id = singleLicenseExpression.simpleLicense(),
            name = singleLicenseExpression.toLicenseName(),
            url = singleLicenseExpression.getLicenseUrl().orEmpty()
        )
    }
}

private fun Map>.toDependencies(): List =
    map { (pkg, definitionFilePaths) ->
        pkg.toDependency(definitionFilePaths)
    }

private fun OrtResult.getTargetPackagesWithDefinitionFiles(skipExcluded: Boolean): Map> {
    val result = mutableMapOf>()

    val packages = getPackages().associate { it.metadata.id to it.metadata }

    getProjects(omitExcluded = skipExcluded).forEach { project ->
        val definitionFilePath = project.definitionFilePath

        // Omit non-referenced and maybe also excluded packages:
        dependencyNavigator.projectDependencies(project) { !skipExcluded || !isExcluded(it.id) }.forEach { id ->
            result.getOrPut(id) { mutableListOf() } += definitionFilePath
        }
    }

    return result.filter { it.key in packages.keys }.mapKeys { packages.getValue(it.key) }
}

private fun Package.toDependency(definitionFilePaths: Collection): Dependency =
    Dependency(
        name = id.name,
        version = id.version,
        licenses = declaredLicensesProcessed.decompose().mapTo(mutableSetOf()) { it.toString() },
        path = definitionFilePaths.sorted().joinToString(","),
        packageManager = id.toPackageManagerName()
    )

private fun SpdxSingleLicenseExpression.toLicenseName(): String {
    // TODO: Get the full name also for non-SPDX / ScanCode licenses.
    val spdxLicenseId = when (this) {
        is SpdxLicenseWithExceptionExpression -> license.simpleLicense()
        is SpdxLicenseIdExpression -> simpleLicense()
        else -> ""
    }

    return SpdxLicense.forId(spdxLicenseId)?.fullName.orEmpty()
}

/**
 * Map the [Identifier.type] to the GitLab license model package names. The mapping is based on the examples found
 * under https://gitlab.com/gitlab-org/security-products/license-management/-/tree/f4ec1f1bf826654ab963d32a2d4a2588ecb91c04/spec/fixtures/expected.
 */
private fun Identifier.toPackageManagerName(): String =
    when (type) {
        "Bower" -> "bower"
        "Bundler" -> "bundler"
        "Composer" -> "composer"
        "Conan" -> "conan"
        "GoMod" -> "go"
        "Gradle" -> "gradle"
        "Maven" -> "maven"
        "NPM" -> "npm"
        "NuGet" -> "nuget"
        "PIP" -> "pip"
        "Yarn" -> "yarn"
        else -> type.lowercase().also {
            logger.info { "No GitLab mapping defined for package manager '$type', guessing '$it'." }
        }
    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy