use crate::BoxedBehavior;
use anyhow::{anyhow, Context as AnyhowContext, Result};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
pub type NodeFactory = Arc<dyn Fn(Value) -> Result<BoxedBehavior> + Send + Sync>;
#[derive(Clone)]
pub struct NodeRegistry {
factories: Arc<RwLock<HashMap<String, NodeFactory>>>,
}
impl NodeRegistry {
pub fn new() -> Self {
Self {
factories: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn register<F>(&mut self, node_type: impl Into<String>, factory: F)
where
F: Fn(Value) -> Result<BoxedBehavior> + Send + Sync + 'static,
{
let mut factories = self.factories.write().unwrap();
factories.insert(node_type.into(), Arc::new(factory));
}
pub fn create(&self, node_type: &str, config: Value) -> Result<BoxedBehavior> {
let factories = self.factories.read().unwrap();
let factory = factories
.get(node_type)
.ok_or_else(|| anyhow!("Node type '{}' not registered", node_type))?;
factory(config).with_context(|| format!("Failed to create node of type '{}'", node_type))
}
pub fn has_node(&self, node_type: &str) -> bool {
let factories = self.factories.read().unwrap();
factories.contains_key(node_type)
}
pub fn contains(&self, node_type: &str) -> bool {
let factories = self.factories.read().unwrap();
factories.contains_key(node_type)
}
pub fn registered_types(&self) -> Vec<String> {
let factories = self.factories.read().unwrap();
factories.keys().cloned().collect()
}
pub fn len(&self) -> usize {
let factories = self.factories.read().unwrap();
factories.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Default for NodeRegistry {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for NodeRegistry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let factories = self.factories.read().unwrap();
f.debug_struct("NodeRegistry")
.field("registered_types", &factories.keys().collect::<Vec<_>>())
.finish()
}
}