coil_ops/search/
catalog.rs1use super::*;
2use coil_core::ModuleManifest;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct SearchCatalog {
6 pub contributions: Vec<SearchIndexContribution>,
7}
8
9impl SearchCatalog {
10 pub fn new(contributions: Vec<SearchIndexContribution>) -> Self {
11 Self { contributions }
12 }
13
14 pub fn standard() -> Self {
15 Self {
16 contributions: Vec::new(),
17 }
18 }
19
20 pub fn from_manifests(manifests: &[ModuleManifest]) -> Result<Self, OpsModelError> {
21 let mut contributions = Vec::new();
22 for manifest in manifests {
23 for contribution in &manifest.search_contributions {
24 contributions.push(SearchIndexContribution::from_manifest_contribution(
25 &manifest.name,
26 contribution,
27 )?);
28 }
29 }
30 let catalog = Self::new(contributions);
31 catalog.validate()?;
32 Ok(catalog)
33 }
34
35 pub fn validate(&self) -> Result<(), OpsModelError> {
36 let mut seen = HashSet::new();
37 for contribution in &self.contributions {
38 if !seen.insert(contribution.id.as_str().to_string()) {
39 return Err(OpsModelError::DuplicateIdentifier {
40 kind: "search index",
41 id: contribution.id.to_string(),
42 });
43 }
44 SearchIndexContribution::new(
45 contribution.id.clone(),
46 contribution.source_module.clone(),
47 contribution.document_kind,
48 contribution.visibility,
49 contribution.publication_required,
50 contribution.fields.clone(),
51 contribution.invalidation_rules.clone(),
52 contribution.rebuild_strategy,
53 )?;
54 }
55
56 Ok(())
57 }
58
59 pub fn contribution(&self, id: &SearchIndexId) -> Option<&SearchIndexContribution> {
60 self.contributions
61 .iter()
62 .find(|contribution| &contribution.id == id)
63 }
64
65 pub fn visible_to(&self, capabilities: &[Capability]) -> Vec<&SearchIndexContribution> {
66 self.contributions
67 .iter()
68 .filter(|contribution| contribution.visible_to(capabilities))
69 .collect()
70 }
71}
72
73impl Default for SearchCatalog {
74 fn default() -> Self {
75 Self::standard()
76 }
77}