From 381ce7598fdb80200d394aa008c547895a1bc361 Mon Sep 17 00:00:00 2001 From: Jan-Niclas Struewer <j.n.struewer@gmail.com> Date: Wed, 31 Jul 2024 14:27:01 +0200 Subject: [PATCH] breaking: backup commit to prepare merge from dev branch. Branch is not in a working state! --- .../iem/app/kpi/dto/KPIHierarchyEdgeDto.kt | 8 - .../iem/app/kpi/dto/KpiCalculationDto.kt | 75 +---- .../iem/app/kpi/entity/KPIEntity.kt | 19 +- .../iem/app/kpi/enumeration/KpiKind.kt | 78 ++--- .../iem/app/kpi/service/KPIService.kt | 312 +++++++++--------- .../AggregationKPICalculationStrategy.kt | 90 ++--- .../strategy/MaximumKPICalculationStrategy.kt | 33 +- .../strategy/RatioKPICalculationStrategy.kt | 28 +- .../controller/RepositoryController.kt | 3 +- .../iem/app/repository/dto/RawKpiDto.kt | 5 +- .../dto/RawValueKpiCreateDtoExtension.kt | 4 +- .../repository/service/RepositoryService.kt | 6 +- .../iem/app/tool/enumeration/ToolType.kt | 34 +- .../iem/app/toolRun/service/ToolRunService.kt | 2 +- .../AggregationKPICalculationStrategyTest.kt | 191 +++++------ .../iem/kpiCalculator/adapter/KpiAdapter.kt | 4 +- .../kpiCalculator/adapter/cve/CveAdapter.kt | 12 +- .../adapter/cve/CveAdapterTest.kt | 2 +- .../iem/kpiCalculator/core/KpiCalculator.kt | 1 + .../core/hierarchy/KPIHierarchyEdgeDto.kt | 8 + .../core/hierarchy/KpiCalculationNode.kt | 48 +++ .../core}/strategy/KPICalculationStrategy.kt | 4 +- .../RawValueKPICalculationStrategy.kt | 6 +- .../model/adapter/AdapterResult.kt | 4 +- .../model/kpi/RawValueKpiCreateDto.kt | 3 - .../kpiCalculator/model/kpi/RawValueKpiDto.kt | 3 + .../model/kpi/hierarchy/KpiHierarchy.kt | 1 + .../{KpiNodeTest.kt => KpiHierarchyTest.kt} | 16 +- 28 files changed, 513 insertions(+), 487 deletions(-) delete mode 100644 app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KPIHierarchyEdgeDto.kt create mode 100644 kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KPIHierarchyEdgeDto.kt create mode 100644 kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KpiCalculationNode.kt rename {app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi => kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core}/strategy/KPICalculationStrategy.kt (52%) rename {app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi => kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core}/strategy/RawValueKPICalculationStrategy.kt (57%) delete mode 100644 kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiCreateDto.kt create mode 100644 kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiDto.kt rename kpi-calculator/model/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/{KpiNodeTest.kt => KpiHierarchyTest.kt} (82%) diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KPIHierarchyEdgeDto.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KPIHierarchyEdgeDto.kt deleted file mode 100644 index 07b2f8a9..00000000 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KPIHierarchyEdgeDto.kt +++ /dev/null @@ -1,8 +0,0 @@ -package de.fraunhofer.iem.app.kpi.dto - -data class KPIHierarchyEdgeDto( - val from: KpiCalculationDto, - val to: KpiCalculationDto, - val plannedWeight: Double, - val actualWeight: Double = plannedWeight -) diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KpiCalculationDto.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KpiCalculationDto.kt index af8f7f74..8378ebe2 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KpiCalculationDto.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/dto/KpiCalculationDto.kt @@ -1,68 +1,21 @@ package de.fraunhofer.iem.app.kpi.dto import de.fraunhofer.iem.app.kpi.enumeration.toViewModel -import de.fraunhofer.iem.app.logger.getLogger -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KpiCalculationNode -class KpiCalculationDto( - val kind: KpiKind, - private val calculationStrategy: de.fraunhofer.iem.app.kpi.strategy.KPICalculationStrategy? = null, - private var isEmpty: Boolean = true, - private var value: Int? = null -) { - private val hierarchyEdges: MutableList<KPIHierarchyEdgeDto> = mutableListOf() - private val logger = getLogger(javaClass) - - fun hasChildren(): Boolean { - return hierarchyEdges.isNotEmpty() - } - - fun getHierarchyEdges(): List<KPIHierarchyEdgeDto> { - return hierarchyEdges.toList() - } - - fun isEmpty(): Boolean { - return isEmpty - } - - fun calculateKPI() { - if (calculationStrategy != null) { - try { - val valueAndEdges = calculationStrategy.calculateKPI(this.hierarchyEdges) - this.value = valueAndEdges.first - this.hierarchyEdges.clear() - this.hierarchyEdges.addAll(valueAndEdges.second) - - this.isEmpty = false - } catch (exception: Exception) { - logger.error("Exception during KPI calculation for $kind with $calculationStrategy") - this.isEmpty = true - this.value = null - } - } else { - this.isEmpty = true - } - } - - fun getValue(): Int { - if (value != null && !isEmpty) { - return value as Int - } else { - throw Exception("Value access for empty KPIs not allowed. KpiKind $kind") - } +fun KpiCalculationNode.toViewModel(): KPITreeResponseDto { + val children = this.hierarchyEdges.map { + val child = it.to.toViewModel() + KPITreeChildResponseDto(kpi = child, plannedWeight = it.plannedWeight, actualWeight = it.actualWeight) } - fun addChildKPI(kpiCreateDto: KpiCalculationDto, weight: Double) { - val hierarchyEdge = KPIHierarchyEdgeDto(this, kpiCreateDto, weight) - this.hierarchyEdges.add(hierarchyEdge) - } - - fun toViewModel(): KPITreeResponseDto { - val children = this.hierarchyEdges.map { - val child = it.to.toViewModel() - KPITreeChildResponseDto(kpi = child, plannedWeight = it.plannedWeight, actualWeight = it.actualWeight) - } - - return this.kind.toViewModel(value = value ?: -1, children = children, isEmpty = isEmpty) - } + return this.kind.toViewModel( + value = try { + //TODO: fixme + // getValue() + -1 + } catch (e: Exception) { + -1 + }, children = children, isEmpty = false // TODO: fixme + ) } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/entity/KPIEntity.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/entity/KPIEntity.kt index 97382493..7f9af682 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/entity/KPIEntity.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/entity/KPIEntity.kt @@ -1,9 +1,9 @@ package de.fraunhofer.iem.app.kpi.entity -import de.fraunhofer.iem.app.kpi.dto.KpiCalculationDto -import de.fraunhofer.iem.app.kpi.strategy.RawValueKPICalculationStrategy import de.fraunhofer.iem.app.toolRun.entity.ToolRunEntity -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KpiCalculationNode +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.RawKpiCalculationNode +import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId import jakarta.persistence.* import org.hibernate.annotations.CurrentTimestamp import org.hibernate.generator.EventType @@ -11,6 +11,7 @@ import org.hibernate.proxy.HibernateProxy import java.sql.Timestamp import java.util.* + @Entity @Table(name = "kpi") class KPIEntity( @@ -27,17 +28,17 @@ class KPIEntity( val score: Int, @Enumerated(EnumType.STRING) - var kind: KpiKind, + var kind: KpiId, @CurrentTimestamp(event = [EventType.INSERT]) @Column(name = "timestamp") var createdAt: Timestamp? = null ) { - fun toCalculationDto(): KpiCalculationDto { - return KpiCalculationDto( + fun toCalculationDto(): KpiCalculationNode { + // TODO: fixme + return RawKpiCalculationNode( kind = this.kind, - calculationStrategy = RawValueKPICalculationStrategy(this.score), - isEmpty = false + score = this.score, ) } @@ -49,7 +50,7 @@ class KPIEntity( val thisEffectiveClass = if (this is HibernateProxy) this.hibernateLazyInitializer.persistentClass else this.javaClass if (thisEffectiveClass != oEffectiveClass) return false - other as de.fraunhofer.iem.app.kpi.entity.KPIEntity + other as KPIEntity return id != null && id == other.id } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/enumeration/KpiKind.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/enumeration/KpiKind.kt index 176e0e33..66ac89ae 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/enumeration/KpiKind.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/enumeration/KpiKind.kt @@ -2,11 +2,11 @@ package de.fraunhofer.iem.app.kpi.enumeration import de.fraunhofer.iem.app.kpi.dto.KPITreeChildResponseDto import de.fraunhofer.iem.app.kpi.dto.KPITreeResponseDto -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind +import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId -fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isEmpty: Boolean): KPITreeResponseDto { +fun KpiId.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isEmpty: Boolean): KPITreeResponseDto { return when (this.name) { - KpiKind.CHECKED_IN_BINARIES.name -> + KpiId.CHECKED_IN_BINARIES.name -> KPITreeResponseDto( value = value, name = this.getName(), @@ -16,7 +16,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.NUMBER_OF_COMMITS.name -> + KpiId.NUMBER_OF_COMMITS.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -25,7 +25,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.VULNERABILITY_SCORE.name -> + KpiId.VULNERABILITY_SCORE.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -36,7 +36,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.NUMBER_OF_SIGNED_COMMITS.name -> + KpiId.NUMBER_OF_SIGNED_COMMITS.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -45,7 +45,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.IS_DEFAULT_BRANCH_PROTECTED.name -> + KpiId.IS_DEFAULT_BRANCH_PROTECTED.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -56,7 +56,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.SECRETS.name -> + KpiId.SECRETS.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -69,7 +69,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.SAST_USAGE.name -> + KpiId.SAST_USAGE.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -78,7 +78,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.COMMENTS_IN_CODE.name -> + KpiId.COMMENTS_IN_CODE.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -88,7 +88,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.DOCUMENTATION_INFRASTRUCTURE.name -> + KpiId.DOCUMENTATION_INFRASTRUCTURE.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -101,7 +101,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.SIGNED_COMMITS_RATIO.name -> + KpiId.SIGNED_COMMITS_RATIO.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -113,7 +113,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.INTERNAL_QUALITY.name -> + KpiId.INTERNAL_QUALITY.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -124,7 +124,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE order = 3 ) - KpiKind.EXTERNAL_QUALITY.name -> + KpiId.EXTERNAL_QUALITY.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -136,7 +136,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE order = 3 ) - KpiKind.PROCESS_COMPLIANCE.name -> + KpiId.PROCESS_COMPLIANCE.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -148,7 +148,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE order = 4 ) - KpiKind.PROCESS_TRANSPARENCY.name -> + KpiId.PROCESS_TRANSPARENCY.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -161,7 +161,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE order = 5 ) - KpiKind.SECURITY.name -> + KpiId.SECURITY.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -173,7 +173,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE order = 2 ) - KpiKind.MAXIMAL_VULNERABILITY.name -> + KpiId.MAXIMAL_VULNERABILITY.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -189,7 +189,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.ROOT.name -> + KpiId.ROOT.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -200,7 +200,7 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE isEmpty = isEmpty ) - KpiKind.DOCUMENTATION.name -> + KpiId.DOCUMENTATION.name -> return KPITreeResponseDto( value = value, name = this.getName(), @@ -219,26 +219,26 @@ fun KpiKind.toViewModel(value: Int, children: List<KPITreeChildResponseDto>, isE } } -fun KpiKind.getName(): String { +fun KpiId.getName(): String { return when (this.name) { - KpiKind.ROOT.name -> "Project Health Score" - KpiKind.PROCESS_COMPLIANCE.name -> "Process Compliance Score" - KpiKind.DOCUMENTATION.name -> "Documentation" - KpiKind.CHECKED_IN_BINARIES.name -> "No Checked in Binaries" - KpiKind.INTERNAL_QUALITY.name -> "Internal Quality" - KpiKind.NUMBER_OF_COMMITS.name -> "Number of Commits" - KpiKind.MAXIMAL_VULNERABILITY.name -> "Maximal Dependency Vulnerability Score" - KpiKind.SECURITY.name -> "Security Score" - KpiKind.VULNERABILITY_SCORE.name -> "Vulnerability Score" - KpiKind.PROCESS_TRANSPARENCY.name -> "Process Transparency Score" - KpiKind.NUMBER_OF_SIGNED_COMMITS.name -> "Number of Signed Commits" - KpiKind.COMMENTS_IN_CODE.name -> "Comments in Code" - KpiKind.DOCUMENTATION_INFRASTRUCTURE.name -> "Existence of Documentation Infrastructure" - KpiKind.IS_DEFAULT_BRANCH_PROTECTED.name -> "Default Branch Protection" - KpiKind.SECRETS.name -> "Public Secrets" - KpiKind.SIGNED_COMMITS_RATIO.name -> "Commit Signature Ratio" - KpiKind.EXTERNAL_QUALITY.name -> "External Quality" - KpiKind.SAST_USAGE.name -> "SAST Usage" + KpiId.ROOT.name -> "Project Health Score" + KpiId.PROCESS_COMPLIANCE.name -> "Process Compliance Score" + KpiId.DOCUMENTATION.name -> "Documentation" + KpiId.CHECKED_IN_BINARIES.name -> "No Checked in Binaries" + KpiId.INTERNAL_QUALITY.name -> "Internal Quality" + KpiId.NUMBER_OF_COMMITS.name -> "Number of Commits" + KpiId.MAXIMAL_VULNERABILITY.name -> "Maximal Dependency Vulnerability Score" + KpiId.SECURITY.name -> "Security Score" + KpiId.VULNERABILITY_SCORE.name -> "Vulnerability Score" + KpiId.PROCESS_TRANSPARENCY.name -> "Process Transparency Score" + KpiId.NUMBER_OF_SIGNED_COMMITS.name -> "Number of Signed Commits" + KpiId.COMMENTS_IN_CODE.name -> "Comments in Code" + KpiId.DOCUMENTATION_INFRASTRUCTURE.name -> "Existence of Documentation Infrastructure" + KpiId.IS_DEFAULT_BRANCH_PROTECTED.name -> "Default Branch Protection" + KpiId.SECRETS.name -> "Public Secrets" + KpiId.SIGNED_COMMITS_RATIO.name -> "Commit Signature Ratio" + KpiId.EXTERNAL_QUALITY.name -> "External Quality" + KpiId.SAST_USAGE.name -> "SAST Usage" else -> "Unknown KPI" } } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/service/KPIService.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/service/KPIService.kt index 3a2a843e..2055ca7f 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/service/KPIService.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/service/KPIService.kt @@ -2,16 +2,14 @@ package de.fraunhofer.iem.app.kpi.service import de.fraunhofer.iem.app.kpi.dto.KPITreeChildResponseDto import de.fraunhofer.iem.app.kpi.dto.KPITreeResponseDto -import de.fraunhofer.iem.app.kpi.dto.KpiCalculationDto import de.fraunhofer.iem.app.kpi.strategy.AggregationKPICalculationStrategy -import de.fraunhofer.iem.app.kpi.strategy.MaximumKPICalculationStrategy -import de.fraunhofer.iem.app.kpi.strategy.RatioKPICalculationStrategy import de.fraunhofer.iem.app.logger.getLogger import de.fraunhofer.iem.app.repository.dto.RepositoryDetailsDto import de.fraunhofer.iem.app.tools.occmd.enumeration.Checks import de.fraunhofer.iem.app.tools.occmd.json.RawResultJson -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind -import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiCreateDto +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KpiCalculationNode +import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId +import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiDto import org.springframework.stereotype.Service @Service @@ -52,47 +50,47 @@ class KPIService { /** * This method calculates the OccmdCreateKpiDtos based upon the given tool results. */ - fun calculateOccmdKpis(rawOccmdResults: List<RawResultJson>): List<RawValueKpiCreateDto> { - val kpis = mutableListOf<RawValueKpiCreateDto>() + fun calculateOccmdKpis(rawOccmdResults: List<RawResultJson>): List<RawValueKpiDto> { + val kpis = mutableListOf<RawValueKpiDto>() rawOccmdResults.forEach { when (val check = Checks.fromString(it.check)) { Checks.CheckedInBinaries -> kpis.add( - RawValueKpiCreateDto( - kind = KpiKind.CHECKED_IN_BINARIES, + RawValueKpiDto( + kind = KpiId.CHECKED_IN_BINARIES, score = (it.score * 100).toInt() ) ) Checks.SastUsageBasic -> kpis.add( - RawValueKpiCreateDto( - kind = KpiKind.SAST_USAGE, + RawValueKpiDto( + kind = KpiId.SAST_USAGE, score = (it.score * 100).toInt() ) ) Checks.Secrets -> kpis.add( - RawValueKpiCreateDto( - kind = KpiKind.SECRETS, + RawValueKpiDto( + kind = KpiId.SECRETS, score = (it.score * 100).toInt() ) ) Checks.CommentsInCode -> kpis.add( - RawValueKpiCreateDto( - kind = KpiKind.COMMENTS_IN_CODE, + RawValueKpiDto( + kind = KpiId.COMMENTS_IN_CODE, score = (it.score * 100).toInt() ) ) Checks.DocumentationInfrastructure -> kpis.add( - RawValueKpiCreateDto( - kind = KpiKind.DOCUMENTATION_INFRASTRUCTURE, + RawValueKpiDto( + kind = KpiId.DOCUMENTATION_INFRASTRUCTURE, score = (it.score * 100).toInt() ) ) @@ -109,26 +107,26 @@ class KPIService { * Creates a named map of RepositoryCreateDtos, based upon the provided repository details. * This method only returns raw KPIs. */ - fun calculateRepositoryDetailsKpis(repoDetailsDto: RepositoryDetailsDto): List<RawValueKpiCreateDto> { + fun calculateRepositoryDetailsKpis(repoDetailsDto: RepositoryDetailsDto): List<RawValueKpiDto> { return listOf( - RawValueKpiCreateDto( - kind = KpiKind.NUMBER_OF_COMMITS, + RawValueKpiDto( + kind = KpiId.NUMBER_OF_COMMITS, score = repoDetailsDto.numberOfCommits ), - RawValueKpiCreateDto( - kind = KpiKind.NUMBER_OF_SIGNED_COMMITS, + RawValueKpiDto( + kind = KpiId.NUMBER_OF_SIGNED_COMMITS, score = repoDetailsDto.numberOfSignedCommits ), - RawValueKpiCreateDto( - kind = KpiKind.IS_DEFAULT_BRANCH_PROTECTED, + RawValueKpiDto( + kind = KpiId.IS_DEFAULT_BRANCH_PROTECTED, score = if (repoDetailsDto.isDefaultBranchProtected) 100 else 0 ) ) } - fun getKpiTreeForRawKpis(rawKpis: List<KpiCalculationDto>): KpiCalculationDto { + fun getKpiTreeForRawKpis(rawKpis: List<KpiCalculationNode>): KpiCalculationNode { val rawValueKpis = rawKpis.toMutableList() - val vulnerabilities = rawValueKpis.filter { it.kind == KpiKind.VULNERABILITY_SCORE } + val vulnerabilities = rawValueKpis.filter { it.kind == KpiId.VULNERABILITY_SCORE } rawValueKpis.toMutableList().removeAll(vulnerabilities) val kpiMap = rawValueKpis.associateBy { it.kind } val rootKpi = generateKPITree(kpiMap, vulnerabilities) @@ -138,141 +136,141 @@ class KPIService { @Suppress("MagicNumber", "LongMethod") private fun generateKPITree( - rawValueKpis: Map<KpiKind, KpiCalculationDto> = emptyMap(), - vulnerabilityKpis: List<KpiCalculationDto> = emptyList() - ): KpiCalculationDto { - val signedCommitsRatioKPI = - KpiCalculationDto( - kind = KpiKind.SIGNED_COMMITS_RATIO, - calculationStrategy = RatioKPICalculationStrategy() - ) - - signedCommitsRatioKPI.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.NUMBER_OF_COMMITS, - KpiCalculationDto(kind = KpiKind.NUMBER_OF_COMMITS) - ), - 1.0 - ) - - signedCommitsRatioKPI.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.NUMBER_OF_SIGNED_COMMITS, - KpiCalculationDto(kind = KpiKind.NUMBER_OF_SIGNED_COMMITS) - ), - 1.0 - ) - - val processComplianceKPI = KpiCalculationDto( - kind = KpiKind.PROCESS_COMPLIANCE, - calculationStrategy = AggregationKPICalculationStrategy() - ) - - processComplianceKPI.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.IS_DEFAULT_BRANCH_PROTECTED, - KpiCalculationDto(kind = KpiKind.IS_DEFAULT_BRANCH_PROTECTED) - ), - 0.3 - ) - - processComplianceKPI.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.CHECKED_IN_BINARIES, - KpiCalculationDto(kind = KpiKind.CHECKED_IN_BINARIES) - ), - 0.2 - ) - - processComplianceKPI.addChildKPI(signedCommitsRatioKPI, 0.2) - - val documentationKpi = KpiCalculationDto( - kind = KpiKind.DOCUMENTATION, - calculationStrategy = AggregationKPICalculationStrategy() - ) - - documentationKpi.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.DOCUMENTATION_INFRASTRUCTURE, - KpiCalculationDto(kind = KpiKind.DOCUMENTATION_INFRASTRUCTURE) - ), - 0.6 - ) - - documentationKpi.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.COMMENTS_IN_CODE, - KpiCalculationDto(kind = KpiKind.COMMENTS_IN_CODE) - ), - 0.4 - ) - - val processTransparencyKPI = KpiCalculationDto( - kind = KpiKind.PROCESS_TRANSPARENCY, - calculationStrategy = AggregationKPICalculationStrategy() - ) - processComplianceKPI.addChildKPI(documentationKpi, 0.3) - processTransparencyKPI.addChildKPI(signedCommitsRatioKPI, 1.0) - - val securityKPI = KpiCalculationDto( - kind = KpiKind.SECURITY, - calculationStrategy = AggregationKPICalculationStrategy() - ) - - val internalQuality = KpiCalculationDto( - kind = KpiKind.INTERNAL_QUALITY, - calculationStrategy = AggregationKPICalculationStrategy() - ) - - val externalQuality = KpiCalculationDto( - kind = KpiKind.EXTERNAL_QUALITY, - calculationStrategy = AggregationKPICalculationStrategy() - ) - - externalQuality.addChildKPI(documentationKpi, 1.0) - internalQuality.addChildKPI(documentationKpi, 1.0) - - val maximalDependencyVulnerabilityKPI = KpiCalculationDto( - kind = KpiKind.MAXIMAL_VULNERABILITY, - calculationStrategy = MaximumKPICalculationStrategy() - ) - - vulnerabilityKpis.forEach { maximalDependencyVulnerabilityKPI.addChildKPI(it, 0.0) } - - securityKPI.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.SECRETS, - KpiCalculationDto(kind = KpiKind.SECRETS) - ), - 0.3 - ) - - securityKPI.addChildKPI( - rawValueKpis.getOrDefault( - KpiKind.CHECKED_IN_BINARIES, - KpiCalculationDto(kind = KpiKind.CHECKED_IN_BINARIES) - ), - 0.2 - ) - - securityKPI.addChildKPI(maximalDependencyVulnerabilityKPI, 0.5) - - val rootKPI = KpiCalculationDto( - kind = KpiKind.ROOT, + rawValueKpis: Map<KpiId, KpiCalculationNode> = emptyMap(), + vulnerabilityKpis: List<KpiCalculationNode> = emptyList() + ): KpiCalculationNode { +// val signedCommitsRatioKPI = +// KpiCalculationNode( +// kind = KpiKind.SIGNED_COMMITS_RATIO, +// calculationStrategy = RatioKPICalculationStrategy() +// ) +// +// signedCommitsRatioKPI.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.NUMBER_OF_COMMITS, +// KpiCalculationNode(kind = KpiKind.NUMBER_OF_COMMITS) +// ), +// 1.0 +// ) +// +// signedCommitsRatioKPI.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.NUMBER_OF_SIGNED_COMMITS, +// KpiCalculationNode(kind = KpiKind.NUMBER_OF_SIGNED_COMMITS) +// ), +// 1.0 +// ) +// +// val processComplianceKPI = KpiCalculationNode( +// kind = KpiKind.PROCESS_COMPLIANCE, +// calculationStrategy = AggregationKPICalculationStrategy() +// ) +// +// processComplianceKPI.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.IS_DEFAULT_BRANCH_PROTECTED, +// KpiCalculationNode(kind = KpiKind.IS_DEFAULT_BRANCH_PROTECTED) +// ), +// 0.3 +// ) +// +// processComplianceKPI.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.CHECKED_IN_BINARIES, +// KpiCalculationNode(kind = KpiKind.CHECKED_IN_BINARIES) +// ), +// 0.2 +// ) +// +// processComplianceKPI.addChildKPI(signedCommitsRatioKPI, 0.2) +// +// val documentationKpi = KpiCalculationNode( +// kind = KpiKind.DOCUMENTATION, +// calculationStrategy = AggregationKPICalculationStrategy() +// ) +// +// documentationKpi.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.DOCUMENTATION_INFRASTRUCTURE, +// KpiCalculationNode(kind = KpiKind.DOCUMENTATION_INFRASTRUCTURE) +// ), +// 0.6 +// ) +// +// documentationKpi.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.COMMENTS_IN_CODE, +// KpiCalculationNode(kind = KpiKind.COMMENTS_IN_CODE) +// ), +// 0.4 +// ) +// +// val processTransparencyKPI = KpiCalculationNode( +// kind = KpiKind.PROCESS_TRANSPARENCY, +// calculationStrategy = AggregationKPICalculationStrategy() +// ) +// processComplianceKPI.addChildKPI(documentationKpi, 0.3) +// processTransparencyKPI.addChildKPI(signedCommitsRatioKPI, 1.0) +// +// val securityKPI = KpiCalculationNode( +// kind = KpiKind.SECURITY, +// calculationStrategy = AggregationKPICalculationStrategy() +// ) +// +// val internalQuality = KpiCalculationNode( +// kind = KpiKind.INTERNAL_QUALITY, +// calculationStrategy = AggregationKPICalculationStrategy() +// ) +// +// val externalQuality = KpiCalculationNode( +// kind = KpiKind.EXTERNAL_QUALITY, +// calculationStrategy = AggregationKPICalculationStrategy() +// ) +// +// externalQuality.addChildKPI(documentationKpi, 1.0) +// internalQuality.addChildKPI(documentationKpi, 1.0) +// +// val maximalDependencyVulnerabilityKPI = KpiCalculationNode( +// kind = KpiKind.MAXIMAL_VULNERABILITY, +// calculationStrategy = MaximumKPICalculationStrategy() +// ) +// +// vulnerabilityKpis.forEach { maximalDependencyVulnerabilityKPI.addChildKPI(it, 0.0) } +// +// securityKPI.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.SECRETS, +// KpiCalculationNode(kind = KpiKind.SECRETS) +// ), +// 0.3 +// ) +// +// securityKPI.addChildKPI( +// rawValueKpis.getOrDefault( +// KpiKind.CHECKED_IN_BINARIES, +// KpiCalculationNode(kind = KpiKind.CHECKED_IN_BINARIES) +// ), +// 0.2 +// ) +// +// securityKPI.addChildKPI(maximalDependencyVulnerabilityKPI, 0.5) +// + val rootKPI = KpiCalculationNode( + kind = KpiId.ROOT, calculationStrategy = AggregationKPICalculationStrategy(), ) - rootKPI.addChildKPI(processTransparencyKPI, 0.1) - rootKPI.addChildKPI(processComplianceKPI, 0.1) - rootKPI.addChildKPI(internalQuality, 0.15) - rootKPI.addChildKPI(externalQuality, 0.25) - rootKPI.addChildKPI(securityKPI, 0.4) +// rootKPI.addChildKPI(processTransparencyKPI, 0.1) +// rootKPI.addChildKPI(processComplianceKPI, 0.1) +// rootKPI.addChildKPI(internalQuality, 0.15) +// rootKPI.addChildKPI(externalQuality, 0.25) +// rootKPI.addChildKPI(securityKPI, 0.4) return rootKPI } private fun calculateKPIsRecursively( - kpi: KpiCalculationDto, - visited: MutableSet<KpiCalculationDto> = mutableSetOf() + kpi: KpiCalculationNode, + visited: MutableSet<KpiCalculationNode> = mutableSetOf() ) { // Check if the KPI has already been visited if (visited.contains(kpi)) { @@ -282,18 +280,18 @@ class KPIService { // Check if the KPI has child KPIs if (!kpi.hasChildren()) { // Leaf node, calculate the KPI value - kpi.calculateKPI() + kpi.applyStrategy() visited.add(kpi) return } // Recursively calculate child KPIs first - for (childEdge in kpi.getHierarchyEdges()) { + for (childEdge in kpi.hierarchyEdges) { calculateKPIsRecursively(childEdge.to, visited) } // Calculate the KPI value after processing child KPIs - kpi.calculateKPI() + kpi.applyStrategy() visited.add(kpi) } } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategy.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategy.kt index 6eab9093..06b807d3 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategy.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategy.kt @@ -1,8 +1,9 @@ package de.fraunhofer.iem.app.kpi.strategy -import de.fraunhofer.iem.app.kpi.dto.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.strategy.KPICalculationStrategy -class AggregationKPICalculationStrategy : de.fraunhofer.iem.app.kpi.strategy.KPICalculationStrategy { +class AggregationKPICalculationStrategy : KPICalculationStrategy { /** * This function calculates the aggregate sum of all given children. @@ -13,47 +14,48 @@ class AggregationKPICalculationStrategy : de.fraunhofer.iem.app.kpi.strategy.KPI * KPIHierarchyEdgeDtos with the actual used weight. */ override fun calculateKPI(children: List<KPIHierarchyEdgeDto>): Pair<Int, List<KPIHierarchyEdgeDto>> { - if (children.none { !it.to.isEmpty() } || children.isEmpty()) { - throw Exception("KPI aggregation of empty children can't be calculated.") - } - - val emptyChildren: List<KPIHierarchyEdgeDto> = children.filter { it.to.isEmpty() } - - val notEmptyChildren = children.toMutableList() - notEmptyChildren.removeAll(emptyChildren) - - val additionalWeightPerElement: Double = if (notEmptyChildren.isNotEmpty()) { - val unusedWeight = emptyChildren.sumOf { it.plannedWeight } - unusedWeight / notEmptyChildren.size - } else { - 0.0 - } - - val weightedEdges: MutableList<KPIHierarchyEdgeDto> = emptyChildren - .map { - KPIHierarchyEdgeDto( - from = it.from, - to = it.to, - plannedWeight = it.plannedWeight, - actualWeight = 0.0 - ) - }.toMutableList() - - var value = 0 - - notEmptyChildren.forEach { child -> - val actualWeight = (child.plannedWeight + additionalWeightPerElement) - weightedEdges.add( - KPIHierarchyEdgeDto( - from = child.from, - to = child.to, - plannedWeight = child.plannedWeight, - actualWeight = actualWeight - ) - ) - value += (child.to.getValue().toFloat() * actualWeight).toInt() - } - - return Pair(value, weightedEdges) +// if (children.none { !it.to.isEmpty() } || children.isEmpty()) { +// throw Exception("KPI aggregation of empty children can't be calculated.") +// } +// +// val emptyChildren: List<KPIHierarchyEdgeDto> = children.filter { it.to.isEmpty() } +// +// val notEmptyChildren = children.toMutableList() +// notEmptyChildren.removeAll(emptyChildren) +// +// val additionalWeightPerElement: Double = if (notEmptyChildren.isNotEmpty()) { +// val unusedWeight = emptyChildren.sumOf { it.plannedWeight } +// unusedWeight / notEmptyChildren.size +// } else { +// 0.0 +// } +// +// val weightedEdges: MutableList<KPIHierarchyEdgeDto> = emptyChildren +// .map { +// KPIHierarchyEdgeDto( +// from = it.from, +// to = it.to, +// plannedWeight = it.plannedWeight, +// actualWeight = 0.0 +// ) +// }.toMutableList() +// +// var value = 0 +// +// notEmptyChildren.forEach { child -> +// val actualWeight = (child.plannedWeight + additionalWeightPerElement) +// weightedEdges.add( +// KPIHierarchyEdgeDto( +// from = child.from, +// to = child.to, +// plannedWeight = child.plannedWeight, +// actualWeight = actualWeight +// ) +// ) +// value += (child.to.getValue().toFloat() * actualWeight).toInt() +// } +// +// return Pair(value, weightedEdges) + TODO() } } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/MaximumKPICalculationStrategy.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/MaximumKPICalculationStrategy.kt index a82be9b5..0b7ed318 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/MaximumKPICalculationStrategy.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/MaximumKPICalculationStrategy.kt @@ -1,23 +1,26 @@ package de.fraunhofer.iem.app.kpi.strategy -import de.fraunhofer.iem.app.kpi.dto.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.strategy.KPICalculationStrategy -class MaximumKPICalculationStrategy : de.fraunhofer.iem.app.kpi.strategy.KPICalculationStrategy { +class MaximumKPICalculationStrategy : KPICalculationStrategy { // TODO: Currently it's tailored to the maximum dependency vulnerability score, this should change in the future @Suppress("MagicNumber") override fun calculateKPI(children: List<KPIHierarchyEdgeDto>): Pair<Int, List<KPIHierarchyEdgeDto>> { - if (children.none { !it.to.isEmpty() } || children.isEmpty()) { - throw Exception("KPI maximum of empty children can't be calculated") - } - var maximum = 0 - for (child in children) { - if (!child.to.isEmpty()) { - val childValue = child.to.getValue() - if (childValue > maximum) { - maximum = childValue - } - } - } - return Pair((100 - (maximum)), children) +// if (children.none { !it.to.isEmpty() } || children.isEmpty()) { +// throw Exception("KPI maximum of empty children can't be calculated") +// } +// var maximum = 0 +// for (child in children) { +// if (!child.to.isEmpty()) { +// val childValue = child.to.getValue() +// if (childValue > maximum) { +// maximum = childValue +// } +// } +// } +// return Pair((100 - (maximum)), children) +// } + TODO() } } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/RatioKPICalculationStrategy.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/RatioKPICalculationStrategy.kt index d6f80d0e..5b552b63 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/RatioKPICalculationStrategy.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/RatioKPICalculationStrategy.kt @@ -1,20 +1,22 @@ package de.fraunhofer.iem.app.kpi.strategy -import de.fraunhofer.iem.app.kpi.dto.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.strategy.KPICalculationStrategy -class RatioKPICalculationStrategy : de.fraunhofer.iem.app.kpi.strategy.KPICalculationStrategy { +class RatioKPICalculationStrategy : KPICalculationStrategy { @Suppress("MagicNumber") override fun calculateKPI(children: List<KPIHierarchyEdgeDto>): Pair<Int, List<KPIHierarchyEdgeDto>> { - if (children.size != 2) { - throw Exception("Requires exactly two children") - } - // TODO: this is a dirty workaround to fix a copy by reference bug - val copiedChildren = children.toList() - val firstValue = children[0].to.getValue() - val secondValue = children[1].to.getValue() - if (firstValue >= secondValue) { - return Pair(((secondValue.toDouble() / firstValue.toDouble()) * 100).toInt(), copiedChildren) - } - return Pair(((firstValue.toDouble() / secondValue.toDouble()) * 100).toInt(), copiedChildren) +// if (children.size != 2) { +// throw Exception("Requires exactly two children") +// } +// // TODO: this is a dirty workaround to fix a copy by reference bug +// val copiedChildren = children.toList() +// val firstValue = children[0].to.getValue() +// val secondValue = children[1].to.getValue() +// if (firstValue >= secondValue) { +// return Pair(((secondValue.toDouble() / firstValue.toDouble()) * 100).toInt(), copiedChildren) +// } +// return Pair(((firstValue.toDouble() / secondValue.toDouble()) * 100).toInt(), copiedChildren) + TODO() } } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/controller/RepositoryController.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/controller/RepositoryController.kt index 9a8154b2..8255e66e 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/controller/RepositoryController.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/controller/RepositoryController.kt @@ -5,6 +5,7 @@ import de.fraunhofer.iem.app.configuration.security.JwtContentDto import de.fraunhofer.iem.app.configuration.security.JwtService import de.fraunhofer.iem.app.gitlab.service.OpenCodeGitlabApi import de.fraunhofer.iem.app.kpi.dto.KPITreeResponseDto +import de.fraunhofer.iem.app.kpi.dto.toViewModel import de.fraunhofer.iem.app.kpi.service.KPIService import de.fraunhofer.iem.app.logger.getLogger import de.fraunhofer.iem.app.repository.dto.* @@ -135,7 +136,7 @@ class RepositoryController( val rawKpis = repositoryEntity.getLastToolRun().kpiEntities.map { val calcDto = it.toCalculationDto() - calcDto.calculateKPI() + calcDto.applyStrategy() calcDto } return RawKpiDto(rawKpis = rawKpis) diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawKpiDto.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawKpiDto.kt index b3f66072..c2205986 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawKpiDto.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawKpiDto.kt @@ -1,5 +1,6 @@ package de.fraunhofer.iem.app.repository.dto -import de.fraunhofer.iem.app.kpi.dto.KpiCalculationDto +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KpiCalculationNode -data class RawKpiDto(val rawKpis: List<KpiCalculationDto>) + +data class RawKpiDto(val rawKpis: List<KpiCalculationNode>) diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawValueKpiCreateDtoExtension.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawValueKpiCreateDtoExtension.kt index 572e43b0..c9c41ab8 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawValueKpiCreateDtoExtension.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/dto/RawValueKpiCreateDtoExtension.kt @@ -1,11 +1,11 @@ package de.fraunhofer.iem.app.repository.dto import de.fraunhofer.iem.app.toolRun.entity.ToolRunEntity -import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiCreateDto +import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiDto import java.sql.Timestamp import java.time.Instant -fun RawValueKpiCreateDto.toDbObject(toolRun: ToolRunEntity): de.fraunhofer.iem.app.kpi.entity.KPIEntity { +fun RawValueKpiDto.toDbObject(toolRun: ToolRunEntity): de.fraunhofer.iem.app.kpi.entity.KPIEntity { return de.fraunhofer.iem.app.kpi.entity.KPIEntity( kind = this.kind, score = this.score, diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/service/RepositoryService.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/service/RepositoryService.kt index d76b1962..177a7a2b 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/service/RepositoryService.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/repository/service/RepositoryService.kt @@ -13,7 +13,7 @@ import de.fraunhofer.iem.app.toolRun.dto.ToolRunDto import de.fraunhofer.iem.app.toolRun.entity.LanguageEntity import de.fraunhofer.iem.app.toolRun.entity.ToolRunEntity import de.fraunhofer.iem.app.toolRun.repository.ToolRunRepository -import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiCreateDto +import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiDto import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Propagation import org.springframework.transaction.annotation.Transactional @@ -30,7 +30,7 @@ class RepositoryService( @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) fun createToolRun( repoDto: RepositoryCreateDto, - kpiToolList: List<Pair<CreateToolDto, List<RawValueKpiCreateDto>>>, + kpiToolList: List<Pair<CreateToolDto, List<RawValueKpiDto>>>, languageMap: Map<String, Float> ) { val repo = getOrCreate(repoDto) @@ -73,7 +73,7 @@ class RepositoryService( logger.info("Creating repository with id ${gitRepository.id}") repo = repositoryRepository.save(gitRepository.toDbObject()) } - return repo + return repo!! } diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/tool/enumeration/ToolType.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/tool/enumeration/ToolType.kt index 330d15c8..0dc3b489 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/tool/enumeration/ToolType.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/tool/enumeration/ToolType.kt @@ -2,7 +2,7 @@ package de.fraunhofer.iem.app.tool.enumeration import de.fraunhofer.iem.app.kpi.enumeration.getName import de.fraunhofer.iem.app.tool.dto.ToolDto -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind +import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId enum class ToolType { ORT { @@ -10,9 +10,9 @@ enum class ToolType { return ToolDto( name = this.getName(), relevantKpis = listOf( - KpiKind.MAXIMAL_VULNERABILITY.getName(), - KpiKind.VULNERABILITY_SCORE.getName(), - KpiKind.SECURITY.getName() + KpiId.MAXIMAL_VULNERABILITY.getName(), + KpiId.VULNERABILITY_SCORE.getName(), + KpiId.SECURITY.getName() ), description = "The OSS Review Toolkit (ORT) provides information about dependencies." + "For more information see https://github.com/oss-review-toolkit/ort.", @@ -29,14 +29,14 @@ enum class ToolType { return ToolDto( name = this.getName(), relevantKpis = listOf( - KpiKind.SECURITY.getName(), - KpiKind.PROCESS_TRANSPARENCY.getName(), - KpiKind.PROCESS_COMPLIANCE.getName(), - KpiKind.SECRETS.getName(), - KpiKind.COMMENTS_IN_CODE.getName(), - KpiKind.DOCUMENTATION.getName(), - KpiKind.SAST_USAGE.getName(), - KpiKind.CHECKED_IN_BINARIES.getName() + KpiId.SECURITY.getName(), + KpiId.PROCESS_TRANSPARENCY.getName(), + KpiId.PROCESS_COMPLIANCE.getName(), + KpiId.SECRETS.getName(), + KpiId.COMMENTS_IN_CODE.getName(), + KpiId.DOCUMENTATION.getName(), + KpiId.SAST_USAGE.getName(), + KpiId.CHECKED_IN_BINARIES.getName() ), description = "The OCCMD provides various information about the analyzed project." + "For more information see https://gitlab.opencode.de/opencode-analyzer/occmd-public.", @@ -54,11 +54,11 @@ enum class ToolType { return ToolDto( name = this.getName(), relevantKpis = listOf( - KpiKind.PROCESS_TRANSPARENCY.getName(), - KpiKind.PROCESS_COMPLIANCE.getName(), - KpiKind.NUMBER_OF_COMMITS.getName(), - KpiKind.NUMBER_OF_SIGNED_COMMITS.getName(), - KpiKind.DOCUMENTATION.getName(), + KpiId.PROCESS_TRANSPARENCY.getName(), + KpiId.PROCESS_COMPLIANCE.getName(), + KpiId.NUMBER_OF_COMMITS.getName(), + KpiId.NUMBER_OF_SIGNED_COMMITS.getName(), + KpiId.DOCUMENTATION.getName(), ), description = "The Gitlab API is used to derive information about, e.g., the project's compliance" + "to OpenCoDE's platform rules.", diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/toolRun/service/ToolRunService.kt b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/toolRun/service/ToolRunService.kt index 6c0a0dad..8b9c3b7b 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/toolRun/service/ToolRunService.kt +++ b/app/backend/src/main/kotlin/de/fraunhofer/iem/app/toolRun/service/ToolRunService.kt @@ -73,7 +73,7 @@ class ToolRunService( // goal is to match the behavior of the old implementation. val rawValueKpiCreateDtos = CveAdapter.transformDataToKpi(vulnerabilityDtos).filterIsInstance<AdapterResult.Success>() - .map { it.rawValueKpiCreateDto } + .map { it.rawValueKpiDto } Pair(ortService.getToolDto(), rawValueKpiCreateDtos) }, diff --git a/app/backend/src/test/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategyTest.kt b/app/backend/src/test/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategyTest.kt index 21d389d8..0e77dbd7 100644 --- a/app/backend/src/test/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategyTest.kt +++ b/app/backend/src/test/kotlin/de/fraunhofer/iem/app/kpi/strategy/AggregationKPICalculationStrategyTest.kt @@ -1,107 +1,108 @@ package de.fraunhofer.iem.app.kpi.strategy -import de.fraunhofer.iem.app.kpi.dto.KpiCalculationDto -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KpiCalculationNode import org.junit.jupiter.api.Test class AggregationKPICalculationStrategyTest { - private fun getRootKpiPartiallyEmpty(): KpiCalculationDto { - val processComplianceKPI = KpiCalculationDto( - kind = KpiKind.PROCESS_COMPLIANCE, - calculationStrategy = RawValueKPICalculationStrategy(25), - value = 25, - isEmpty = false - ) - - val processTransparencyKPI = KpiCalculationDto( - kind = KpiKind.PROCESS_TRANSPARENCY, - calculationStrategy = RawValueKPICalculationStrategy(50), - value = 50, - isEmpty = false - ) - - val securityKPI = KpiCalculationDto( - kind = KpiKind.SECURITY, - calculationStrategy = AggregationKPICalculationStrategy(), - value = -1, - isEmpty = true - ) - - val transparencyKpi = KpiCalculationDto( - kind = KpiKind.PROCESS_TRANSPARENCY, - calculationStrategy = AggregationKPICalculationStrategy(), - value = -1, - isEmpty = true - ) - - transparencyKpi.addChildKPI( - KpiCalculationDto( - kind = KpiKind.PROCESS_TRANSPARENCY, - calculationStrategy = RawValueKPICalculationStrategy(-1), - value = -1, - isEmpty = true - ), - 1.0 - ) - - val rootKPI = KpiCalculationDto( - kind = KpiKind.ROOT, - calculationStrategy = AggregationKPICalculationStrategy(), - ) - - rootKPI.addChildKPI(processTransparencyKPI, 0.25) - rootKPI.addChildKPI(processComplianceKPI, 0.25) - rootKPI.addChildKPI(transparencyKpi, 0.25) - rootKPI.addChildKPI(securityKPI, 0.25) - - return rootKPI - } - - private fun getRootKpiComplete(): KpiCalculationDto { - val processComplianceKPI = KpiCalculationDto( - kind = KpiKind.PROCESS_COMPLIANCE, - calculationStrategy = RawValueKPICalculationStrategy(25), - value = 25, - isEmpty = false - ) - - val processTransparencyKPI = KpiCalculationDto( - kind = KpiKind.PROCESS_TRANSPARENCY, - calculationStrategy = RawValueKPICalculationStrategy(50), - value = 50, - isEmpty = false - ) - - val securityKPI = KpiCalculationDto( - kind = KpiKind.SECURITY, - calculationStrategy = RawValueKPICalculationStrategy(100), - value = 100, - isEmpty = false - ) - - val rootKPI = KpiCalculationDto( - kind = KpiKind.ROOT, - calculationStrategy = AggregationKPICalculationStrategy(), - ) - - rootKPI.addChildKPI(processTransparencyKPI, 0.25) - rootKPI.addChildKPI(processComplianceKPI, 0.25) - rootKPI.addChildKPI(securityKPI, 0.5) - - return rootKPI + private fun getRootKpiPartiallyEmpty(): KpiCalculationNode { + TODO() +// val processComplianceKPI = KpiCalculationNode( +// kind = KpiKind.PROCESS_COMPLIANCE, +// calculationStrategy = RawValueKPICalculationStrategy(25), +// value = 25, +// isEmpty = false +// ) +// +// val processTransparencyKPI = KpiCalculationNode( +// kind = KpiKind.PROCESS_TRANSPARENCY, +// calculationStrategy = RawValueKPICalculationStrategy(50), +// value = 50, +// isEmpty = false +// ) +// +// val securityKPI = KpiCalculationNode( +// kind = KpiKind.SECURITY, +// calculationStrategy = AggregationKPICalculationStrategy(), +// value = -1, +// isEmpty = true +// ) +// +// val transparencyKpi = KpiCalculationNode( +// kind = KpiKind.PROCESS_TRANSPARENCY, +// calculationStrategy = AggregationKPICalculationStrategy(), +// value = -1, +// isEmpty = true +// ) +// +// transparencyKpi.addChildKPI( +// KpiCalculationNode( +// kind = KpiKind.PROCESS_TRANSPARENCY, +// calculationStrategy = RawValueKPICalculationStrategy(-1), +// value = -1, +// isEmpty = true +// ), +// 1.0 +// ) +// +// val rootKPI = KpiCalculationNode( +// kind = KpiKind.ROOT, +// calculationStrategy = AggregationKPICalculationStrategy(), +// ) +// +// rootKPI.addChildKPI(processTransparencyKPI, 0.25) +// rootKPI.addChildKPI(processComplianceKPI, 0.25) +// rootKPI.addChildKPI(transparencyKpi, 0.25) +// rootKPI.addChildKPI(securityKPI, 0.25) +// +// return rootKPI +// } +// +// private fun getRootKpiComplete(): KpiCalculationNode { +// val processComplianceKPI = KpiCalculationNode( +// kind = KpiKind.PROCESS_COMPLIANCE, +// calculationStrategy = RawValueKPICalculationStrategy(25), +// value = 25, +// isEmpty = false +// ) +// +// val processTransparencyKPI = KpiCalculationNode( +// kind = KpiKind.PROCESS_TRANSPARENCY, +// calculationStrategy = RawValueKPICalculationStrategy(50), +// value = 50, +// isEmpty = false +// ) +// +// val securityKPI = KpiCalculationNode( +// kind = KpiKind.SECURITY, +// calculationStrategy = RawValueKPICalculationStrategy(100), +// value = 100, +// isEmpty = false +// ) +// +// val rootKPI = KpiCalculationNode( +// kind = KpiKind.ROOT, +// calculationStrategy = AggregationKPICalculationStrategy(), +// ) +// +// rootKPI.addChildKPI(processTransparencyKPI, 0.25) +// rootKPI.addChildKPI(processComplianceKPI, 0.25) +// rootKPI.addChildKPI(securityKPI, 0.5) +// +// return rootKPI } @Test fun calculateKPI() { - val rootKpiPartiallyEmpty = getRootKpiPartiallyEmpty() - rootKpiPartiallyEmpty.getHierarchyEdges() - - val sum = AggregationKPICalculationStrategy().calculateKPI(rootKpiPartiallyEmpty.getHierarchyEdges()) - assert(sum.first == 37) - - val rootKpi = getRootKpiComplete() - val sum2 = AggregationKPICalculationStrategy().calculateKPI(rootKpi.getHierarchyEdges()) - assert(sum2.first == 68) +// val rootKpiPartiallyEmpty = getRootKpiPartiallyEmpty() +// rootKpiPartiallyEmpty.hierarchyEdges +// +// val sum = AggregationKPICalculationStrategy().calculateKPI(rootKpiPartiallyEmpty.hierarchyEdges) +// assert(sum.first == 37) +// +// val rootKpi = getRootKpiComplete() +// val sum2 = AggregationKPICalculationStrategy().calculateKPI(rootKpi.hierarchyEdges) +// assert(sum2.first == 68) + TODO() } } diff --git a/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/KpiAdapter.kt b/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/KpiAdapter.kt index 55633bc9..b7ca1357 100644 --- a/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/KpiAdapter.kt +++ b/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/KpiAdapter.kt @@ -1,11 +1,11 @@ package de.fraunhofer.iem.kpiCalculator.adapter import de.fraunhofer.iem.kpiCalculator.model.adapter.AdapterResult -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind +import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId interface KpiAdapter<T> { - val kpiKind: KpiKind + val kpiId: KpiId fun transformDataToKpi(data: List<T>): List<AdapterResult> fun transformDataToKpi(data: T): AdapterResult = transformDataToKpi(listOf(data)).first() diff --git a/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapter.kt b/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapter.kt index 9cb30699..e71fdb38 100644 --- a/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapter.kt +++ b/kpi-calculator/adapter/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapter.kt @@ -4,20 +4,20 @@ import de.fraunhofer.iem.kpiCalculator.adapter.KpiAdapter import de.fraunhofer.iem.kpiCalculator.model.adapter.AdapterResult import de.fraunhofer.iem.kpiCalculator.model.adapter.ErrorType import de.fraunhofer.iem.kpiCalculator.model.adapter.VulnerabilityDto -import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiKind -import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiCreateDto +import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId +import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiDto object CveAdapter : KpiAdapter<VulnerabilityDto> { - override val kpiKind: KpiKind - get() = KpiKind.VULNERABILITY_SCORE + override val kpiId: KpiId + get() = KpiId.VULNERABILITY_SCORE override fun transformDataToKpi(data: List<VulnerabilityDto>): List<AdapterResult> { return data .map { return@map if (isValid(it)) { AdapterResult.Success( - RawValueKpiCreateDto( - kind = kpiKind, + RawValueKpiDto( + kind = kpiId, score = (it.severity * 10).toInt() ) ) diff --git a/kpi-calculator/adapter/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapterTest.kt b/kpi-calculator/adapter/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapterTest.kt index cb482bef..e24b0c18 100644 --- a/kpi-calculator/adapter/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapterTest.kt +++ b/kpi-calculator/adapter/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/adapter/cve/CveAdapterTest.kt @@ -21,7 +21,7 @@ class CveAdapterTest { ) when (validKpi) { is AdapterResult.Success -> { - assert(validKpi.rawValueKpiCreateDto.score in (0..100)) + assert(validKpi.rawValueKpiDto.score in (0..100)) } is AdapterResult.Error -> { diff --git a/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/KpiCalculator.kt b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/KpiCalculator.kt index 0d1d240a..5ffc7910 100644 --- a/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/KpiCalculator.kt +++ b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/KpiCalculator.kt @@ -3,5 +3,6 @@ package de.fraunhofer.iem.kpiCalculator.core object KpiCalculator { //XXX: Setup Logger +// fun calculateKpis(root: KpiCalculationNode): } diff --git a/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KPIHierarchyEdgeDto.kt b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KPIHierarchyEdgeDto.kt new file mode 100644 index 00000000..388207c6 --- /dev/null +++ b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KPIHierarchyEdgeDto.kt @@ -0,0 +1,8 @@ +package de.fraunhofer.iem.kpiCalculator.core.hierarchy + +data class KPIHierarchyEdgeDto( + val from: KpiCalculationNode, + val to: KpiCalculationNode, + val plannedWeight: Double, + val actualWeight: Double = plannedWeight +) diff --git a/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KpiCalculationNode.kt b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KpiCalculationNode.kt new file mode 100644 index 00000000..f03aa75f --- /dev/null +++ b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/hierarchy/KpiCalculationNode.kt @@ -0,0 +1,48 @@ +package de.fraunhofer.iem.kpiCalculator.core.hierarchy + +import de.fraunhofer.iem.kpiCalculator.core.strategy.KPICalculationStrategy +import de.fraunhofer.iem.kpiCalculator.core.strategy.RawValueKPICalculationStrategy +import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId + +sealed class KpiCalculationResult { + class Kpi(val kind: KpiId, val score: Int) : KpiCalculationResult() + class Error(val reason: String) : KpiCalculationResult() +} + +// TODO: fixme +open class KpiCalculationNode(val kind: KpiId, private val calculationStrategy: KPICalculationStrategy) { + + private val _hierarchyEdges: MutableList<KPIHierarchyEdgeDto> = mutableListOf() + val hierarchyEdges: List<KPIHierarchyEdgeDto> + get() = _hierarchyEdges + + fun hasChildren(): Boolean { + return hierarchyEdges.isNotEmpty() + } + + fun applyStrategy(): KpiCalculationResult { + return try { + val valueAndEdges = calculationStrategy.calculateKPI(this.hierarchyEdges) + val value = valueAndEdges.first + this._hierarchyEdges.clear() + this._hierarchyEdges.addAll(valueAndEdges.second) + + KpiCalculationResult.Kpi(kind = this.kind, score = value) + } catch (exception: Exception) { + KpiCalculationResult.Error(exception.toString()) + } + } + + + fun addChildKPI(kpiCreateDto: KpiCalculationNode, weight: Double) { + val hierarchyEdge = KPIHierarchyEdgeDto(this, kpiCreateDto, weight) + this._hierarchyEdges.add(hierarchyEdge) + } +} + + +class RawKpiCalculationNode( + score: Int, + kind: KpiId +) : KpiCalculationNode(kind, RawValueKPICalculationStrategy(score)) + diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/KPICalculationStrategy.kt b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/strategy/KPICalculationStrategy.kt similarity index 52% rename from app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/KPICalculationStrategy.kt rename to kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/strategy/KPICalculationStrategy.kt index 8d31a145..516ea616 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/KPICalculationStrategy.kt +++ b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/strategy/KPICalculationStrategy.kt @@ -1,6 +1,6 @@ -package de.fraunhofer.iem.app.kpi.strategy +package de.fraunhofer.iem.kpiCalculator.core.strategy -import de.fraunhofer.iem.app.kpi.dto.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KPIHierarchyEdgeDto fun interface KPICalculationStrategy { fun calculateKPI(children: List<KPIHierarchyEdgeDto>): Pair<Int, List<KPIHierarchyEdgeDto>> diff --git a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/RawValueKPICalculationStrategy.kt b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/strategy/RawValueKPICalculationStrategy.kt similarity index 57% rename from app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/RawValueKPICalculationStrategy.kt rename to kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/strategy/RawValueKPICalculationStrategy.kt index 0bb577e7..86c0a134 100644 --- a/app/backend/src/main/kotlin/de/fraunhofer/iem/app/kpi/strategy/RawValueKPICalculationStrategy.kt +++ b/kpi-calculator/core/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/core/strategy/RawValueKPICalculationStrategy.kt @@ -1,9 +1,9 @@ -package de.fraunhofer.iem.app.kpi.strategy +package de.fraunhofer.iem.kpiCalculator.core.strategy -import de.fraunhofer.iem.app.kpi.dto.KPIHierarchyEdgeDto +import de.fraunhofer.iem.kpiCalculator.core.hierarchy.KPIHierarchyEdgeDto class RawValueKPICalculationStrategy(private val value: Int) : - de.fraunhofer.iem.app.kpi.strategy.KPICalculationStrategy { + KPICalculationStrategy { override fun calculateKPI(children: List<KPIHierarchyEdgeDto>): Pair<Int, List<KPIHierarchyEdgeDto>> { return Pair(this.value, children) } diff --git a/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/adapter/AdapterResult.kt b/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/adapter/AdapterResult.kt index 6c71e534..bdb5acf4 100644 --- a/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/adapter/AdapterResult.kt +++ b/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/adapter/AdapterResult.kt @@ -1,10 +1,10 @@ package de.fraunhofer.iem.kpiCalculator.model.adapter -import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiCreateDto +import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiDto enum class ErrorType { DATA_VALIDATION_ERROR } sealed class AdapterResult { - data class Success(val rawValueKpiCreateDto: RawValueKpiCreateDto) : AdapterResult() + data class Success(val rawValueKpiDto: RawValueKpiDto) : AdapterResult() data class Error(val type: ErrorType) : AdapterResult() } diff --git a/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiCreateDto.kt b/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiCreateDto.kt deleted file mode 100644 index fe82d588..00000000 --- a/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiCreateDto.kt +++ /dev/null @@ -1,3 +0,0 @@ -package de.fraunhofer.iem.kpiCalculator.model.kpi - -data class RawValueKpiCreateDto(val kind: KpiKind, val score: Int) diff --git a/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiDto.kt b/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiDto.kt new file mode 100644 index 00000000..ef3e322c --- /dev/null +++ b/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/RawValueKpiDto.kt @@ -0,0 +1,3 @@ +package de.fraunhofer.iem.kpiCalculator.model.kpi + +data class RawValueKpiDto(val kind: KpiId, val score: Int) diff --git a/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiHierarchy.kt b/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiHierarchy.kt index a7ce187e..be3d6900 100644 --- a/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiHierarchy.kt +++ b/kpi-calculator/model/src/main/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiHierarchy.kt @@ -20,3 +20,4 @@ data class KpiNode(val kpiId: KpiId, val strategyType: KpiStrategyId, val childr @Serializable data class KpiEdge(val target: KpiNode, val weight: Double) + diff --git a/kpi-calculator/model/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiNodeTest.kt b/kpi-calculator/model/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiHierarchyTest.kt similarity index 82% rename from kpi-calculator/model/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiNodeTest.kt rename to kpi-calculator/model/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiHierarchyTest.kt index c2872514..014b4c5e 100644 --- a/kpi-calculator/model/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiNodeTest.kt +++ b/kpi-calculator/model/src/test/kotlin/de/fraunhofer/iem/kpiCalculator/model/kpi/hierarchy/KpiHierarchyTest.kt @@ -2,13 +2,14 @@ package de.fraunhofer.iem.kpiCalculator.model.kpi.hierarchy import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiId import de.fraunhofer.iem.kpiCalculator.model.kpi.KpiStrategyId +import de.fraunhofer.iem.kpiCalculator.model.kpi.RawValueKpiDto import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow import kotlin.test.assertEquals -class KpiNodeTest { +class KpiHierarchyTest { @Test fun constructHierarchy() { // This test doesn't really test any functionality. It's mainly here as a reminder to fail whenever we change something @@ -43,4 +44,17 @@ class KpiNodeTest { assertEquals(hierarchy.schemaVersion, "1.0.0") } } + + @Test + fun connectHierarchyAndData() { + + val rawValueKpis = listOf( + RawValueKpiDto( + kind = KpiId.COMMENTS_IN_CODE, + score = 40 + ) + ) + val hierarchy = DefaultHierarchy.get() + println(KpiHierarchy.isValid(hierarchy)) + } } -- GitLab