toolkit.utils.spdx-utils.44.0.0.source-code.Extensions.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spdx-utils Show documentation
Show all versions of spdx-utils Show documentation
Part of the OSS Review Toolkit (ORT), a suite to automate software compliance checks.
The 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.utils.spdx
import java.lang.invoke.MethodHandles
import org.apache.logging.log4j.kotlin.loggerOf
import org.ossreviewtoolkit.utils.common.collectMessages
import org.ossreviewtoolkit.utils.spdx.SpdxExpression.Strictness
private val logger = loggerOf(MethodHandles.lookup().lookupClass())
/**
* Convert an [SpdxExpression] to `NOASSERTION` if null, to `NONE` if blank, or to its string representation otherwise.
*/
fun SpdxExpression?.nullOrBlankToSpdxNoassertionOrNone(): String =
when {
this == null -> SpdxConstants.NOASSERTION
toString().isBlank() -> SpdxConstants.NONE
else -> toString()
}
/**
* Create an [SpdxLicenseIdExpression] from this [SpdxLicense].
*/
fun SpdxLicense.toExpression(): SpdxLicenseIdExpression {
var expressionId = id
// While in the current SPDX standard the "or later version" semantic is part of the id string itself, it is a
// generic "+" operator for deprecated licenses.
val orLaterVersion = if (deprecated) {
expressionId = id.removeSuffix("+")
id != expressionId
} else {
id.endsWith("-or-later")
}
return SpdxLicenseIdExpression(expressionId, orLaterVersion)
}
/**
* Return true if and only if this string can be successfully parsed to a [SpdxExpression] of the given [strictness].
*/
fun String.isSpdxExpression(strictness: Strictness = Strictness.ALLOW_DEPRECATED): Boolean =
runCatching { SpdxExpression.parse(this, strictness) }.isSuccess
/**
* Return true if and only if this String can be successfully parsed to an [SpdxExpression] with the given [strictness],
* or if it equals [SpdxConstants.NONE] or [SpdxConstants.NOASSERTION].
*/
fun String.isSpdxExpressionOrNotPresent(strictness: Strictness = Strictness.ALLOW_DEPRECATED): Boolean =
SpdxConstants.isNotPresent(this) || isSpdxExpression(strictness)
/**
* Parse this string as an [SpdxExpression] of the given [strictness] and return the result on success, or throw an
* [SpdxException] if the string cannot be parsed.
*/
fun String.toSpdx(strictness: Strictness = Strictness.ALLOW_ANY): SpdxExpression =
SpdxExpression.parse(this, strictness)
/**
* Parse this string as an [SpdxExpression] of the given [strictness] and return the result on success, or null if this
* string cannot be parsed.
*/
fun String.toSpdxOrNull(strictness: Strictness = Strictness.ALLOW_ANY): SpdxExpression? =
runCatching {
toSpdx(strictness)
}.onFailure {
logger.debug { "Could not parse '$this' as an SPDX license: ${it.collectMessages()}" }
}.getOrNull()
/**
* Convert a [String] to an SPDX "idstring" (like license IDs, package IDs, etc.) which may only contain letters,
* numbers, ".", and / or "-". If [allowPlusSuffix] is enabled, a "+" (as used in license IDs) is kept as the suffix.
*/
fun String.toSpdxId(allowPlusSuffix: Boolean = false): String {
val hasPlusSuffix = endsWith('+')
val specialValid = setOf('-', '.')
val specialInvalid = setOf(':', '_')
val converted = buildString {
var lastChar: Char? = null
[email protected] { c ->
when {
// Take allowed chars as-is.
c.isLetterOrDigit() || c in specialValid -> c
// Replace colons and underscores with dashes. Do not allow consecutive special chars for readability.
c in specialInvalid -> '-'.takeUnless { lastChar in specialValid }
// Replace anything else with dots. Do not allow consecutive special chars for readability.
else -> '.'.takeUnless { lastChar in specialValid }
}?.let {
append(it)
lastChar = it
}
}
}
// Do not allow leading or trailing special chars for readability.
val trimmed = converted.trim { it in specialValid }
return trimmed.takeUnless { hasPlusSuffix && allowPlusSuffix } ?: "$trimmed+"
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy