• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 9778142714

03 Jul 2024 12:47PM UTC coverage: 90.741% (+0.05%) from 90.687%
9778142714

Pull #970

github

web-flow
Merge 371bbde3c into 9a33a5b13
Pull Request #970: FAIR dataset deletion

1369 of 1424 new or added lines in 9 files covered. (96.14%)

22 existing lines in 12 files now uncovered.

134486 of 148208 relevant lines covered (90.74%)

52199.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.35
/services/src/datasets/external/netcdfcf/ebvportal_api.rs
1
//! GEO BON EBV Portal catalog lookup service
2
//!
3
//! Connects to <https://portal.geobon.org/api/v1/>.
4

5
use crate::datasets::external::netcdfcf::{error, NetCdfOverview};
6
use crate::error::Result;
7
use error::NetCdfCf4DProviderError;
8
use geoengine_datatypes::dataset::DataProviderId;
9
use log::debug;
10
use serde::Serialize;
11
use url::Url;
12

13
mod portal_responses {
14
    use serde::Deserialize;
15

16
    #[derive(Debug, Deserialize)]
10✔
17
    pub struct EbvClassesResponse {
18
        pub data: Vec<EbvClassesResponseClass>,
19
    }
20

21
    #[derive(Debug, Deserialize)]
40✔
22
    pub struct EbvClassesResponseClass {
23
        pub ebv_class: String,
24
        pub ebv_name: Vec<String>,
25
    }
26

27
    #[derive(Debug, Deserialize)]
20✔
28
    pub struct EbvDatasetsResponse {
29
        pub data: Vec<EbvDatasetsResponseData>,
30
    }
31

32
    #[derive(Debug, Deserialize)]
164✔
33
    pub struct EbvDatasetsResponseData {
34
        pub id: String,
35
        pub title: String,
36
        pub summary: String,
37
        pub creator: EbvDatasetsResponseCreator,
38
        pub license: String,
39
        pub dataset: EbvDatasetsResponseDataset,
40
        pub ebv: EbvDatasetsResponseEbv,
41
        pub ebv_scenario: EbvDatasetsResponseEbvScenario,
42
    }
43

44
    #[derive(Debug, Deserialize)]
28✔
45
    pub struct EbvDatasetsResponseCreator {
46
        pub creator_name: String,
47
        pub creator_institution: String,
48
    }
49

50
    #[derive(Debug, Deserialize)]
24✔
51
    pub struct EbvDatasetsResponseDataset {
52
        pub pathname: String,
53
    }
54

55
    #[derive(Debug, Deserialize)]
20✔
56
    pub struct EbvDatasetsResponseEbv {
57
        pub ebv_class: String,
58
        pub ebv_name: String,
59
    }
60

61
    #[derive(Debug, Deserialize)]
7✔
62
    #[serde(untagged)]
63
    pub enum EbvDatasetsResponseEbvScenario {
64
        String(String),
65
        Value(EbvDatasetsResponseEbvScenarioValue),
66
    }
67

68
    #[derive(Debug, Deserialize)]
4✔
69
    pub struct EbvDatasetsResponseEbvScenarioValue {
70
        pub ebv_scenario_classification_name: String,
71
    }
72
}
73

74
#[derive(Debug, Serialize)]
×
75
#[serde(rename_all = "camelCase")]
76
pub struct EbvClass {
77
    pub name: String,
78
    pub ebv_names: Vec<String>,
79
}
80

81
#[derive(Debug, Serialize)]
×
82
#[serde(rename_all = "camelCase")]
83
struct EbvClasses {
84
    classes: Vec<EbvClass>,
85
}
86

87
#[derive(Debug)]
×
88
pub struct EbvPortalApi {
89
    base_url: Url,
90
}
91

