xsd_schema/schema/
group.rs1use crate::ids::{AttributeGroupKey, ModelGroupKey, NameId};
6use crate::parser::location::SourceRef;
7use crate::types::complex::{AttributeUse, AttributeWildcard, Compositor, ContentParticle};
8
9#[derive(Debug, Clone)]
13pub struct ModelGroupDef {
14 pub name: Option<NameId>,
16
17 pub target_namespace: Option<NameId>,
19
20 pub source: Option<SourceRef>,
22
23 pub compositor: Compositor,
25
26 pub particles: Vec<ContentParticle>,
28
29 pub id: Option<String>,
31}
32
33impl ModelGroupDef {
34 pub fn new(name: NameId, compositor: Compositor) -> Self {
36 Self {
37 name: Some(name),
38 target_namespace: None,
39 source: None,
40 compositor,
41 particles: Vec::new(),
42 id: None,
43 }
44 }
45
46 pub fn anonymous(compositor: Compositor) -> Self {
48 Self {
49 name: None,
50 target_namespace: None,
51 source: None,
52 compositor,
53 particles: Vec::new(),
54 id: None,
55 }
56 }
57
58 pub fn is_named(&self) -> bool {
60 self.name.is_some()
61 }
62
63 pub fn is_empty(&self) -> bool {
65 self.particles.is_empty()
66 }
67
68 pub fn add_particle(&mut self, particle: ContentParticle) {
70 self.particles.push(particle);
71 }
72}
73
74#[derive(Debug, Clone)]
76pub enum ModelGroupRef {
77 Resolved(ModelGroupKey),
79 Unresolved {
81 namespace: Option<NameId>,
82 local_name: NameId,
83 },
84}
85
86#[derive(Debug, Clone)]
90pub struct AttributeGroupDef {
91 pub name: Option<NameId>,
93
94 pub target_namespace: Option<NameId>,
96
97 pub source: Option<SourceRef>,
99
100 pub attributes: Vec<AttributeUse>,
102
103 pub attribute_group_refs: Vec<AttributeGroupRef>,
105
106 pub attribute_wildcard: Option<AttributeWildcard>,
108
109 pub id: Option<String>,
111}
112
113impl AttributeGroupDef {
114 pub fn new(name: NameId) -> Self {
116 Self {
117 name: Some(name),
118 target_namespace: None,
119 source: None,
120 attributes: Vec::new(),
121 attribute_group_refs: Vec::new(),
122 attribute_wildcard: None,
123 id: None,
124 }
125 }
126
127 pub fn anonymous() -> Self {
129 Self {
130 name: None,
131 target_namespace: None,
132 source: None,
133 attributes: Vec::new(),
134 attribute_group_refs: Vec::new(),
135 attribute_wildcard: None,
136 id: None,
137 }
138 }
139
140 pub fn is_named(&self) -> bool {
142 self.name.is_some()
143 }
144
145 pub fn is_empty(&self) -> bool {
147 self.attributes.is_empty()
148 && self.attribute_group_refs.is_empty()
149 && self.attribute_wildcard.is_none()
150 }
151
152 pub fn add_attribute(&mut self, attr_use: AttributeUse) {
154 self.attributes.push(attr_use);
155 }
156
157 pub fn add_attribute_group_ref(&mut self, ref_: AttributeGroupRef) {
159 self.attribute_group_refs.push(ref_);
160 }
161}
162
163#[derive(Debug, Clone)]
165pub enum AttributeGroupRef {
166 Resolved(AttributeGroupKey),
168 Unresolved {
170 namespace: Option<NameId>,
171 local_name: NameId,
172 },
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
177pub struct Occurrence {
178 pub min: u32,
180 pub max: Option<u32>,
182}
183
184impl Occurrence {
185 pub const ONCE: Occurrence = Occurrence {
187 min: 1,
188 max: Some(1),
189 };
190
191 pub const OPTIONAL: Occurrence = Occurrence {
193 min: 0,
194 max: Some(1),
195 };
196
197 pub const UNBOUNDED: Occurrence = Occurrence { min: 0, max: None };
199
200 pub const ONE_OR_MORE: Occurrence = Occurrence { min: 1, max: None };
202
203 pub fn new(min: u32, max: Option<u32>) -> Self {
205 Self { min, max }
206 }
207
208 pub fn is_optional(&self) -> bool {
210 self.min == 0
211 }
212
213 pub fn is_unbounded(&self) -> bool {
215 self.max.is_none()
216 }
217
218 pub fn allows_multiple(&self) -> bool {
220 self.max.is_none_or(|m| m > 1)
221 }
222
223 pub fn is_once(&self) -> bool {
225 self.min == 1 && self.max == Some(1)
226 }
227}
228
229impl Default for Occurrence {
230 fn default() -> Self {
231 Self::ONCE
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238
239 #[test]
240 fn test_model_group_def() {
241 let group = ModelGroupDef::new(NameId(1), Compositor::Sequence);
242 assert!(group.is_named());
243 assert!(group.is_empty());
244 assert_eq!(group.compositor, Compositor::Sequence);
245 }
246
247 #[test]
248 fn test_anonymous_model_group() {
249 let group = ModelGroupDef::anonymous(Compositor::Choice);
250 assert!(!group.is_named());
251 assert_eq!(group.compositor, Compositor::Choice);
252 }
253
254 #[test]
255 fn test_attribute_group_def() {
256 let group = AttributeGroupDef::new(NameId(1));
257 assert!(group.is_named());
258 assert!(group.is_empty());
259 }
260
261 #[test]
262 fn test_anonymous_attribute_group() {
263 let group = AttributeGroupDef::anonymous();
264 assert!(!group.is_named());
265 assert!(group.is_empty());
266 }
267
268 #[test]
269 fn test_occurrence_constants() {
270 assert!(Occurrence::ONCE.is_once());
271 assert!(!Occurrence::ONCE.is_optional());
272 assert!(!Occurrence::ONCE.is_unbounded());
273
274 assert!(Occurrence::OPTIONAL.is_optional());
275 assert!(!Occurrence::OPTIONAL.allows_multiple());
276
277 assert!(Occurrence::UNBOUNDED.is_unbounded());
278 assert!(Occurrence::UNBOUNDED.allows_multiple());
279
280 assert!(!Occurrence::ONE_OR_MORE.is_optional());
281 assert!(Occurrence::ONE_OR_MORE.is_unbounded());
282 }
283
284 #[test]
285 fn test_occurrence_custom() {
286 let occ = Occurrence::new(2, Some(5));
287 assert!(!occ.is_optional());
288 assert!(!occ.is_unbounded());
289 assert!(occ.allows_multiple());
290 }
291}