use crate::matching::RuleEngine;
use crate::model::{CanonicalId, NormalizedSbom};
use indexmap::IndexMap;
use std::collections::HashMap;
pub struct RuleApplicationResult {
pub old_filtered: NormalizedSbom,
pub new_filtered: NormalizedSbom,
pub old_canonical: HashMap<CanonicalId, CanonicalId>,
pub new_canonical: HashMap<CanonicalId, CanonicalId>,
pub rules_count: usize,
}
pub fn apply_rules(
rule_engine: Option<&RuleEngine>,
old: &NormalizedSbom,
new: &NormalizedSbom,
) -> Option<RuleApplicationResult> {
let engine = rule_engine?;
let old_result = engine.apply(&old.components);
let new_result = engine.apply(&new.components);
let old_components: IndexMap<_, _> = old
.components
.iter()
.filter(|(id, _)| !old_result.excluded.contains(*id))
.map(|(id, c)| (id.clone(), c.clone()))
.collect();
let new_components: IndexMap<_, _> = new
.components
.iter()
.filter(|(id, _)| !new_result.excluded.contains(*id))
.map(|(id, c)| (id.clone(), c.clone()))
.collect();
let mut old_filtered = old.clone();
old_filtered.components = old_components;
old_filtered
.edges
.retain(|e| !old_result.excluded.contains(&e.from) && !old_result.excluded.contains(&e.to));
let mut new_filtered = new.clone();
new_filtered.components = new_components;
new_filtered
.edges
.retain(|e| !new_result.excluded.contains(&e.from) && !new_result.excluded.contains(&e.to));
let rules_count = old_result.applied_rules.len() + new_result.applied_rules.len();
Some(RuleApplicationResult {
old_filtered,
new_filtered,
old_canonical: old_result.canonical_map,
new_canonical: new_result.canonical_map,
rules_count,
})
}