1use async_trait::async_trait;
7use std::collections::HashMap;
8use std::sync::Arc;
9
10use crate::controller::base::ElifController;
11use crate::errors::HttpError;
12use crate::request::ElifRequest;
13use elif_core::container::{IocContainer, ScopeId};
14
15#[async_trait]
17pub trait ControllerFactory: Send + Sync {
18 async fn create_controller(
20 &self,
21 container: &IocContainer,
22 scope: Option<&ScopeId>,
23 ) -> Result<Arc<dyn ElifController>, HttpError>;
24}
25
26pub struct IocControllerFactory<T> {
28 _phantom: std::marker::PhantomData<T>,
29}
30
31impl<T> IocControllerFactory<T> {
32 pub fn new() -> Self {
33 Self {
34 _phantom: std::marker::PhantomData,
35 }
36 }
37}
38
39impl<T> Default for IocControllerFactory<T> {
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45#[async_trait]
46impl<T> ControllerFactory for IocControllerFactory<T>
47where
48 T: ElifController + IocControllable + 'static,
49{
50 async fn create_controller(
51 &self,
52 container: &IocContainer,
53 scope: Option<&ScopeId>,
54 ) -> Result<Arc<dyn ElifController>, HttpError> {
55 let controller =
56 T::from_ioc_container(container, scope).map_err(|e| HttpError::InternalError {
57 message: format!("Failed to create controller: {}", e),
58 })?;
59
60 Ok(Arc::new(controller))
61 }
62}
63
64pub trait IocControllable {
66 fn from_ioc_container(
68 container: &IocContainer,
69 scope: Option<&ScopeId>,
70 ) -> Result<Self, String>
71 where
72 Self: Sized;
73}
74
75pub struct ControllerRegistry {
77 factories: HashMap<String, Box<dyn ControllerFactory>>,
78 container: Arc<IocContainer>,
79}
80
81impl ControllerRegistry {
82 pub fn new(container: Arc<IocContainer>) -> Self {
84 Self {
85 factories: HashMap::new(),
86 container,
87 }
88 }
89
90 pub fn register<T>(&mut self, name: &str) -> Result<(), HttpError>
92 where
93 T: ElifController + IocControllable + 'static,
94 {
95 let factory = Box::new(IocControllerFactory::<T>::new());
96 self.factories.insert(name.to_string(), factory);
97 Ok(())
98 }
99
100 pub fn register_factory(&mut self, name: &str, factory: Box<dyn ControllerFactory>) {
102 self.factories.insert(name.to_string(), factory);
103 }
104
105 pub async fn create_controller(
107 &self,
108 name: &str,
109 scope: Option<&ScopeId>,
110 ) -> Result<Arc<dyn ElifController>, HttpError> {
111 let factory = self
112 .factories
113 .get(name)
114 .ok_or_else(|| HttpError::InternalError {
115 message: format!("Controller '{}' not registered", name),
116 })?;
117
118 factory.create_controller(&self.container, scope).await
119 }
120
121 pub async fn create_scoped_registry(
123 &self,
124 request: &ElifRequest,
125 ) -> Result<ScopedControllerRegistry<'_>, HttpError> {
126 let scope_id = self
127 .container
128 .create_scope()
129 .map_err(|e| HttpError::InternalError {
130 message: format!("Failed to create request scope: {}", e),
131 })?;
132
133 Ok(ScopedControllerRegistry {
134 registry: self,
135 scope_id,
136 request_context: RequestContext::from_request(request),
137 })
138 }
139
140 pub fn registered_controllers(&self) -> Vec<String> {
142 self.factories.keys().cloned().collect()
143 }
144}
145
146pub struct ScopedControllerRegistry<'a> {
148 registry: &'a ControllerRegistry,
149 scope_id: ScopeId,
150 #[allow(dead_code)]
151 request_context: RequestContext,
152}
153
154impl<'a> ScopedControllerRegistry<'a> {
155 pub async fn create_controller(
157 &self,
158 name: &str,
159 ) -> Result<Arc<dyn ElifController>, HttpError> {
160 self.registry
164 .create_controller(name, Some(&self.scope_id))
165 .await
166 }
167
168 pub fn scope_id(&self) -> &ScopeId {
170 &self.scope_id
171 }
172
173 pub async fn dispose(self) -> Result<(), HttpError> {
175 self.registry
176 .container
177 .dispose_scope(&self.scope_id)
178 .await
179 .map_err(|e| HttpError::InternalError {
180 message: format!("Failed to dispose scope: {}", e),
181 })
182 }
183}
184
185#[derive(Clone, Debug)]
187pub struct RequestContext {
188 pub method: String,
189 pub path: String,
190 pub query_params: HashMap<String, String>,
191 pub headers: HashMap<String, String>,
192}
193
194impl RequestContext {
195 pub fn from_request(request: &ElifRequest) -> Self {
197 Self {
198 method: request.method.to_string(),
199 path: request.path().to_string(),
200 query_params: HashMap::new(), headers: HashMap::new(), }
203 }
204}
205
206pub struct ControllerRegistryBuilder {
208 container: Option<Arc<IocContainer>>,
209 controllers: Vec<(String, Box<dyn ControllerFactory>)>,
210}
211
212impl ControllerRegistryBuilder {
213 pub fn new() -> Self {
215 Self {
216 container: None,
217 controllers: Vec::new(),
218 }
219 }
220
221 pub fn container(mut self, container: Arc<IocContainer>) -> Self {
223 self.container = Some(container);
224 self
225 }
226
227 pub fn register<T>(mut self, name: &str) -> Self
229 where
230 T: ElifController + IocControllable + 'static,
231 {
232 let factory = Box::new(IocControllerFactory::<T>::new());
233 self.controllers.push((name.to_string(), factory));
234 self
235 }
236
237 pub fn register_factory(mut self, name: &str, factory: Box<dyn ControllerFactory>) -> Self {
239 self.controllers.push((name.to_string(), factory));
240 self
241 }
242
243 pub fn build(self) -> Result<ControllerRegistry, HttpError> {
245 let container = self.container.ok_or_else(|| HttpError::InternalError {
246 message: "IoC container is required for controller registry".to_string(),
247 })?;
248
249 let mut registry = ControllerRegistry::new(container);
250
251 for (name, factory) in self.controllers {
252 registry.register_factory(&name, factory);
253 }
254
255 Ok(registry)
256 }
257}
258
259impl Default for ControllerRegistryBuilder {
260 fn default() -> Self {
261 Self::new()
262 }
263}
264
265pub struct ControllerScanner;
267
268impl ControllerScanner {
269 pub async fn scan_and_register(
272 _registry: &mut ControllerRegistry,
273 _module_path: &str,
274 ) -> Result<usize, HttpError> {
275 Ok(0)
278 }
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284 use crate::controller::base::{ControllerRoute, ElifController};
285 use async_trait::async_trait;
286 use elif_core::ServiceBinder;
287
288 pub struct TestController {
290 #[allow(dead_code)]
291 pub service: Arc<TestService>,
292 }
293
294 #[async_trait]
295 impl ElifController for TestController {
296 fn name(&self) -> &str {
297 "TestController"
298 }
299
300 fn base_path(&self) -> &str {
301 "/test"
302 }
303
304 fn routes(&self) -> Vec<ControllerRoute> {
305 vec![]
306 }
307
308 async fn handle_request(
309 self: Arc<Self>,
310 _method_name: String,
311 _request: ElifRequest,
312 ) -> crate::errors::HttpResult<crate::response::ElifResponse> {
313 Ok(crate::response::ElifResponse::ok().text("test"))
314 }
315 }
316
317 impl IocControllable for TestController {
318 fn from_ioc_container(
319 container: &IocContainer,
320 _scope: Option<&ScopeId>,
321 ) -> Result<Self, String> {
322 let service = container
323 .resolve::<TestService>()
324 .map_err(|e| format!("Failed to resolve TestService: {}", e))?;
325
326 Ok(Self { service })
327 }
328 }
329
330 #[derive(Default)]
332 pub struct TestService {
333 #[allow(dead_code)]
334 pub name: String,
335 }
336
337 unsafe impl Send for TestService {}
338 unsafe impl Sync for TestService {}
339
340 #[tokio::test]
341 async fn test_controller_factory_creation() {
342 let mut container = IocContainer::new();
343 container.bind::<TestService, TestService>();
344 container.build().expect("Container build failed");
345
346 let container_arc = Arc::new(container);
347 let mut registry = ControllerRegistry::new(container_arc);
348
349 registry
350 .register::<TestController>("test")
351 .expect("Failed to register controller");
352
353 let controller = registry
354 .create_controller("test", None)
355 .await
356 .expect("Failed to create controller");
357
358 assert_eq!(controller.name(), "TestController");
359 }
360}