ecitygml_io/validate/
extracted_information.rs1use 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}