Skip to main content

camel_bean/
registry.rs

1use crate::{BeanError, BeanProcessor};
2use camel_api::{CamelError, Exchange};
3use std::collections::HashMap;
4use std::sync::Arc;
5
6pub struct BeanRegistry {
7    beans: HashMap<String, Arc<dyn BeanProcessor>>,
8}
9
10impl BeanRegistry {
11    pub fn new() -> Self {
12        Self {
13            beans: HashMap::new(),
14        }
15    }
16
17    pub fn register<B>(&mut self, name: impl Into<String>, bean: B)
18    where
19        B: BeanProcessor + 'static,
20    {
21        self.beans.insert(name.into(), Arc::new(bean));
22    }
23
24    pub fn get(&self, name: &str) -> Option<Arc<dyn BeanProcessor>> {
25        self.beans.get(name).cloned()
26    }
27
28    pub async fn invoke(
29        &self,
30        bean_name: &str,
31        method: &str,
32        exchange: &mut Exchange,
33    ) -> Result<(), CamelError> {
34        let bean = self
35            .get(bean_name)
36            .ok_or_else(|| BeanError::NotFound(bean_name.to_string()))?;
37
38        if !bean.methods().contains(&method) {
39            return Err(BeanError::MethodNotFound(method.to_string()).into());
40        }
41
42        bean.call(method, exchange).await
43    }
44
45    pub fn len(&self) -> usize {
46        self.beans.len()
47    }
48
49    pub fn is_empty(&self) -> bool {
50        self.beans.is_empty()
51    }
52}
53
54impl Default for BeanRegistry {
55    fn default() -> Self {
56        Self::new()
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use async_trait::async_trait;
64    use camel_api::{Exchange, Message};
65
66    struct MockBean;
67
68    #[async_trait]
69    impl BeanProcessor for MockBean {
70        async fn call(&self, method: &str, _exchange: &mut Exchange) -> Result<(), CamelError> {
71            match method {
72                "process" => Ok(()),
73                _ => Err(BeanError::MethodNotFound(method.to_string()).into()),
74            }
75        }
76
77        fn methods(&self) -> Vec<&'static str> {
78            vec!["process"]
79        }
80    }
81
82    #[test]
83    fn test_register_and_get() {
84        let mut registry = BeanRegistry::new();
85        registry.register("mock", MockBean);
86
87        assert!(registry.get("mock").is_some());
88        assert!(registry.get("nonexistent").is_none());
89    }
90
91    #[test]
92    fn test_len_and_is_empty() {
93        let mut registry = BeanRegistry::new();
94        assert!(registry.is_empty());
95
96        registry.register("mock", MockBean);
97        assert_eq!(registry.len(), 1);
98        assert!(!registry.is_empty());
99    }
100
101    #[tokio::test]
102    async fn test_invoke_success() {
103        let mut registry = BeanRegistry::new();
104        registry.register("mock", MockBean);
105
106        let mut exchange = Exchange::new(Message::default());
107        let result = registry.invoke("mock", "process", &mut exchange).await;
108
109        assert!(result.is_ok());
110    }
111
112    #[tokio::test]
113    async fn test_invoke_bean_not_found() {
114        let registry = BeanRegistry::new();
115        let mut exchange = Exchange::new(Message::default());
116
117        let result = registry
118            .invoke("nonexistent", "process", &mut exchange)
119            .await;
120        assert!(result.is_err());
121    }
122
123    #[tokio::test]
124    async fn test_invoke_method_not_found() {
125        let mut registry = BeanRegistry::new();
126        registry.register("mock", MockBean);
127
128        let mut exchange = Exchange::new(Message::default());
129        let result = registry.invoke("mock", "unknown", &mut exchange).await;
130
131        assert!(result.is_err());
132    }
133}