ecitygml_io/validate/
extracted_information.rs

1use crate::validate::report::{Report, ReportElement, ReportStatistics};
2
3use serde::{Deserialize, Serialize};
4use std::collections::{HashMap, HashSet};
5
6#[derive(Debug, Clone, Default)]
7pub struct ExtractedInformation {
8    pub gml_id_count_per_element_type: HashMap<String, GmlIdCount>,
9
10    pub gml_id_count: HashMap<String, usize>,
11    pub city_object_relations: HashSet<CityObjectRelation>,
12    pub predecessor_hrefs: HashMap<String, usize>,
13    pub successor_hrefs: HashMap<String, usize>,
14}
15
16#[derive(Debug, Clone, Default, Eq, PartialEq)]
17pub struct GmlIdCount {
18    pub with_gml_id_count: usize,
19    pub without_gml_id_count: usize,
20}
21
22impl GmlIdCount {
23    pub fn increment(&mut self, gml_id_existent: bool) {
24        if gml_id_existent {
25            self.with_gml_id_count += 1;
26        } else {
27            self.without_gml_id_count += 1;
28        }
29    }
30}
31
32impl ExtractedInformation {
33    pub fn get_gml_id_duplicates(&self) -> Vec<(&String, &usize)> {
34        let filtered: Vec<_> = self
35            .gml_id_count
36            .iter()
37            .filter(|&i| *i.1 > 1usize)
38            .collect();
39        filtered
40    }
41
42    pub fn contains_gml_id_duplicates(&self) -> bool {
43        self.gml_id_count.values().any(|x| *x > 1usize)
44    }
45
46    pub fn find_broken_object_relations(&self) -> Vec<&CityObjectRelation> {
47        let broken_object_relations: Vec<&CityObjectRelation> = self
48            .city_object_relations
49            .iter()
50            .filter(|x| {
51                !self
52                    .gml_id_count
53                    .contains_key(&x.related_to.xlink_href.as_str()[1..])
54            })
55            .collect();
56        broken_object_relations
57    }
58
59    pub fn find_broken_predecessor_hrefs(&self) -> Vec<String> {
60        let broken_hrefs: Vec<String> = self
61            .predecessor_hrefs
62            .iter()
63            .filter(|x| !self.gml_id_count.contains_key(&x.0.as_str()[1..]))
64            .map(|x| x.0.clone())
65            .collect();
66        broken_hrefs
67    }
68
69    pub fn find_broken_successor_hrefs(&self) -> Vec<String> {
70        let broken_hrefs: Vec<String> = self
71            .successor_hrefs
72            .iter()
73            .filter(|x| !self.gml_id_count.contains_key(&x.0.as_str()[1..]))
74            .map(|x| x.0.clone())
75            .collect();
76        broken_hrefs
77    }
78
79    pub fn compile_report(&self) -> Report {
80        let gml_id_duplicates: Vec<(String, usize)> = self
81            .get_gml_id_duplicates()
82            .iter()
83            .map(|x| (x.0.clone(), *x.1))
84            .collect();
85
86        let broken_object_relations: Vec<String> = self
87            .find_broken_object_relations()
88            .iter()
89            .map(|x| x.related_to.xlink_href.clone())
90            .collect();
91
92        let mut xml_elements: Vec<ReportElement> = self
93            .gml_id_count_per_element_type
94            .iter()
95            .map(|x| ReportElement {
96                element_name: x.0.clone(),
97                number_total: x.1.with_gml_id_count + x.1.without_gml_id_count,
98                number_with_gml_id: x.1.with_gml_id_count,
99                number_without_gml_id: x.1.without_gml_id_count,
100            })
101            .collect();
102        xml_elements.sort_by_key(|x| x.element_name.clone().to_lowercase());
103
104        let statistics = ReportStatistics {
105            number_of_gml_duplicates: gml_id_duplicates.len(),
106            number_of_broken_object_relations: broken_object_relations.len(),
107        };
108
109        Report {
110            statistics,
111            xml_elements,
112            gml_id_duplicates,
113            broken_object_relations,
114            broken_predecessor_hrefs: self.find_broken_predecessor_hrefs(),
115            broken_successor_hrefs: self.find_broken_successor_hrefs(),
116        }
117    }
118}
119
120#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
121pub struct CityObjectRelation {
122    #[serde(rename = "relationType")]
123    pub related_type: RelatedType,
124    #[serde(rename = "relatedTo")]
125    pub related_to: RelatedTo,
126}
127
128#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
129#[serde(rename = "relationType")]
130pub struct RelatedType {
131    #[serde(rename = "$value", default)]
132    pub(crate) value: String,
133}
134
135#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
136#[serde(rename = "relatedTo")]
137pub struct RelatedTo {
138    #[serde(rename = "@href", default)]
139    pub xlink_href: String,
140}