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

toolkit.evaluator.36.0.0.source-code.RuleSet.kt Maven / Gradle / Ivy

Go to download

Part of the OSS Review Toolkit (ORT), a suite to automate software compliance checks.

There is a newer version: 40.0.1
Show newest version
/*
 * Copyright (C) 2017 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.evaluator

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

import org.ossreviewtoolkit.model.DependencyNode
import org.ossreviewtoolkit.model.OrtResult
import org.ossreviewtoolkit.model.Package
import org.ossreviewtoolkit.model.Project
import org.ossreviewtoolkit.model.RuleViolation
import org.ossreviewtoolkit.model.licenses.LicenseInfoResolver
import org.ossreviewtoolkit.model.utils.DefaultResolutionProvider
import org.ossreviewtoolkit.model.utils.ResolutionProvider
import org.ossreviewtoolkit.model.utils.createLicenseInfoResolver

/**
 * A set of evaluator [Rule]s, using an [ortResult] as input.
 */
class RuleSet(
    val ortResult: OrtResult,
    val licenseInfoResolver: LicenseInfoResolver,
    val resolutionProvider: ResolutionProvider,
    val projectSourceResolver: SourceTreeResolver
) {
    /**
     * The set of all issues created by the rules of this [RuleSet].
     */
    val violations = mutableSetOf()

    /**
     * A DSL function to configure an [OrtResultRule]. The rule is applied once to [ortResult].
     */
    fun ortResultRule(name: String, configure: OrtResultRule.() -> Unit) {
        OrtResultRule(this, name).apply {
            configure()
            evaluate()
        }
    }

    /**
     * A DSL function to configure an [ProjectSourceRule]. The rule is applied once to [ortResult].
     */
    fun projectSourceRule(name: String, configure: ProjectSourceRule.() -> Unit) {
        ProjectSourceRule(this, name).apply {
            configure()
            evaluate()
        }
    }

    /**
     * A DSL function to configure a [PackageRule]. The rule is applied to each [Package] and [Project] contained in
     * [ortResult].
     */
    fun packageRule(name: String, configure: PackageRule.() -> Unit) {
        val packages = ortResult.getProjects().map { it.toPackage().toCuratedPackage() } + ortResult.getPackages()

        packages.forEach { curatedPackage ->
            val resolvedLicenseInfo = licenseInfoResolver.resolveLicenseInfo(curatedPackage.metadata.id)
            PackageRule(this, name, curatedPackage, resolvedLicenseInfo).apply {
                configure()
                evaluate()
            }
        }
    }

    /**
     * A DSL function to configure a [DependencyRule]. The rule is applied to each [DependencyNode] from the
     * dependency trees contained in [ortResult]. If the same dependency appears multiple times in the same scope, the
     * rule will be applied only once.
     */
    fun dependencyRule(name: String, configure: DependencyRule.() -> Unit) {
        fun traverse(
            node: DependencyNode,
            ancestors: List,
            level: Int,
            scopeName: String,
            project: Project,
            visitedPackages: MutableSet
        ) {
            if (node in visitedPackages) {
                logger.debug { "Skipping rule $name for already visited dependency ${node.id.toCoordinates()}." }
                return
            }

            visitedPackages += node

            val curatedPackage = ortResult.getPackage(node.id)
                ?: ortResult.getProject(node.id)?.toPackage()?.toCuratedPackage()

            if (curatedPackage == null) {
                logger.warn { "Could not find package for dependency ${node.id.toCoordinates()}, skipping rule $name." }
            } else {
                val resolvedLicenseInfo = licenseInfoResolver.resolveLicenseInfo(curatedPackage.metadata.id)

                DependencyRule(
                    this,
                    name,
                    curatedPackage,
                    resolvedLicenseInfo,
                    node,
                    ancestors,
                    level,
                    scopeName,
                    project
                ).apply {
                    configure()
                    evaluate()
                }
            }

            node.visitDependencies { dependencies ->
                dependencies.forEach { dependency ->
                    traverse(
                        dependency,
                        listOf(node.getStableReference()) + ancestors,
                        level + 1,
                        scopeName,
                        project,
                        visitedPackages
                    )
                }
            }
        }

        ortResult.getProjects().forEach { project ->
            ortResult.dependencyNavigator.scopeNames(project).forEach { scopeName ->
                val visitedPackages = mutableSetOf()
                ortResult.dependencyNavigator.directDependencies(project, scopeName).forEach { dependency ->
                    traverse(dependency, emptyList(), 0, scopeName, project, visitedPackages)
                }
            }
        }
    }
}

/**
 * A DSL function to configure a [RuleSet].
 */
fun ruleSet(
    ortResult: OrtResult,
    licenseInfoResolver: LicenseInfoResolver = ortResult.createLicenseInfoResolver(),
    resolutionProvider: ResolutionProvider = DefaultResolutionProvider.create(),
    projectSourceResolver: SourceTreeResolver = SourceTreeResolver.forRemoteRepository(
        ortResult.repository.vcsProcessed
    ),
    configure: RuleSet.() -> Unit = { }
) = RuleSet(ortResult, licenseInfoResolver, resolutionProvider, projectSourceResolver).apply(configure)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy