elif_core/container/
phase6_demo.rs

1/*!
2 * Phase 6 Demo: Developer Experience & Tooling
3 *
4 * This demo shows the new Phase 6 features for IoC Phase 6 - Developer Experience & Tooling
5 * including auto-wiring conventions, module system, validation, visualization, and debug utilities.
6 */
7
8use crate::container::binding::ServiceBinder;
9use crate::container::conventions::{
10    ServiceConventions, ServiceMetadata, ServiceRegistry as ConventionServiceRegistry,
11};
12use crate::container::debug::ContainerInspector;
13use crate::container::ioc_container::IocContainer;
14use crate::container::module::{ModuleRegistry, ServiceModule};
15use crate::container::scope::ServiceScope;
16use crate::container::visualization::{
17    DependencyVisualizer, VisualizationFormat, VisualizationStyle,
18};
19use crate::errors::CoreError;
20use std::sync::Arc;
21
22/// Example service for demonstration
23#[derive(Default)]
24pub struct UserService;
25
26impl UserService {
27    pub fn get_user(&self, _id: u32) -> String {
28        "Demo User".to_string()
29    }
30}
31
32/// Example repository service
33#[derive(Default)]
34pub struct UserRepository;
35
36impl UserRepository {
37    pub fn find_user(&self, _id: u32) -> Option<String> {
38        Some("Repository User".to_string())
39    }
40}
41
42/// Example logger service
43#[derive(Default)]
44pub struct AppLogger;
45
46impl AppLogger {
47    pub fn log(&self, message: &str) {
48        println!("[LOG] {}", message);
49    }
50}
51
52/// Example module demonstrating the module system
53pub struct UserModule;
54
55impl ServiceModule for UserModule {
56    fn name(&self) -> &str {
57        "User Management Module"
58    }
59
60    fn description(&self) -> Option<&str> {
61        Some("Handles user-related services and operations")
62    }
63
64    fn version(&self) -> Option<&str> {
65        Some("1.0.0")
66    }
67
68    fn configure(&self, services: &mut crate::container::binding::ServiceBindings) {
69        // Example of registering services for this module
70        services.bind::<UserService, UserService>();
71        services.bind::<UserRepository, UserRepository>();
72    }
73
74    fn depends_on(&self) -> Vec<crate::container::module::ModuleId> {
75        vec![]
76    }
77}
78
79/// Core module that other modules depend on
80pub struct CoreModule;
81
82impl ServiceModule for CoreModule {
83    fn name(&self) -> &str {
84        "Core Module"
85    }
86
87    fn description(&self) -> Option<&str> {
88        Some("Core application services")
89    }
90
91    fn configure(&self, services: &mut crate::container::binding::ServiceBindings) {
92        // Example of registering services for this module
93        services.bind::<AppLogger, AppLogger>();
94        // Note: DatabaseConnection would need to be defined to actually bind it
95        // services.bind::<DatabaseConnection, DatabaseConnection>();
96    }
97}
98
99/// Demo function for Phase 6 features
100pub fn demo_phase6_features() -> Result<(), CoreError> {
101    println!("=== Phase 6 Demo: Developer Experience & Tooling ===");
102    println!();
103
104    // 1. Auto-wiring Conventions Demo
105    println!("1. Auto-wiring Conventions:");
106    println!("---------------------------");
107
108    let mut conventions = ServiceConventions::new();
109    conventions.add_naming_convention("*Service", ServiceScope::Singleton);
110    conventions.add_naming_convention("*Repository", ServiceScope::Scoped);
111    conventions.add_naming_convention("*Logger", ServiceScope::Singleton);
112
113    println!(
114        "✓ UserService lifetime: {:?}",
115        conventions.get_lifetime_for_type("UserService")
116    );
117    println!(
118        "✓ UserRepository lifetime: {:?}",
119        conventions.get_lifetime_for_type("UserRepository")
120    );
121    println!(
122        "✓ AppLogger lifetime: {:?}",
123        conventions.get_lifetime_for_type("AppLogger")
124    );
125
126    // Register services using conventions
127    let mut service_registry = ConventionServiceRegistry::new();
128
129    let user_service_metadata =
130        ServiceMetadata::new("UserService".to_string()).with_lifetime(ServiceScope::Singleton);
131    service_registry.register_service(user_service_metadata);
132
133    let user_repo_metadata =
134        ServiceMetadata::new("UserRepository".to_string()).with_lifetime(ServiceScope::Scoped);
135    service_registry.register_service(user_repo_metadata);
136
137    println!(
138        "✓ Registered {} services with conventions",
139        service_registry.all_services().len()
140    );
141    println!();
142
143    // 2. Module System Demo
144    println!("2. Module System:");
145    println!("-----------------");
146
147    let mut module_registry = ModuleRegistry::new();
148
149    // Register modules
150    module_registry.register_module(CoreModule, None)?;
151    module_registry.register_module(UserModule, None)?;
152
153    // Calculate load order
154    let load_order = module_registry.calculate_load_order()?;
155    println!(
156        "✓ Module load order calculated: {} modules",
157        load_order.len()
158    );
159
160    for (i, module_id) in load_order.iter().enumerate() {
161        if let Some(loaded_module) = module_registry.get_loaded_module(module_id) {
162            println!(
163                "  {}. {} ({})",
164                i + 1,
165                loaded_module.metadata.name,
166                loaded_module
167                    .metadata
168                    .version
169                    .as_deref()
170                    .unwrap_or("no version")
171            );
172        }
173    }
174    println!();
175
176    // 3. Container Inspection Demo
177    println!("3. Debug & Inspection Tools:");
178    println!("-----------------------------");
179
180    let container = IocContainer::new();
181    let inspector = ContainerInspector::new(Arc::new(container));
182
183    let container_info = inspector.get_container_info();
184    println!(
185        "✓ Container Status: {}",
186        if container_info.is_built {
187            "Built"
188        } else {
189            "Not Built"
190        }
191    );
192    println!("✓ Registered Services: {}", container_info.service_count);
193    println!("✓ Cached Instances: {}", container_info.cached_instances);
194    println!();
195
196    // 4. Visualization Demo
197    println!("4. Dependency Visualization:");
198    println!("----------------------------");
199
200    // Create a simple visualizer (would normally use real descriptors)
201    let descriptors = vec![]; // Empty for demo
202    let visualizer = DependencyVisualizer::new(descriptors);
203
204    // Generate different visualization formats
205    let style = VisualizationStyle::default();
206
207    match visualizer.visualize(VisualizationFormat::Ascii, style.clone()) {
208        Ok(ascii_viz) => {
209            println!("✓ ASCII Visualization Generated:");
210            println!(
211                "{}",
212                ascii_viz.lines().take(10).collect::<Vec<_>>().join("\n")
213            );
214            if ascii_viz.lines().count() > 10 {
215                println!("  ... (truncated)");
216            }
217        }
218        Err(e) => println!("⚠️  ASCII visualization failed: {}", e),
219    }
220    println!();
221
222    match visualizer.visualize(VisualizationFormat::Json, style) {
223        Ok(json_viz) => {
224            println!("✓ JSON Visualization Generated ({} bytes)", json_viz.len());
225            // Show first few lines
226            let preview: String = json_viz.chars().take(200).collect();
227            println!("  Preview: {}...", preview);
228        }
229        Err(e) => println!("⚠️  JSON visualization failed: {}", e),
230    }
231    println!();
232
233    // 5. Health Check Demo
234    println!("5. Container Health Monitoring:");
235    println!("-------------------------------");
236
237    // This would normally perform actual health checks
238    println!("✓ Health Check System Available");
239    println!("✓ Performance Profiler Available");
240    println!("✓ Resolution Tracer Available");
241    println!();
242
243    println!("🎉 Phase 6 Demo Complete!");
244    println!("   All developer experience and tooling features are operational.");
245
246    Ok(())
247}
248
249#[cfg(test)]
250mod tests {
251    use super::*;
252
253    #[test]
254    fn test_phase6_demo() {
255        let result = demo_phase6_features();
256        assert!(result.is_ok(), "Phase 6 demo should run successfully");
257    }
258
259    #[test]
260    fn test_service_conventions() {
261        let conventions = ServiceConventions::new();
262
263        // Test default naming conventions
264        assert_eq!(
265            conventions.get_lifetime_for_type("UserService"),
266            ServiceScope::Singleton
267        );
268        assert_eq!(
269            conventions.get_lifetime_for_type("UserRepository"),
270            ServiceScope::Scoped
271        );
272        assert_eq!(
273            conventions.get_lifetime_for_type("PaymentFactory"),
274            ServiceScope::Transient
275        );
276        assert_eq!(
277            conventions.get_lifetime_for_type("AppLogger"),
278            ServiceScope::Singleton
279        );
280    }
281
282    #[test]
283    fn test_module_registry() {
284        let mut registry = ModuleRegistry::new();
285
286        // Register modules
287        assert!(registry.register_module(CoreModule, None).is_ok());
288        assert!(registry.register_module(UserModule, None).is_ok());
289
290        // Calculate load order
291        let load_order = registry.calculate_load_order();
292        assert!(load_order.is_ok());
293        assert_eq!(load_order.unwrap().len(), 2);
294    }
295
296    #[test]
297    fn test_container_inspector() {
298        let container = IocContainer::new();
299        let inspector = ContainerInspector::new(Arc::new(container));
300
301        let info = inspector.get_container_info();
302        assert!(!info.is_built); // New container should not be built
303        assert_eq!(info.service_count, 0); // Should have no services initially
304    }
305
306    #[test]
307    fn test_service_metadata() {
308        let metadata = ServiceMetadata::new("TestService".to_string())
309            .with_lifetime(ServiceScope::Singleton)
310            .with_name("test".to_string())
311            .as_default()
312            .with_tag("core".to_string());
313
314        assert_eq!(metadata.type_name, "TestService");
315        assert_eq!(metadata.lifetime, Some(ServiceScope::Singleton));
316        assert_eq!(metadata.name, Some("test".to_string()));
317        assert!(metadata.is_default);
318        assert_eq!(metadata.tags, vec!["core"]);
319    }
320}