ddex_parser/transform/
resolve.rs

1// core/src/transform/resolve.rs
2//! Reference resolution
3
4use std::collections::HashMap;
5use ddex_core::models::graph::{ERNMessage, Party, Resource, Release, Deal};
6
7pub struct ReferenceResolver {
8    party_map: HashMap<String, Party>,
9    resource_map: HashMap<String, Resource>,
10    release_map: HashMap<String, Release>,
11    deal_map: HashMap<String, Deal>,
12}
13
14impl ReferenceResolver {
15    pub fn new() -> Self {
16        Self {
17            party_map: HashMap::new(),
18            resource_map: HashMap::new(),
19            release_map: HashMap::new(),
20            deal_map: HashMap::new(),
21        }
22    }
23    
24    pub fn build_maps(&mut self, message: &ERNMessage) {
25        // Build party map
26        for party in &message.parties {
27            if let Some(id) = party.party_id.first() {
28                self.party_map.insert(id.value.clone(), party.clone());
29            }
30        }
31        
32        // Build resource map
33        for resource in &message.resources {
34            self.resource_map.insert(resource.resource_reference.clone(), resource.clone());
35        }
36        
37        // Build release map
38        for release in &message.releases {
39            self.release_map.insert(release.release_reference.clone(), release.clone());
40        }
41        
42        // Build deal map
43        for (idx, deal) in message.deals.iter().enumerate() {
44            let key = deal.deal_reference.clone()
45                .unwrap_or_else(|| format!("deal_{}", idx));
46            self.deal_map.insert(key, deal.clone());
47        }
48    }
49    
50    pub fn resolve_party_reference(&self, reference: &str) -> Option<&Party> {
51        self.party_map.get(reference)
52    }
53    
54    pub fn resolve_resource_reference(&self, reference: &str) -> Option<&Resource> {
55        self.resource_map.get(reference)
56    }
57    
58    pub fn resolve_release_reference(&self, reference: &str) -> Option<&Release> {
59        self.release_map.get(reference)
60    }
61    
62    pub fn validate_references(&self, message: &ERNMessage) -> Vec<UnresolvedReference> {
63        let mut unresolved = Vec::new();
64        
65        // Check release resource references
66        for release in &message.releases {
67            for rref in &release.release_resource_reference_list {
68                if !self.resource_map.contains_key(&rref.resource_reference) {
69                    unresolved.push(UnresolvedReference {
70                        reference_type: "Resource".to_string(),
71                        reference_value: rref.resource_reference.clone(),
72                        location: format!("Release/{}/ResourceReference", release.release_reference),
73                    });
74                }
75            }
76        }
77        
78        // Check deal release references
79        for (idx, deal) in message.deals.iter().enumerate() {
80            for release_ref in &deal.deal_release_reference {
81                if !self.release_map.contains_key(release_ref as &str) {
82                    unresolved.push(UnresolvedReference {
83                        reference_type: "Release".to_string(),
84                        reference_value: release_ref.clone(),
85                        location: format!("Deal[{}]/ReleaseReference", idx),
86                    });
87                }
88            }
89        }
90        
91        unresolved
92    }
93}
94
95#[derive(Debug, Clone)]
96pub struct UnresolvedReference {
97    pub reference_type: String,
98    pub reference_value: String,
99    pub location: String,
100}