Skip to main content

batuta/data/
tree.rs

1//! Data Platforms Ecosystem Tree Visualization
2//!
3//! Provides hierarchical views of:
4//! - Enterprise data platform ecosystems
5//! - PAIML-Platform integration mappings
6
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10// ============================================================================
11// DATA-TREE-001: Core Types
12// ============================================================================
13
14/// Supported data platforms
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub enum Platform {
17    Databricks,
18    Snowflake,
19    Aws,
20    HuggingFace,
21    Paiml,
22}
23
24impl Platform {
25    /// Get display name
26    #[must_use]
27    pub const fn name(&self) -> &'static str {
28        match self {
29            Self::Databricks => "DATABRICKS",
30            Self::Snowflake => "SNOWFLAKE",
31            Self::Aws => "AWS",
32            Self::HuggingFace => "HUGGINGFACE",
33            Self::Paiml => "PAIML",
34        }
35    }
36
37    /// Get all platforms
38    #[must_use]
39    pub fn all() -> Vec<Self> {
40        vec![Self::Databricks, Self::Snowflake, Self::Aws, Self::HuggingFace]
41    }
42}
43
44impl fmt::Display for Platform {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "{}", self.name())
47    }
48}
49
50/// Platform category
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct PlatformCategory {
53    pub name: String,
54    pub components: Vec<PlatformComponent>,
55}
56
57impl PlatformCategory {
58    pub fn new(name: impl Into<String>) -> Self {
59        Self { name: name.into(), components: Vec::new() }
60    }
61
62    pub fn with_component(mut self, component: PlatformComponent) -> Self {
63        self.components.push(component);
64        self
65    }
66}
67
68/// A component within a platform
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct PlatformComponent {
71    pub name: String,
72    pub description: String,
73    pub sub_components: Vec<String>,
74}
75
76impl PlatformComponent {
77    pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
78        Self { name: name.into(), description: description.into(), sub_components: Vec::new() }
79    }
80
81    pub fn with_sub(mut self, sub: impl Into<String>) -> Self {
82        self.sub_components.push(sub.into());
83        self
84    }
85}
86
87/// Complete platform tree
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct DataPlatformTree {
90    pub platform: Platform,
91    pub categories: Vec<PlatformCategory>,
92}
93
94impl DataPlatformTree {
95    pub fn new(platform: Platform) -> Self {
96        Self { platform, categories: Vec::new() }
97    }
98
99    pub fn add_category(mut self, category: PlatformCategory) -> Self {
100        self.categories.push(category);
101        self
102    }
103
104    pub fn total_components(&self) -> usize {
105        self.categories.iter().map(|c| c.components.len()).sum()
106    }
107}
108
109// ============================================================================
110// DATA-TREE-002: Integration Types
111// ============================================================================
112
113/// Integration type between PAIML and data platforms
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
115pub enum IntegrationType {
116    /// PAIML is compatible with platform format
117    Compatible,
118    /// PAIML provides a native Rust alternative
119    Alternative,
120    /// PAIML orchestrates platform workflows
121    Orchestrates,
122    /// PAIML uses platform directly
123    Uses,
124    /// PAIML transpiles platform code
125    Transpiles,
126}
127
128impl IntegrationType {
129    /// Get short code for display
130    #[must_use]
131    pub const fn code(&self) -> &'static str {
132        match self {
133            Self::Compatible => "CMP",
134            Self::Alternative => "ALT",
135            Self::Orchestrates => "ORC",
136            Self::Uses => "USE",
137            Self::Transpiles => "TRN",
138        }
139    }
140
141    /// Get description
142    #[must_use]
143    pub const fn description(&self) -> &'static str {
144        match self {
145            Self::Compatible => "Compatible format/protocol",
146            Self::Alternative => "PAIML native alternative",
147            Self::Orchestrates => "PAIML orchestrates",
148            Self::Uses => "PAIML uses directly",
149            Self::Transpiles => "PAIML transpiles to Rust",
150        }
151    }
152}
153
154impl fmt::Display for IntegrationType {
155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156        write!(f, "[{}]", self.code())
157    }
158}
159
160/// Integration mapping between platform and PAIML
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct IntegrationMapping {
163    pub platform_component: String,
164    pub paiml_component: String,
165    pub integration_type: IntegrationType,
166    pub category: String,
167}
168
169impl IntegrationMapping {
170    pub fn new(
171        platform: impl Into<String>,
172        paiml: impl Into<String>,
173        integration_type: IntegrationType,
174        category: impl Into<String>,
175    ) -> Self {
176        Self {
177            platform_component: platform.into(),
178            paiml_component: paiml.into(),
179            integration_type,
180            category: category.into(),
181        }
182    }
183}
184
185// ============================================================================
186// DATA-TREE-003: Tree Builders
187// ============================================================================
188
189/// Build the Databricks platform tree
190#[must_use]
191pub fn build_databricks_tree() -> DataPlatformTree {
192    DataPlatformTree::new(Platform::Databricks)
193        .add_category(
194            PlatformCategory::new("Unity Catalog").with_component(
195                PlatformComponent::new("Unity Catalog", "Unified governance for data and AI")
196                    .with_sub("Schemas")
197                    .with_sub("Tables")
198                    .with_sub("Views"),
199            ),
200        )
201        .add_category(
202            PlatformCategory::new("Delta Lake").with_component(
203                PlatformComponent::new("Delta Lake", "ACID transactions on data lakes")
204                    .with_sub("Parquet storage")
205                    .with_sub("Transaction log")
206                    .with_sub("Time travel"),
207            ),
208        )
209        .add_category(
210            PlatformCategory::new("MLflow").with_component(
211                PlatformComponent::new("MLflow", "ML lifecycle management")
212                    .with_sub("Experiment tracking")
213                    .with_sub("Model registry")
214                    .with_sub("Model serving"),
215            ),
216        )
217        .add_category(
218            PlatformCategory::new("Spark").with_component(
219                PlatformComponent::new("Spark", "Distributed compute engine")
220                    .with_sub("DataFrames")
221                    .with_sub("Structured Streaming")
222                    .with_sub("MLlib"),
223            ),
224        )
225}
226
227/// Build the Snowflake platform tree
228#[must_use]
229pub fn build_snowflake_tree() -> DataPlatformTree {
230    DataPlatformTree::new(Platform::Snowflake)
231        .add_category(
232            PlatformCategory::new("Virtual Warehouse").with_component(
233                PlatformComponent::new("Virtual Warehouse", "Elastic compute clusters")
234                    .with_sub("Compute clusters")
235                    .with_sub("Result cache")
236                    .with_sub("Auto-scaling"),
237            ),
238        )
239        .add_category(
240            PlatformCategory::new("Iceberg Tables").with_component(
241                PlatformComponent::new("Iceberg Tables", "Open table format support")
242                    .with_sub("Open format")
243                    .with_sub("Schema evolution")
244                    .with_sub("Partition pruning"),
245            ),
246        )
247        .add_category(
248            PlatformCategory::new("Snowpark").with_component(
249                PlatformComponent::new("Snowpark", "Developer experience for data")
250                    .with_sub("Python UDFs")
251                    .with_sub("Java/Scala UDFs")
252                    .with_sub("ML functions"),
253            ),
254        )
255        .add_category(
256            PlatformCategory::new("Data Sharing").with_component(
257                PlatformComponent::new("Data Sharing", "Secure data exchange")
258                    .with_sub("Secure shares")
259                    .with_sub("Reader accounts")
260                    .with_sub("Marketplace"),
261            ),
262        )
263}
264
265/// Build the AWS platform tree
266#[must_use]
267pub fn build_aws_tree() -> DataPlatformTree {
268    DataPlatformTree::new(Platform::Aws)
269        .add_category(
270            PlatformCategory::new("Storage")
271                .with_component(
272                    PlatformComponent::new("S3", "Object storage")
273                        .with_sub("Objects")
274                        .with_sub("Versioning")
275                        .with_sub("Lifecycle"),
276                )
277                .with_component(
278                    PlatformComponent::new("Glue Catalog", "Metadata catalog")
279                        .with_sub("Databases")
280                        .with_sub("Tables")
281                        .with_sub("Crawlers"),
282                )
283                .with_component(PlatformComponent::new("Lake Formation", "Data lake management")),
284        )
285        .add_category(
286            PlatformCategory::new("Compute")
287                .with_component(PlatformComponent::new("EMR", "Managed Spark/Hadoop"))
288                .with_component(PlatformComponent::new("Lambda", "Serverless functions"))
289                .with_component(PlatformComponent::new("ECS/EKS", "Container orchestration")),
290        )
291        .add_category(
292            PlatformCategory::new("ML")
293                .with_component(
294                    PlatformComponent::new("SageMaker", "ML platform")
295                        .with_sub("Training")
296                        .with_sub("Endpoints")
297                        .with_sub("Pipelines"),
298                )
299                .with_component(
300                    PlatformComponent::new("Bedrock", "Foundation models")
301                        .with_sub("Foundation models")
302                        .with_sub("Fine-tuning")
303                        .with_sub("Agents"),
304                )
305                .with_component(PlatformComponent::new("Comprehend", "NLP service")),
306        )
307        .add_category(
308            PlatformCategory::new("Analytics")
309                .with_component(PlatformComponent::new("Athena", "Serverless SQL"))
310                .with_component(PlatformComponent::new("Redshift", "Data warehouse"))
311                .with_component(PlatformComponent::new("QuickSight", "BI dashboards")),
312        )
313}
314
315/// Build the HuggingFace platform tree
316#[must_use]
317pub fn build_huggingface_tree() -> DataPlatformTree {
318    DataPlatformTree::new(Platform::HuggingFace)
319        .add_category(
320            PlatformCategory::new("Hub").with_component(
321                PlatformComponent::new("Hub", "Model and dataset repository")
322                    .with_sub("Models (500K+)")
323                    .with_sub("Datasets (100K+)")
324                    .with_sub("Spaces (200K+)"),
325            ),
326        )
327        .add_category(
328            PlatformCategory::new("Libraries")
329                .with_component(PlatformComponent::new("Transformers", "Model library"))
330                .with_component(PlatformComponent::new("Datasets", "Dataset library"))
331                .with_component(PlatformComponent::new("Tokenizers", "Fast tokenization"))
332                .with_component(PlatformComponent::new("Accelerate", "Distributed training")),
333        )
334        .add_category(
335            PlatformCategory::new("Formats")
336                .with_component(PlatformComponent::new("SafeTensors", "Safe model format"))
337                .with_component(PlatformComponent::new("GGUF", "Quantized models"))
338                .with_component(PlatformComponent::new("ONNX", "Interop format")),
339        )
340}
341
342// ============================================================================
343// DATA-TREE-004: Integration Mappings
344// ============================================================================
345
346/// Build all integration mappings
347#[must_use]
348pub fn build_integration_mappings() -> Vec<IntegrationMapping> {
349    vec![
350        // Storage & Catalogs
351        IntegrationMapping::new(
352            "Delta Lake",
353            "Alimentar (.ald)",
354            IntegrationType::Alternative,
355            "STORAGE & CATALOGS",
356        ),
357        IntegrationMapping::new(
358            "Iceberg Tables",
359            "Alimentar (.ald)",
360            IntegrationType::Compatible,
361            "STORAGE & CATALOGS",
362        ),
363        IntegrationMapping::new(
364            "S3",
365            "Alimentar (sync)",
366            IntegrationType::Compatible,
367            "STORAGE & CATALOGS",
368        ),
369        IntegrationMapping::new(
370            "Unity Catalog",
371            "Pacha Registry",
372            IntegrationType::Alternative,
373            "STORAGE & CATALOGS",
374        ),
375        IntegrationMapping::new(
376            "Glue Catalog",
377            "Pacha Registry",
378            IntegrationType::Alternative,
379            "STORAGE & CATALOGS",
380        ),
381        IntegrationMapping::new(
382            "HuggingFace Hub",
383            "Pacha Registry",
384            IntegrationType::Alternative,
385            "STORAGE & CATALOGS",
386        ),
387        // Compute & Processing
388        IntegrationMapping::new(
389            "Spark DataFrames",
390            "Trueno",
391            IntegrationType::Alternative,
392            "COMPUTE & PROCESSING",
393        ),
394        IntegrationMapping::new(
395            "Snowpark",
396            "Trueno",
397            IntegrationType::Alternative,
398            "COMPUTE & PROCESSING",
399        ),
400        IntegrationMapping::new(
401            "EMR",
402            "Trueno",
403            IntegrationType::Alternative,
404            "COMPUTE & PROCESSING",
405        ),
406        IntegrationMapping::new(
407            "Snowpark Python",
408            "Depyler → Rust",
409            IntegrationType::Transpiles,
410            "COMPUTE & PROCESSING",
411        ),
412        IntegrationMapping::new(
413            "Lambda Python",
414            "Depyler → Rust",
415            IntegrationType::Transpiles,
416            "COMPUTE & PROCESSING",
417        ),
418        IntegrationMapping::new(
419            "Neptune/GraphQL",
420            "Trueno-Graph",
421            IntegrationType::Alternative,
422            "COMPUTE & PROCESSING",
423        ),
424        // ML Training
425        IntegrationMapping::new("MLlib", "Aprender", IntegrationType::Alternative, "ML TRAINING"),
426        IntegrationMapping::new(
427            "Snowpark ML",
428            "Aprender",
429            IntegrationType::Alternative,
430            "ML TRAINING",
431        ),
432        IntegrationMapping::new(
433            "SageMaker Training",
434            "Entrenar",
435            IntegrationType::Alternative,
436            "ML TRAINING",
437        ),
438        IntegrationMapping::new(
439            "MLflow Tracking",
440            "Entrenar",
441            IntegrationType::Alternative,
442            "ML TRAINING",
443        ),
444        IntegrationMapping::new(
445            "SageMaker Experiments",
446            "Entrenar",
447            IntegrationType::Alternative,
448            "ML TRAINING",
449        ),
450        IntegrationMapping::new("W&B", "Entrenar", IntegrationType::Uses, "ML TRAINING"),
451        // Model Serving
452        IntegrationMapping::new(
453            "MLflow Serving",
454            "Realizar",
455            IntegrationType::Alternative,
456            "MODEL SERVING",
457        ),
458        IntegrationMapping::new(
459            "SageMaker Endpoints",
460            "Realizar",
461            IntegrationType::Alternative,
462            "MODEL SERVING",
463        ),
464        IntegrationMapping::new(
465            "Bedrock",
466            "Realizar + serve",
467            IntegrationType::Alternative,
468            "MODEL SERVING",
469        ),
470        IntegrationMapping::new("GGUF models", "Realizar", IntegrationType::Uses, "MODEL SERVING"),
471        IntegrationMapping::new(
472            "HF Transformers",
473            "Realizar (via GGUF)",
474            IntegrationType::Compatible,
475            "MODEL SERVING",
476        ),
477        // Orchestration
478        IntegrationMapping::new(
479            "Databricks Workflows",
480            "Batuta",
481            IntegrationType::Orchestrates,
482            "ORCHESTRATION",
483        ),
484        IntegrationMapping::new(
485            "Snowflake Tasks",
486            "Batuta",
487            IntegrationType::Orchestrates,
488            "ORCHESTRATION",
489        ),
490        IntegrationMapping::new(
491            "Step Functions",
492            "Batuta",
493            IntegrationType::Orchestrates,
494            "ORCHESTRATION",
495        ),
496        IntegrationMapping::new(
497            "Airflow/Prefect",
498            "Batuta",
499            IntegrationType::Orchestrates,
500            "ORCHESTRATION",
501        ),
502    ]
503}
504
505// ============================================================================
506// DATA-TREE-005: Display Formatters
507// ============================================================================
508
509/// Format platform tree for display
510pub fn format_platform_tree(tree: &DataPlatformTree) -> String {
511    let mut output = String::new();
512    output.push_str(&format!("{}\n", tree.platform.name()));
513
514    for (i, category) in tree.categories.iter().enumerate() {
515        let is_last_category = i == tree.categories.len() - 1;
516        let prefix = if is_last_category { "└── " } else { "├── " };
517        let child_prefix = if is_last_category { "    " } else { "│   " };
518
519        output.push_str(&format!("{}{}\n", prefix, category.name));
520
521        for (j, component) in category.components.iter().enumerate() {
522            let is_last_component = j == category.components.len() - 1;
523            let comp_prefix = if is_last_component { "└── " } else { "├── " };
524            let sub_prefix = if is_last_component { "    " } else { "│   " };
525
526            output.push_str(&format!("{}{}{}\n", child_prefix, comp_prefix, component.name));
527
528            for (k, sub) in component.sub_components.iter().enumerate() {
529                let is_last_sub = k == component.sub_components.len() - 1;
530                let sub_comp_prefix = if is_last_sub { "└── " } else { "├── " };
531                output
532                    .push_str(&format!("{}{}{}{}", child_prefix, sub_prefix, sub_comp_prefix, sub));
533                output.push('\n');
534            }
535        }
536    }
537
538    output
539}
540
541/// Format all platforms tree
542pub fn format_all_platforms() -> String {
543    let mut output = String::new();
544    output.push_str("DATA PLATFORMS ECOSYSTEM\n");
545    output.push_str("========================\n\n");
546
547    let trees = vec![
548        build_databricks_tree(),
549        build_snowflake_tree(),
550        build_aws_tree(),
551        build_huggingface_tree(),
552    ];
553
554    let total_components: usize = trees.iter().map(|t| t.total_components()).sum();
555    let total_categories: usize = trees.iter().map(|t| t.categories.len()).sum();
556
557    for tree in &trees {
558        output.push_str(&format_platform_tree(tree));
559        output.push('\n');
560    }
561
562    output.push_str(&format!(
563        "Summary: {} platforms, {} categories, {} components\n",
564        trees.len(),
565        total_categories,
566        total_components
567    ));
568
569    output
570}
571
572/// Format integration mappings
573pub fn format_integration_mappings() -> String {
574    let mut output = String::new();
575    output.push_str("PAIML ↔ DATA PLATFORMS INTEGRATION\n");
576    output.push_str("==================================\n\n");
577
578    let mappings = build_integration_mappings();
579
580    // Group by category
581    let mut current_category = String::new();
582    for mapping in &mappings {
583        if mapping.category != current_category {
584            if !current_category.is_empty() {
585                output.push('\n');
586            }
587            output.push_str(&format!("{}\n", mapping.category));
588            current_category = mapping.category.clone();
589        }
590
591        output.push_str(&format!(
592            "├── {} {} ←→ {}\n",
593            mapping.integration_type, mapping.paiml_component, mapping.platform_component
594        ));
595    }
596
597    // Count by type
598    let compatible =
599        mappings.iter().filter(|m| m.integration_type == IntegrationType::Compatible).count();
600    let alternative =
601        mappings.iter().filter(|m| m.integration_type == IntegrationType::Alternative).count();
602    let uses = mappings.iter().filter(|m| m.integration_type == IntegrationType::Uses).count();
603    let transpiles =
604        mappings.iter().filter(|m| m.integration_type == IntegrationType::Transpiles).count();
605    let orchestrates =
606        mappings.iter().filter(|m| m.integration_type == IntegrationType::Orchestrates).count();
607
608    output.push_str("\nLegend: [CMP]=Compatible [ALT]=Alternative [USE]=Uses [TRN]=Transpiles [ORC]=Orchestrates\n\n");
609    output.push_str(&format!(
610        "Summary: {} compatible, {} alternatives, {} uses, {} transpiles, {} orchestrates\n",
611        compatible, alternative, uses, transpiles, orchestrates
612    ));
613    output.push_str(&format!("         Total: {} integration points\n", mappings.len()));
614
615    output
616}
617
618// ============================================================================
619// Tests
620// ============================================================================
621
622#[cfg(test)]
623#[allow(non_snake_case)]
624mod tests {
625    use super::*;
626
627    // ========================================================================
628    // DATA-TREE-001: Platform Tests
629    // ========================================================================
630
631    #[test]
632    fn test_DATA_TREE_001_platform_names() {
633        assert_eq!(Platform::Databricks.name(), "DATABRICKS");
634        assert_eq!(Platform::Snowflake.name(), "SNOWFLAKE");
635        assert_eq!(Platform::Aws.name(), "AWS");
636        assert_eq!(Platform::HuggingFace.name(), "HUGGINGFACE");
637    }
638
639    #[test]
640    fn test_DATA_TREE_001_platform_all() {
641        let all = Platform::all();
642        assert_eq!(all.len(), 4);
643    }
644
645    #[test]
646    fn test_DATA_TREE_001_platform_display() {
647        assert_eq!(format!("{}", Platform::Databricks), "DATABRICKS");
648    }
649
650    // ========================================================================
651    // DATA-TREE-002: Integration Type Tests
652    // ========================================================================
653
654    #[test]
655    fn test_DATA_TREE_002_integration_codes() {
656        assert_eq!(IntegrationType::Compatible.code(), "CMP");
657        assert_eq!(IntegrationType::Alternative.code(), "ALT");
658        assert_eq!(IntegrationType::Orchestrates.code(), "ORC");
659        assert_eq!(IntegrationType::Uses.code(), "USE");
660        assert_eq!(IntegrationType::Transpiles.code(), "TRN");
661    }
662
663    #[test]
664    fn test_DATA_TREE_002_integration_display() {
665        assert_eq!(format!("{}", IntegrationType::Compatible), "[CMP]");
666    }
667
668    // ========================================================================
669    // DATA-TREE-003: Tree Builder Tests
670    // ========================================================================
671
672    #[test]
673    fn test_DATA_TREE_003_databricks_tree() {
674        let tree = build_databricks_tree();
675        assert_eq!(tree.platform, Platform::Databricks);
676        assert!(!tree.categories.is_empty());
677        assert!(tree.total_components() > 0);
678    }
679
680    #[test]
681    fn test_DATA_TREE_003_snowflake_tree() {
682        let tree = build_snowflake_tree();
683        assert_eq!(tree.platform, Platform::Snowflake);
684        assert!(!tree.categories.is_empty());
685    }
686
687    #[test]
688    fn test_DATA_TREE_003_aws_tree() {
689        let tree = build_aws_tree();
690        assert_eq!(tree.platform, Platform::Aws);
691        assert!(tree.categories.len() >= 4); // Storage, Compute, ML, Analytics
692    }
693
694    #[test]
695    fn test_DATA_TREE_003_huggingface_tree() {
696        let tree = build_huggingface_tree();
697        assert_eq!(tree.platform, Platform::HuggingFace);
698        assert!(!tree.categories.is_empty());
699    }
700
701    // ========================================================================
702    // DATA-TREE-004: Integration Mapping Tests
703    // ========================================================================
704
705    #[test]
706    fn test_DATA_TREE_004_mappings_exist() {
707        let mappings = build_integration_mappings();
708        assert!(!mappings.is_empty());
709        assert!(mappings.len() >= 25); // At least 25 integration points
710    }
711
712    #[test]
713    fn test_DATA_TREE_004_mapping_categories() {
714        let mappings = build_integration_mappings();
715        let categories: std::collections::HashSet<_> =
716            mappings.iter().map(|m| &m.category).collect();
717        assert!(categories.contains(&"STORAGE & CATALOGS".to_string()));
718        assert!(categories.contains(&"ML TRAINING".to_string()));
719        assert!(categories.contains(&"MODEL SERVING".to_string()));
720    }
721
722    #[test]
723    fn test_DATA_TREE_004_has_all_types() {
724        let mappings = build_integration_mappings();
725        let types: std::collections::HashSet<_> =
726            mappings.iter().map(|m| m.integration_type).collect();
727        assert!(types.contains(&IntegrationType::Compatible));
728        assert!(types.contains(&IntegrationType::Alternative));
729        assert!(types.contains(&IntegrationType::Uses));
730        assert!(types.contains(&IntegrationType::Transpiles));
731        assert!(types.contains(&IntegrationType::Orchestrates));
732    }
733
734    // ========================================================================
735    // DATA-TREE-005: Formatter Tests
736    // ========================================================================
737
738    #[test]
739    fn test_DATA_TREE_005_format_platform_tree() {
740        let tree = build_databricks_tree();
741        let output = format_platform_tree(&tree);
742        assert!(output.contains("DATABRICKS"));
743        assert!(output.contains("Delta Lake"));
744        assert!(output.contains("MLflow"));
745    }
746
747    #[test]
748    fn test_DATA_TREE_005_format_all_platforms() {
749        let output = format_all_platforms();
750        assert!(output.contains("DATA PLATFORMS ECOSYSTEM"));
751        assert!(output.contains("DATABRICKS"));
752        assert!(output.contains("SNOWFLAKE"));
753        assert!(output.contains("AWS"));
754        assert!(output.contains("HUGGINGFACE"));
755        assert!(output.contains("Summary:"));
756    }
757
758    #[test]
759    fn test_DATA_TREE_005_format_integration_mappings() {
760        let output = format_integration_mappings();
761        assert!(output.contains("PAIML"));
762        assert!(output.contains("STORAGE & CATALOGS"));
763        assert!(output.contains("Alimentar"));
764        assert!(output.contains("Legend:"));
765        assert!(output.contains("Total:"));
766    }
767
768    // ========================================================================
769    // DATA-TREE-006: Component Tests
770    // ========================================================================
771
772    #[test]
773    fn test_DATA_TREE_006_platform_category() {
774        let category = PlatformCategory::new("Test Category")
775            .with_component(PlatformComponent::new("Component1", "Description 1"));
776        assert_eq!(category.name, "Test Category");
777        assert_eq!(category.components.len(), 1);
778    }
779
780    #[test]
781    fn test_DATA_TREE_006_platform_component() {
782        let component =
783            PlatformComponent::new("Test", "Description").with_sub("Sub1").with_sub("Sub2");
784        assert_eq!(component.name, "Test");
785        assert_eq!(component.sub_components.len(), 2);
786    }
787
788    #[test]
789    fn test_DATA_TREE_006_integration_mapping() {
790        let mapping =
791            IntegrationMapping::new("Source", "Target", IntegrationType::Compatible, "Category");
792        assert_eq!(mapping.platform_component, "Source");
793        assert_eq!(mapping.paiml_component, "Target");
794    }
795
796    // ========================================================================
797    // Additional Coverage Tests
798    // ========================================================================
799
800    #[test]
801    fn test_integration_type_descriptions() {
802        assert!(!IntegrationType::Compatible.description().is_empty());
803        assert!(!IntegrationType::Alternative.description().is_empty());
804        assert!(!IntegrationType::Orchestrates.description().is_empty());
805        assert!(!IntegrationType::Uses.description().is_empty());
806        assert!(!IntegrationType::Transpiles.description().is_empty());
807    }
808
809    #[test]
810    fn test_platform_paiml() {
811        assert_eq!(Platform::Paiml.name(), "PAIML");
812        assert_eq!(format!("{}", Platform::Paiml), "PAIML");
813    }
814
815    #[test]
816    fn test_data_platform_tree_empty() {
817        let tree = DataPlatformTree::new(Platform::Paiml);
818        assert_eq!(tree.platform, Platform::Paiml);
819        assert!(tree.categories.is_empty());
820        assert_eq!(tree.total_components(), 0);
821    }
822
823    #[test]
824    fn test_data_platform_tree_multiple_categories() {
825        let tree = DataPlatformTree::new(Platform::Aws)
826            .add_category(
827                PlatformCategory::new("Cat1")
828                    .with_component(PlatformComponent::new("C1", "D1"))
829                    .with_component(PlatformComponent::new("C2", "D2")),
830            )
831            .add_category(
832                PlatformCategory::new("Cat2").with_component(PlatformComponent::new("C3", "D3")),
833            );
834        assert_eq!(tree.categories.len(), 2);
835        assert_eq!(tree.total_components(), 3);
836    }
837
838    #[test]
839    fn test_platform_equality() {
840        assert_eq!(Platform::Databricks, Platform::Databricks);
841        assert_ne!(Platform::Databricks, Platform::Snowflake);
842    }
843
844    #[test]
845    fn test_integration_type_equality() {
846        assert_eq!(IntegrationType::Compatible, IntegrationType::Compatible);
847        assert_ne!(IntegrationType::Compatible, IntegrationType::Alternative);
848    }
849
850    #[test]
851    fn test_platform_category_empty() {
852        let cat = PlatformCategory::new("Empty");
853        assert!(cat.components.is_empty());
854    }
855
856    #[test]
857    fn test_platform_component_no_subs() {
858        let comp = PlatformComponent::new("NoSubs", "Description");
859        assert!(comp.sub_components.is_empty());
860    }
861
862    #[test]
863    fn test_format_platform_tree_with_subs() {
864        let tree = DataPlatformTree::new(Platform::Paiml).add_category(
865            PlatformCategory::new("Category").with_component(
866                PlatformComponent::new("Component", "Desc").with_sub("Sub1").with_sub("Sub2"),
867            ),
868        );
869        let output = format_platform_tree(&tree);
870        assert!(output.contains("PAIML"));
871        assert!(output.contains("Sub1"));
872        assert!(output.contains("Sub2"));
873    }
874
875    #[test]
876    fn test_integration_mapping_fields() {
877        let mapping =
878            IntegrationMapping::new("Platform", "PAIML", IntegrationType::Orchestrates, "Category");
879        assert_eq!(mapping.integration_type, IntegrationType::Orchestrates);
880        assert_eq!(mapping.category, "Category");
881    }
882
883    #[test]
884    fn test_all_platforms_count() {
885        let platforms = Platform::all();
886        // all() returns 4 platforms (not including PAIML which is internal)
887        assert_eq!(platforms.len(), 4);
888        assert!(!platforms.contains(&Platform::Paiml));
889    }
890
891    #[test]
892    fn test_tree_with_multiple_components_per_category() {
893        let tree = DataPlatformTree::new(Platform::Aws).add_category(
894            PlatformCategory::new("MultiComp")
895                .with_component(PlatformComponent::new("A", "DA"))
896                .with_component(PlatformComponent::new("B", "DB"))
897                .with_component(PlatformComponent::new("C", "DC")),
898        );
899        assert_eq!(tree.total_components(), 3);
900    }
901}