use std::{collections::HashMap, sync::Arc};
use crate::{
command::CommandHandlerRegistration,
item::{IngestBufferPolicy, IngestBufferRegistration, ItemParseFn, ItemRegistration},
query::{QueryCellFactory, QueryParseFn, QueryRegistration},
report::{ReportCellFactory, ReportParseFn, ReportRegistration},
view::{ViewCellFactory, ViewParseFn, ViewRegistration},
};
pub struct StoredQueryData {
pub query_id: Arc<str>,
pub query_item_type: Arc<str>,
pub parse: QueryParseFn,
pub cell_factory: QueryCellFactory,
}
pub struct StoredViewData {
pub view_id: Arc<str>,
pub view_item_type: Arc<str>,
pub parse: ViewParseFn,
pub cell_factory: ViewCellFactory,
}
pub struct StoredReportData {
pub report_id: Arc<str>,
pub parse: ReportParseFn,
pub cell_factory: ReportCellFactory,
}
pub struct HandlerRegistry {
item_parsers: HashMap<Arc<str>, ItemParseFn>,
item_buffer_policies: HashMap<Arc<str>, IngestBufferPolicy>,
query_data: HashMap<Arc<str>, StoredQueryData>,
view_data: HashMap<Arc<str>, StoredViewData>,
report_data: HashMap<Arc<str>, StoredReportData>,
}
impl HandlerRegistry {
pub fn new() -> Self {
let mut item_parsers = HashMap::new();
let mut item_buffer_policies = HashMap::new();
let mut query_data = HashMap::new();
let mut view_data = HashMap::new();
let mut report_data = HashMap::new();
for registration in inventory::iter::<ItemRegistration> {
log::trace!("Registered item parser: {}", registration.entity_type);
item_parsers.insert(registration.entity_type.into(), registration.parse);
}
for registration in inventory::iter::<IngestBufferRegistration> {
log::trace!(
"Registered ingest buffer policy: {} -> {:?}",
registration.entity_type,
registration.policy
);
item_buffer_policies.insert(registration.entity_type.into(), registration.policy);
}
for registration in inventory::iter::<QueryRegistration> {
log::trace!("Registered query: {}", registration.query_id);
let data = StoredQueryData {
query_id: registration.query_id.into(),
query_item_type: registration.query_item_type.into(),
parse: registration.parse,
cell_factory: registration.cell_factory,
};
query_data.insert(data.query_id.clone(), data);
}
for registration in inventory::iter::<ViewRegistration> {
log::trace!("Registered view: {}", registration.view_id);
let data = StoredViewData {
view_id: registration.view_id.into(),
view_item_type: registration.view_item_type.into(),
parse: registration.parse,
cell_factory: registration.cell_factory,
};
view_data.insert(data.view_id.clone(), data);
}
for registration in inventory::iter::<ReportRegistration> {
log::trace!("Registered report: {}", registration.report_id);
let data = StoredReportData {
report_id: registration.report_id.into(),
parse: registration.parse,
cell_factory: registration.cell_factory,
};
report_data.insert(data.report_id.clone(), data);
}
let mut command_ids: Vec<&str> = inventory::iter::<CommandHandlerRegistration>()
.map(|r| r.command_id)
.collect();
command_ids.sort_unstable();
fn format_list<'a>(keys: impl Iterator<Item = &'a Arc<str>>) -> String {
let mut items: Vec<&str> = keys.map(|k| k.as_ref()).collect();
items.sort_unstable();
if items.is_empty() {
"(none)".to_string()
} else {
items.join(", ")
}
}
fn format_str_list(items: &[&str]) -> String {
if items.is_empty() {
"(none)".to_string()
} else {
items.join(", ")
}
}
log::trace!(
"HandlerRegistry initialized:\n Items ({}):\n {}\n Queries ({}):\n {}\n Views ({}):\n {}\n Reports ({}):\n {}\n Commands ({}):\n {}",
item_parsers.len(),
format_list(item_parsers.keys()),
query_data.len(),
format_list(query_data.keys()),
view_data.len(),
format_list(view_data.keys()),
report_data.len(),
format_list(report_data.keys()),
command_ids.len(),
format_str_list(&command_ids),
);
Self {
item_parsers,
item_buffer_policies,
query_data,
view_data,
report_data,
}
}
pub fn get_item_parser(&self, entity_type: &str) -> Option<ItemParseFn> {
self.item_parsers.get(entity_type).copied()
}
pub fn get_item_buffer_policy(&self, entity_type: &str) -> IngestBufferPolicy {
self.item_buffer_policies
.get(entity_type)
.copied()
.unwrap_or(IngestBufferPolicy::None)
}
pub fn get_query(&self, query_id: &str) -> Option<&StoredQueryData> {
self.query_data.get(query_id)
}
pub fn get_report(&self, report_id: &str) -> Option<&StoredReportData> {
self.report_data.get(report_id)
}
pub fn get_view(&self, view_id: &str) -> Option<&StoredViewData> {
self.view_data.get(view_id)
}
pub fn has_item_parser(&self, entity_type: &str) -> bool {
self.item_parsers.contains_key(entity_type)
}
pub fn entity_types(&self) -> impl Iterator<Item = &Arc<str>> {
self.item_parsers.keys()
}
pub fn query_ids(&self) -> impl Iterator<Item = &Arc<str>> {
self.query_data.keys()
}
pub fn report_ids(&self) -> impl Iterator<Item = &Arc<str>> {
self.report_data.keys()
}
pub fn view_ids(&self) -> impl Iterator<Item = &Arc<str>> {
self.view_data.keys()
}
}
impl Default for HandlerRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_registry_creation() {
let registry = HandlerRegistry::new();
let _ = registry.entity_types().count();
}
}