use std::collections::BTreeMap;
use omena_cascade::{
CascadeDeclaration, CascadeKey, CascadeValue, LayerRank, ModuleRank, Specificity,
cascade_level_for_origin, cascade_property, parse_simple_selector_signature,
};
use omena_query_checker_orchestrator::{
OmenaCheckerCascadeDeclarationInputV0, REPLICA_ENSEMBLE_FEATURE_GATE_V0,
REPLICA_ENSEMBLE_LAYER_MARKER_V0, REPLICA_ENSEMBLE_SCHEMA_VERSION_V0, ReplicaSiteOutcomeV0,
site as replica_ensemble_site,
};
use super::collect_query_checker_cascade_declarations;
pub(in crate::style) fn collect_query_replica_ensemble_site_outcomes(
source: &str,
) -> Vec<ReplicaSiteOutcomeV0> {
let declarations = collect_query_checker_cascade_declarations(source);
let mut by_site: BTreeMap<(String, String), Vec<CascadeDeclaration>> = BTreeMap::new();
for declaration in &declarations {
let property = declaration.input.property.as_str();
if property.starts_with("--") {
continue;
}
let cascade_declaration = query_cascade_declaration_from_input(&declaration.input);
by_site
.entry((
declaration.input.selector.as_str().to_string(),
declaration.input.property.clone(),
))
.or_default()
.push(cascade_declaration);
}
by_site
.into_iter()
.filter_map(|((selector, property), site_declarations)| {
let outcome = cascade_property(site_declarations, &property);
if !matches!(outcome, omena_cascade::CascadeOutcome::Definite { .. }) {
return None;
}
Some(ReplicaSiteOutcomeV0 {
schema_version: REPLICA_ENSEMBLE_SCHEMA_VERSION_V0,
product: "omena-ensemble.replica-site-outcome",
layer_marker: REPLICA_ENSEMBLE_LAYER_MARKER_V0,
feature_gate: REPLICA_ENSEMBLE_FEATURE_GATE_V0,
site: replica_ensemble_site(selector, property),
outcome,
provenance: None,
})
})
.collect()
}
fn query_cascade_declaration_from_input(
input: &OmenaCheckerCascadeDeclarationInputV0,
) -> CascadeDeclaration {
let level = cascade_level_for_origin(input.origin, input.important);
let layer_rank = LayerRank(input.layer_order.unwrap_or(0));
let (specificity, specificity_exactness) =
parse_simple_selector_signature(input.selector.as_str()).map_or(
(
Specificity::ZERO,
omena_cascade::SpecificityExactnessV0::Inexact,
),
|signature| (signature.specificity, signature.specificity_exactness),
);
let value = input.value.trim().to_string();
CascadeDeclaration {
id: value.clone(),
property: input.property.clone(),
value: CascadeValue::Literal(value),
key: CascadeKey::new(
level,
layer_rank,
0,
specificity,
ModuleRank::ZERO,
input.source_order,
),
specificity_exactness,
}
}