92
impl EbvPortalApi {
93
    pub fn new(base_url: Url) -> Self {
6✔
94
        Self { base_url }
6✔
95
    }
6✔
96

97
    pub async fn get_classes(&self) -> Result<Vec<EbvClass>> {
2✔
98
        let url = format!("{}/ebv-map", self.base_url);
2✔
99

100
        debug!("Calling {url}");
×
101

102
        let response = reqwest::get(url)
2✔
103
            .await?
3✔
104
            .json::<portal_responses::EbvClassesResponse>()
2✔
105
            .await?;
×
106

107
        Ok(response
2✔
108
            .data
2✔
109
            .into_iter()
2✔
110
            .map(|c| EbvClass {
8✔
111
                name: c.ebv_class,
8✔
112
                ebv_names: c.ebv_name,
8✔
113
            })
8✔
114
            .collect())
2✔
115
    }
2✔
116

117
    pub async fn get_ebv_datasets(&self, ebv_name: &str) -> Result<Vec<EbvDataset>> {
2✔
118
        let url = format!("{}/datasets/filter", self.base_url);
2✔
119

120
        debug!("Calling {url}");
×
121

122
        let response = reqwest::Client::new()
2✔
123
            .get(url)
2✔
124
            .query(&[("ebvName", ebv_name)])
2✔
125
            .send()
2✔
UNCOV
126
            .await?
×
127
            .json::<portal_responses::EbvDatasetsResponse>()
2✔
128
            .await?;
×
129

130
        Ok(response
2✔
131
            .data
2✔
132
            .into_iter()
2✔
133
            .map(|data| EbvDataset {
2✔
134
                id: data.id,
2✔
135
                name: data.title,
2✔
136
                author_name: data.creator.creator_name,
2✔
137
                author_institution: data.creator.creator_institution,
2✔
138
                description: data.summary,
2✔
139
                license: data.license,
2✔
140
                dataset_path: data.dataset.pathname,
2✔
141
                ebv_class: data.ebv.ebv_class,
2✔
142
                ebv_name: data.ebv.ebv_name,
2✔
143
                has_scenario: matches!(
2✔
144
                    data.ebv_scenario,
2✔
145
                    portal_responses::EbvDatasetsResponseEbvScenario::Value(_)
146
                ),
147
            })
2✔
148
            .collect())
2✔
149
    }
2✔
150

151
    pub async fn get_dataset_metadata(&self, id: &str) -> Result<EbvDataset> {
2✔
152
        let url = format!("{}/datasets/{id}", self.base_url);
2✔
153

154
        debug!("Calling {url}");
×
155

156
        let response = reqwest::get(url)
2✔
157
            .await?
4✔
158
            .json::<portal_responses::EbvDatasetsResponse>()
2✔
159
            .await?;
1✔
160

161
        let dataset: Option<EbvDataset> = response
2✔
162
            .data
2✔
163
            .into_iter()
2✔
164
            .map(|data| EbvDataset {
2✔
165
                id: data.id,
2✔
166
                name: data.title,
2✔
167
                author_name: data.creator.creator_name,
2✔
168
                author_institution: data.creator.creator_institution,
2✔
169
                description: data.summary,
2✔
170
                license: data.license,
2✔
171
                dataset_path: data.dataset.pathname,
2✔
172
                ebv_class: data.ebv.ebv_class,
2✔
173
                ebv_name: data.ebv.ebv_name,
2✔
174
                has_scenario: matches!(
2✔
175
                    data.ebv_scenario,
2✔
176
                    portal_responses::EbvDatasetsResponseEbvScenario::Value(_)
177
                ),
178
            })
2✔
179
            .next();
2✔
180

2✔
181
        match dataset {
2✔
182
            Some(dataset) => Ok(dataset),
2✔
183
            None => Err(NetCdfCf4DProviderError::CannotLookupDataset { id: id.to_string() }.into()),
×
184
        }
185
    }
2✔
186
}
187

188
#[derive(Debug, Serialize)]
×
189
#[serde(rename_all = "camelCase")]
190
pub struct EbvDataset {
191
    pub id: String,
192
    pub name: String,
193
    pub author_name: String,
194
    pub author_institution: String,
195
    pub description: String,
196
    pub license: String,
197
    pub dataset_path: String,
198
    pub ebv_class: String,
199
    pub ebv_name: String,
200
    pub has_scenario: bool,
201
}
202

203
#[derive(Debug, Serialize)]
×
204
#[serde(rename_all = "camelCase")]
205
pub struct EbvHierarchy {
206
    pub provider_id: DataProviderId,
207
    pub tree: NetCdfOverview,
208
}
209

210
#[cfg(test)]
211
mod tests {
212
    use super::portal_responses::EbvDatasetsResponseEbvScenario;
213

214
    #[test]
1✔
215
    fn it_parses_ebv_scenario() {
1✔
216
        let value: EbvDatasetsResponseEbvScenario = serde_json::from_str(
1✔
217
            r#"{
1✔
218
                "ebv_scenario_classification_name": "foo",
1✔
219
                "other_field": "bar"
1✔
220
            }"#,
1✔
221
        )
1✔
222
        .unwrap();
1✔
223

224
        matches!(value, EbvDatasetsResponseEbvScenario::Value(_));
1✔
225

226
        let value: EbvDatasetsResponseEbvScenario = serde_json::from_str(r#""N/A""#).unwrap();
1✔
227

228
        matches!(value, EbvDatasetsResponseEbvScenario::String(_));
1✔
229
    }
1✔
230
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc