use crate::sbom_generation::domain::LicenseInfo;
pub struct LicensePriority;
impl LicensePriority {
pub fn select_license(
license: Option<String>,
license_expression: Option<String>,
classifiers: &[String],
) -> Option<String> {
license
.filter(|l| !l.is_empty() && l != "UNKNOWN")
.or_else(|| license_expression.filter(|l| !l.is_empty()))
.or_else(|| Self::extract_license_from_classifiers(classifiers))
}
pub fn create_license_info(
license: Option<String>,
license_expression: Option<String>,
classifiers: &[String],
summary: Option<String>,
) -> LicenseInfo {
let selected_license = Self::select_license(license, license_expression, classifiers);
LicenseInfo::new(selected_license, summary)
}
fn extract_license_from_classifiers(classifiers: &[String]) -> Option<String> {
for classifier in classifiers {
if let Some(license) = classifier.strip_prefix("License :: OSI Approved :: ") {
return Some(license.to_string());
}
}
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_select_license_prefers_license_field() {
let license = Some("MIT".to_string());
let license_expression = Some("Apache-2.0".to_string());
let classifiers = vec!["License :: OSI Approved :: BSD License".to_string()];
let result = LicensePriority::select_license(license, license_expression, &classifiers);
assert_eq!(result, Some("MIT".to_string()));
}
#[test]
fn test_select_license_falls_back_to_expression() {
let license = None;
let license_expression = Some("Apache-2.0".to_string());
let classifiers = vec!["License :: OSI Approved :: BSD License".to_string()];
let result = LicensePriority::select_license(license, license_expression, &classifiers);
assert_eq!(result, Some("Apache-2.0".to_string()));
}
#[test]
fn test_select_license_falls_back_to_classifiers() {
let license = None;
let license_expression = None;
let classifiers = vec![
"Programming Language :: Python :: 3".to_string(),
"License :: OSI Approved :: MIT License".to_string(),
];
let result = LicensePriority::select_license(license, license_expression, &classifiers);
assert_eq!(result, Some("MIT License".to_string()));
}
#[test]
fn test_select_license_ignores_unknown() {
let license = Some("UNKNOWN".to_string());
let license_expression = Some("MIT".to_string());
let classifiers = vec![];
let result = LicensePriority::select_license(license, license_expression, &classifiers);
assert_eq!(result, Some("MIT".to_string()));
}
#[test]
fn test_select_license_ignores_empty_string() {
let license = Some("".to_string());
let license_expression = Some("GPL-3.0".to_string());
let classifiers = vec![];
let result = LicensePriority::select_license(license, license_expression, &classifiers);
assert_eq!(result, Some("GPL-3.0".to_string()));
}
#[test]
fn test_select_license_no_license_found() {
let license = None;
let license_expression = None;
let classifiers = vec!["Programming Language :: Python :: 3".to_string()];
let result = LicensePriority::select_license(license, license_expression, &classifiers);
assert_eq!(result, None);
}
#[test]
fn test_extract_license_from_classifiers() {
let classifiers = vec![
"Development Status :: 5 - Production/Stable".to_string(),
"License :: OSI Approved :: Apache Software License".to_string(),
"Programming Language :: Python :: 3".to_string(),
];
let result = LicensePriority::extract_license_from_classifiers(&classifiers);
assert_eq!(result, Some("Apache Software License".to_string()));
}
#[test]
fn test_extract_license_from_classifiers_not_found() {
let classifiers = vec![
"Development Status :: 5 - Production/Stable".to_string(),
"Programming Language :: Python :: 3".to_string(),
];
let result = LicensePriority::extract_license_from_classifiers(&classifiers);
assert_eq!(result, None);
}
#[test]
fn test_extract_license_from_classifiers_empty() {
let classifiers: Vec<String> = vec![];
let result = LicensePriority::extract_license_from_classifiers(&classifiers);
assert_eq!(result, None);
}
#[test]
fn test_create_license_info() {
let license = Some("MIT".to_string());
let license_expression = None;
let classifiers = vec![];
let summary = Some("A great library".to_string());
let info = LicensePriority::create_license_info(
license,
license_expression,
&classifiers,
summary.clone(),
);
assert_eq!(info.license_text(), Some("MIT"));
assert_eq!(info.description(), summary.as_deref());
}
#[test]
fn test_create_license_info_no_license() {
let license = None;
let license_expression = None;
let classifiers = vec![];
let summary = Some("A library without license".to_string());
let info = LicensePriority::create_license_info(
license,
license_expression,
&classifiers,
summary,
);
assert_eq!(info.license_text(), None);
}
#[test]
fn test_select_license_complex_priority() {
let license = Some("".to_string());
let license_expression = Some("MIT OR Apache-2.0".to_string());
let classifiers = vec!["License :: OSI Approved :: BSD License".to_string()];
let result = LicensePriority::select_license(license, license_expression, &classifiers);
assert_eq!(result, Some("MIT OR Apache-2.0".to_string()));
}
}