Skip to main content

qualia_core_db/domains/geospatial/adapters/
wms_adapter.rs

1use crate::domains::geospatial::adapters::AdapterHttpRequest;
2use crate::net::disclosure::NetworkDisclosureRegistry;
3
4pub enum OgcServiceType {
5    Wms,
6    Wfs,
7    Wcs,
8    Wmts,
9}
10
11/// Adapter for OGC Web Services (WMS, WFS, WCS, WMTS).
12pub struct WmsAdapter {
13    pub id: &'static str,
14    pub endpoint: String,
15    pub service_type: OgcServiceType,
16}
17
18impl WmsAdapter {
19    pub fn new(id: &'static str, endpoint: &str, service_type: OgcServiceType) -> Self {
20        Self {
21            id,
22            endpoint: endpoint.to_string(),
23            service_type,
24        }
25    }
26}
27
28impl WmsAdapter {
29    pub fn adapter_id(&self) -> &'static str {
30        self.id
31    }
32
33    pub fn build_fetch_request(
34        &self,
35        bbox: (f64, f64, f64, f64),
36        time_range: (u64, u64),
37        registry: &NetworkDisclosureRegistry,
38    ) -> Result<AdapterHttpRequest, String> {
39        if !registry.check_egress_consent(self.adapter_id(), &self.endpoint) {
40            return Err(format!(
41                "Consent denied or unregistered for endpoint {} by adapter {}",
42                self.endpoint,
43                self.adapter_id()
44            ));
45        }
46
47        let (service, request) = match self.service_type {
48            OgcServiceType::Wms => ("WMS", "GetMap"),
49            OgcServiceType::Wfs => ("WFS", "GetFeature"),
50            OgcServiceType::Wcs => ("WCS", "GetCoverage"),
51            OgcServiceType::Wmts => ("WMTS", "GetTile"),
52        };
53
54        let mut url = format!(
55            "{}?SERVICE={}&REQUEST={}&BBOX={},{},{},{}",
56            self.endpoint, service, request, bbox.0, bbox.1, bbox.2, bbox.3
57        );
58
59        if time_range.1 > 0 {
60            // Stub: proper ISO8601 formatting for TIME parameter
61            url.push_str(&format!("&TIME={}/{}", time_range.0, time_range.1));
62        }
63
64        Ok(AdapterHttpRequest::get(url, "OGC"))
65    }
66
67    pub fn fetch_region(
68        &self,
69        bbox: (f64, f64, f64, f64),
70        time_range: (u64, u64),
71        registry: &NetworkDisclosureRegistry,
72    ) -> Result<(), String> {
73        let request = self.build_fetch_request(bbox, time_range, registry)?;
74        super::execute_http_request_status(&request)?;
75        // Parsing response data is deferred.
76        Ok(())
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_wms_adapter_egress() {
86        let adapter = WmsAdapter::new(
87            "wms_adapter",
88            "https://wms.example.com/geoserver/wms",
89            OgcServiceType::Wms,
90        );
91        let registry = NetworkDisclosureRegistry::new();
92
93        let res1 = adapter.fetch_region((-1.0, 51.0, 0.0, 52.0), (0, 0), &registry);
94        assert!(res1.is_err());
95
96        let mut registry = registry;
97        registry.register_egress(
98            adapter.adapter_id(),
99            "https://wms.example.com/geoserver/wms",
100            "Fetch raster map tiles via WMS GetMap",
101            "User enables base map layer",
102        );
103
104        let res2 = adapter.fetch_region((-1.0, 51.0, 0.0, 52.0), (0, 0), &registry);
105        if let Err(e) = res2 {
106            assert!(
107                !e.contains("Consent denied"),
108                "Failed on consent when it should have been granted: {}",
109                e
110            );
111        }
112    }
113}