Skip to main content

coil_ops/reports/
catalog.rs

1use std::collections::HashSet;
2
3use coil_core::ModuleManifest;
4
5use crate::error::OpsModelError;
6use crate::identifiers::ReportId;
7
8use super::ReportDefinition;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct ReportCatalog {
12    pub definitions: Vec<ReportDefinition>,
13}
14
15impl ReportCatalog {
16    pub fn new(definitions: Vec<ReportDefinition>) -> Self {
17        Self { definitions }
18    }
19
20    pub fn standard() -> Self {
21        Self {
22            definitions: Vec::new(),
23        }
24    }
25
26    pub fn from_manifests(manifests: &[ModuleManifest]) -> Result<Self, OpsModelError> {
27        let mut definitions = Vec::new();
28        for manifest in manifests {
29            for definition in &manifest.report_definitions {
30                definitions.push(ReportDefinition::from_manifest_definition(
31                    &manifest.name,
32                    definition,
33                )?);
34            }
35        }
36        let catalog = Self::new(definitions);
37        catalog.validate()?;
38        Ok(catalog)
39    }
40
41    pub fn validate(&self) -> Result<(), OpsModelError> {
42        let mut seen = HashSet::new();
43        for definition in &self.definitions {
44            if !seen.insert(definition.id.as_str().to_string()) {
45                return Err(OpsModelError::DuplicateIdentifier {
46                    kind: "report",
47                    id: definition.id.to_string(),
48                });
49            }
50
51            ReportDefinition::new(
52                definition.id.clone(),
53                definition.source_module.clone(),
54                definition.title.clone(),
55                definition.description.clone(),
56                definition.required_capability,
57                definition.format,
58                definition.sensitivity,
59                definition.delivery_mode,
60                definition.export_prefix.clone(),
61                definition.retry_policy.clone(),
62            )?;
63        }
64
65        Ok(())
66    }
67
68    pub fn definition(&self, id: &ReportId) -> Option<&ReportDefinition> {
69        self.definitions
70            .iter()
71            .find(|definition| &definition.id == id)
72    }
73}
74
75impl Default for ReportCatalog {
76    fn default() -> Self {
77        Self::standard()
78    }
79}