1use catalogue::Catalogue;
2use parse::{
3 Map,
4 UpperName,
5};
6use parse::xml::*;
7use roxmltree::{
8 Node,
9};
10
11mod choice;
12mod classification;
13mod ddl;
14mod dotted;
15mod suggest;
16mod table;
17
18pub use choice::{
19 Choice,
20 ChoiceItem,
21};
22pub use classification::{
23 Classification,
24 ClassificationFolder,
25};
26pub (crate) use dotted::{
27 DottedField,
28 DottedRefer,
29 DottedReverse,
30};
31pub (crate) use suggest::{
32 Suggest,
33};
34pub use table::{
35 BooleanDisplayAs,
36 BooleanField,
37 Field,
38 Index,
39 IndexKind,
40 IdentifierField,
41 NumberField,
42 NumberRange,
43 ReferField,
44 ReferKind,
45 StringField,
46 StringKind,
47 Table,
48};
49pub (crate) use table::{
50 AddressField,
51 ChoiceField,
52 ClassificationField,
53 ClassificationRestrict,
54 FieldKind,
55 ReferRestrict,
56 ReferRestrictTo,
57 Summary,
58};
59
60use crate::{
61 ChoiceId,
62 ClassificationId,
63 Error,
64 TableId,
65};
66
67use crate::pass0::Framework0;
68
69pub struct Framework {
70 pub (crate) choices: Map<UpperName, Choice, ChoiceId>,
71 pub (crate) classifications: Map<UpperName, Classification, ClassificationId>,
72 pub (crate) tables: Map<UpperName, Table, TableId>,
73 pub version: usize,
74}
75
76impl Framework {
77 pub (crate) fn parse(
78 element: Node,
79 catalogue: Catalogue,
80 errors: &mut Vec<Error>,
81 ) -> Option<Self> {
82 let Some(framework0) = Framework0::parse(element, catalogue, errors) else {
83 return None;
84 };
85
86 let Some(choices) = framework0.choices.map(Choice::map, errors) else {
87 return None;
88 };
89 let Some(classifications) = framework0.classifications.map_cx(Classification::map, &framework0, errors) else {
90 return None;
91 };
92 let Some(tables) = framework0.tables.map_cx(Table::map, &framework0, errors) else {
93 return None;
94 };
95
96 let version = framework0.version;
97 let framework = Framework {
98 choices,
99 classifications,
100 tables,
101 version: version.number,
102 };
103
104 match framework.ddl_hash() {
105 Ok(hash) =>
106 if hash != version.hash {
107 errors.push(Error::HashChanged {
108 calculated: hash,
109 existing: version.hash_range.into(),
110 });
111
112 return None;
113 }
114
115 Err(message) => {
116 errors.push(Error::HashError {
117 message,
118 });
119
120 return None;
121 }
122 }
123
124 Some(framework)
125 }
126
127 pub (crate) fn choice_by_id(&self, id: &ChoiceId) -> &Choice {
128 self.choices.vec.get(id.index())
129 .expect("Exist by construction")
130 }
131
132 pub (crate) fn classification_by_id(&self, id: &ClassificationId) -> &Classification {
133 self.classifications.vec.get(id.index())
134 .expect("Exist by construction")
135 }
136
137 pub (crate) fn table_by_id(&self, id: &TableId) -> &Table {
138 self.tables.vec.get(id.index())
139 .expect("Exist by construction")
140 }
141}