1818 */
1919
2020package org.ossreviewtoolkit.plugins.scanners.scanoss
21-
21+ import com.scanoss.dto.LicenseDetails
2222import com.scanoss.dto.ScanFileDetails
2323import com.scanoss.dto.ScanFileResult
2424import com.scanoss.dto.enums.MatchType
25+ import com.scanoss.dto.enums.StatusType
2526
27+ import java.lang.invoke.MethodHandles
2628import java.time.Instant
2729
30+ import kotlin.math.min
31+
32+ import org.apache.logging.log4j.kotlin.loggerOf
33+
2834import org.ossreviewtoolkit.downloader.VcsHost
2935import org.ossreviewtoolkit.model.CopyrightFinding
3036import org.ossreviewtoolkit.model.LicenseFinding
@@ -36,7 +42,8 @@ import org.ossreviewtoolkit.model.TextLocation
3642import org.ossreviewtoolkit.utils.spdx.SpdxConstants
3743import org.ossreviewtoolkit.utils.spdx.SpdxExpression
3844import org.ossreviewtoolkit.utils.spdx.SpdxLicenseIdExpression
39- import org.ossreviewtoolkit.utils.spdx.andOrNull
45+
46+ private val logger = loggerOf(MethodHandles .lookup().lookupClass())
4047
4148/* *
4249 * Generate a summary from the given SCANOSS [result], using [startTime], [endTime] as metadata. This variant can be
@@ -56,16 +63,23 @@ internal fun generateSummary(startTime: Instant, endTime: Instant, results: List
5663 }
5764
5865 MatchType .snippet -> {
59- val file = requireNotNull(details.file)
60- val lines = requireNotNull(details.lines)
61- val sourceLocations = convertLines(file, lines)
62- val snippets = getSnippets(details)
63-
64- snippets.forEach { snippet ->
65- sourceLocations.forEach { sourceLocation ->
66- // TODO: Aggregate the snippet by source file location.
67- snippetFindings + = SnippetFinding (sourceLocation, setOf (snippet))
66+ val file = requireNotNull(result.filePath)
67+ if (details.status == StatusType .pending) {
68+ val lines = requireNotNull(details.lines)
69+ val sourceLocations = convertLines(file, lines)
70+ val snippets = getSnippets(details)
71+
72+ if (sourceLocations.size != snippets.size) {
73+ logger.warn(" number of local line ranges does not match with oss lines on file '$file '" )
74+ }
75+
76+ for (i in 0 until min(sourceLocations.size, snippets.size)) {
77+ snippetFindings + = SnippetFinding (sourceLocations[i], setOf (snippets[i]))
6878 }
79+ } else {
80+ logger.warn(" file '$file ' is identified, not including on snippet findings" )
81+ licenseFindings + = getLicenseFindings(details)
82+ copyrightFindings + = getCopyrightFindings(details)
6983 }
7084 }
7185
@@ -137,16 +151,14 @@ private fun getCopyrightFindings(details: ScanFileDetails): List<CopyrightFindin
137151 * Get the snippet findings from the given [details]. If a snippet returned by ScanOSS contains several Purls,
138152 * several snippets are created in ORT each containing a single Purl.
139153 */
140- private fun getSnippets (details : ScanFileDetails ): Set <Snippet > {
154+ private fun getSnippets (details : ScanFileDetails ): List <Snippet > {
141155 val matched = requireNotNull(details.matched)
142156 val fileUrl = requireNotNull(details.fileUrl)
143157 val ossLines = requireNotNull(details.ossLines)
144158 val url = requireNotNull(details.url)
145159 val purls = requireNotNull(details.purls)
146160
147- val licenses = details.licenseDetails.orEmpty().mapTo(mutableSetOf ()) { license ->
148- SpdxExpression .parse(license.name)
149- }
161+ val license = getUniqueLicenseExpression(details.licenseDetails)
150162
151163 val score = matched.substringBeforeLast(" %" ).toFloat()
152164 val locations = convertLines(fileUrl, ossLines)
@@ -156,11 +168,9 @@ private fun getSnippets(details: ScanFileDetails): Set<Snippet> {
156168
157169 val additionalData = mapOf (" release_date" to details.releaseDate)
158170
159- return buildSet {
171+ return buildList {
160172 purls.forEach { purl ->
161173 locations.forEach { snippetLocation ->
162- val license = licenses.andOrNull()?.sorted() ? : SpdxLicenseIdExpression (SpdxConstants .NOASSERTION )
163-
164174 add(Snippet (score, snippetLocation, provenance, purl, license, additionalData))
165175 }
166176 }
@@ -180,3 +190,14 @@ private fun convertLines(file: String, lineRanges: String): List<TextLocation> =
180190 else -> throw IllegalArgumentException (" Unsupported line range '$lineRange '." )
181191 }
182192 }
193+
194+ fun getUniqueLicenseExpression (licensesDetails : Array <LicenseDetails >): SpdxExpression {
195+ if (licensesDetails.isEmpty()) {
196+ return SpdxLicenseIdExpression (SpdxConstants .NOASSERTION )
197+ }
198+
199+ return licensesDetails
200+ .map { license -> SpdxExpression .parse(license.name) }
201+ .reduce { acc, expr -> acc.and (expr) }
202+ .simplify()
203+ }
0 commit comments