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}