Skip to main content

xsd_schema/parser/frames/
directives.rs

1// ============================================================================
2// Include/Import/Redefine Frames
3// ============================================================================
4
5/// Frame for xs:include
6pub struct IncludeFrame {
7    schema_location: Option<String>,
8    id: Option<String>,
9    annotation: Option<Annotation>,
10    source: Option<SourceRef>,
11    foreign_attributes: Vec<ForeignAttribute>,
12}
13
14impl IncludeFrame {
15    pub fn new(
16        attrs: &AttributeMap,
17        name_table: &NameTable,
18        source: Option<SourceRef>,
19    ) -> SchemaResult<Self> {
20        let schema_location = attrs
21            .get_value_by_name(name_table, "schemaLocation")
22            .map(String::from);
23
24        let id = attrs
25            .get_value_by_name(name_table, "id")
26            .map(String::from);
27
28        Ok(Self {
29            schema_location,
30            id,
31            annotation: None,
32            source,
33            foreign_attributes: Vec::new(),
34        })
35    }
36}
37
38impl Frame for IncludeFrame {
39    fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
40        matches!(local_name, xsd_names::ANNOTATION)
41    }
42
43    fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
44        matches!(local_name, "schemaLocation" | "id")
45    }
46
47    fn on_child_start(&mut self, _local_name: &str, _name_table: &NameTable) {}
48
49    fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
50        if let FrameResult::Annotation(ann) = child {
51            self.annotation = Some(ann);
52        }
53        Ok(())
54    }
55
56    fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
57        let schema_location = self.schema_location.ok_or_else(|| SchemaError::structural(
58            "src-include",
59            "xs:include requires 'schemaLocation' attribute",
60            None,
61        ))?;
62
63        let annotation = merge_foreign_attributes(
64            self.annotation,
65            self.foreign_attributes,
66            self.source.clone(),
67        );
68        Ok(FrameResult::Directive(DirectiveResult::Include(IncludeResult {
69            schema_location,
70            id: self.id,
71            annotation,
72            source: self.source,
73        })))
74    }
75
76    fn has_annotation(&self) -> bool {
77        self.annotation.is_some()
78    }
79
80    fn source(&self) -> Option<&SourceRef> {
81        self.source.as_ref()
82    }
83
84    fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
85        self.foreign_attributes = attrs;
86    }
87}
88
89/// Frame for xs:import
90pub struct ImportFrame {
91    namespace: Option<String>,
92    schema_location: Option<String>,
93    id: Option<String>,
94    annotation: Option<Annotation>,
95    source: Option<SourceRef>,
96    foreign_attributes: Vec<ForeignAttribute>,
97}
98
99impl ImportFrame {
100    pub fn new(
101        attrs: &AttributeMap,
102        name_table: &NameTable,
103        source: Option<SourceRef>,
104    ) -> SchemaResult<Self> {
105        let namespace = attrs
106            .get_value_by_name(name_table, "namespace")
107            .map(String::from);
108
109        let schema_location = attrs
110            .get_value_by_name(name_table, "schemaLocation")
111            .map(String::from);
112
113        let id = attrs
114            .get_value_by_name(name_table, "id")
115            .map(String::from);
116
117        Ok(Self {
118            namespace,
119            schema_location,
120            id,
121            annotation: None,
122            source,
123            foreign_attributes: Vec::new(),
124        })
125    }
126}
127
128impl Frame for ImportFrame {
129    fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
130        matches!(local_name, xsd_names::ANNOTATION)
131    }
132
133    fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
134        matches!(local_name, "namespace" | "schemaLocation" | "id")
135    }
136
137    fn on_child_start(&mut self, _local_name: &str, _name_table: &NameTable) {}
138
139    fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
140        if let FrameResult::Annotation(ann) = child {
141            self.annotation = Some(ann);
142        }
143        Ok(())
144    }
145
146    fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
147        let annotation = merge_foreign_attributes(
148            self.annotation,
149            self.foreign_attributes,
150            self.source.clone(),
151        );
152        Ok(FrameResult::Directive(DirectiveResult::Import(ImportResult {
153            namespace: self.namespace,
154            schema_location: self.schema_location,
155            id: self.id,
156            annotation,
157            source: self.source,
158        })))
159    }
160
161    fn has_annotation(&self) -> bool {
162        self.annotation.is_some()
163    }
164
165    fn source(&self) -> Option<&SourceRef> {
166        self.source.as_ref()
167    }
168
169    fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
170        self.foreign_attributes = attrs;
171    }
172}
173
174#[cfg(feature = "xsd11")]
175/// Frame for xs:override (XSD 1.1)
176pub struct OverrideFrame {
177    schema_location: Option<String>,
178    id: Option<String>,
179    annotation: Option<Annotation>,
180    source: Option<SourceRef>,
181    foreign_attributes: Vec<ForeignAttribute>,
182    // Overridden components (schemaTop)
183    simple_types: Vec<SimpleTypeResult>,
184    complex_types: Vec<ComplexTypeResult>,
185    elements: Vec<ElementFrameResult>,
186    attributes: Vec<AttributeFrameResult>,
187    groups: Vec<GroupFrameResult>,
188    attribute_groups: Vec<GroupFrameResult>,
189    notations: Vec<NotationResult>,
190}
191
192#[cfg(feature = "xsd11")]
193impl OverrideFrame {
194    pub fn new(
195        attrs: &AttributeMap,
196        name_table: &NameTable,
197        source: Option<SourceRef>,
198    ) -> SchemaResult<Self> {
199        let schema_location = attrs
200            .get_value_by_name(name_table, "schemaLocation")
201            .map(String::from);
202
203        let id = attrs
204            .get_value_by_name(name_table, "id")
205            .map(String::from);
206
207        Ok(Self {
208            schema_location,
209            id,
210            annotation: None,
211            source,
212            foreign_attributes: Vec::new(),
213            simple_types: Vec::new(),
214            complex_types: Vec::new(),
215            elements: Vec::new(),
216            attributes: Vec::new(),
217            groups: Vec::new(),
218            attribute_groups: Vec::new(),
219            notations: Vec::new(),
220        })
221    }
222}
223
224#[cfg(feature = "xsd11")]
225impl Frame for OverrideFrame {
226    fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
227        // Override can contain annotation and schemaTop elements
228        matches!(
229            local_name,
230            xsd_names::ANNOTATION
231                | xsd_names::SIMPLE_TYPE
232                | xsd_names::COMPLEX_TYPE
233                | xsd_names::ELEMENT
234                | xsd_names::ATTRIBUTE
235                | xsd_names::GROUP
236                | xsd_names::ATTRIBUTE_GROUP
237                | xsd_names::NOTATION
238        )
239    }
240
241    fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
242        matches!(local_name, "schemaLocation" | "id")
243    }
244
245    fn on_child_start(&mut self, _local_name: &str, _name_table: &NameTable) {}
246
247    fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
248        match child {
249            FrameResult::Annotation(ann) => {
250                self.annotation = Some(ann);
251            }
252            FrameResult::Type(TypeFrameResult::Simple(st)) => {
253                self.simple_types.push(*st);
254            }
255            FrameResult::Type(TypeFrameResult::Complex(ct)) => {
256                self.complex_types.push(*ct);
257            }
258            FrameResult::Element(el) => {
259                self.elements.push(el);
260            }
261            FrameResult::Attribute(attr) => {
262                self.attributes.push(attr);
263            }
264            FrameResult::Group(group) => {
265                match group {
266                    GroupFrameResult::Model(_) => self.groups.push(group),
267                    GroupFrameResult::Attribute(_) => self.attribute_groups.push(group),
268                }
269            }
270            FrameResult::Notation(notation) => {
271                self.notations.push(notation);
272            }
273            _ => {}
274        }
275        Ok(())
276    }
277
278    fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
279        let schema_location = self.schema_location.ok_or_else(|| SchemaError::structural(
280            "src-override",
281            "xs:override requires 'schemaLocation' attribute",
282            None,
283        ))?;
284
285        let annotation = merge_foreign_attributes(
286            self.annotation,
287            self.foreign_attributes,
288            self.source.clone(),
289        );
290        Ok(FrameResult::Directive(DirectiveResult::Override(OverrideResult {
291            schema_location,
292            id: self.id,
293            annotation,
294            source: self.source,
295            simple_types: self.simple_types,
296            complex_types: self.complex_types,
297            elements: self.elements,
298            attributes: self.attributes,
299            groups: self.groups,
300            attribute_groups: self.attribute_groups,
301            notations: self.notations,
302        })))
303    }
304
305    fn children_are_top_level(&self) -> bool {
306        true
307    }
308
309    fn source(&self) -> Option<&SourceRef> {
310        self.source.as_ref()
311    }
312
313    fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
314        self.foreign_attributes = attrs;
315    }
316}
317
318/// Frame for xs:redefine
319pub struct RedefineFrame {
320    schema_location: Option<String>,
321    id: Option<String>,
322    annotation: Option<Annotation>,
323    components: Vec<RedefineComponent>,
324    source: Option<SourceRef>,
325    foreign_attributes: Vec<ForeignAttribute>,
326}
327
328impl RedefineFrame {
329    pub fn new(
330        attrs: &AttributeMap,
331        name_table: &NameTable,
332        source: Option<SourceRef>,
333    ) -> SchemaResult<Self> {
334        let schema_location = attrs
335            .get_value_by_name(name_table, "schemaLocation")
336            .map(String::from);
337
338        let id = attrs
339            .get_value_by_name(name_table, "id")
340            .map(String::from);
341
342        Ok(Self {
343            schema_location,
344            id,
345            annotation: None,
346            components: Vec::new(),
347            source,
348            foreign_attributes: Vec::new(),
349        })
350    }
351}
352
353impl Frame for RedefineFrame {
354    fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
355        matches!(
356            local_name,
357            xsd_names::ANNOTATION
358                | xsd_names::SIMPLE_TYPE
359                | xsd_names::COMPLEX_TYPE
360                | xsd_names::GROUP
361                | xsd_names::ATTRIBUTE_GROUP
362        )
363    }
364
365    fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
366        matches!(local_name, "schemaLocation" | "id")
367    }
368
369    fn on_child_start(&mut self, _local_name: &str, _name_table: &NameTable) {}
370
371    fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
372        match child {
373            FrameResult::Annotation(ann) => {
374                self.annotation = Some(ann);
375            }
376            FrameResult::Type(TypeFrameResult::Simple(st)) => {
377                self.components.push(RedefineComponent::SimpleType(st));
378            }
379            FrameResult::Type(TypeFrameResult::Complex(ct)) => {
380                self.components.push(RedefineComponent::ComplexType(ct));
381            }
382            FrameResult::Group(GroupFrameResult::Model(mg)) => {
383                self.components.push(RedefineComponent::Group(mg));
384            }
385            FrameResult::Group(GroupFrameResult::Attribute(ag)) => {
386                self.components.push(RedefineComponent::AttributeGroup(ag));
387            }
388            FrameResult::Skip => {}
389            _ => {}
390        }
391        Ok(())
392    }
393
394    fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
395        let schema_location = self.schema_location.ok_or_else(|| SchemaError::structural(
396            "src-redefine",
397            "xs:redefine requires 'schemaLocation' attribute",
398            None,
399        ))?;
400
401        let annotation = merge_foreign_attributes(
402            self.annotation,
403            self.foreign_attributes,
404            self.source.clone(),
405        );
406        Ok(FrameResult::Directive(DirectiveResult::Redefine(RedefineResult {
407            schema_location,
408            id: self.id,
409            annotation,
410            components: self.components,
411            source: self.source,
412        })))
413    }
414
415    fn children_are_top_level(&self) -> bool {
416        true
417    }
418
419    fn source(&self) -> Option<&SourceRef> {
420        self.source.as_ref()
421    }
422
423    fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
424        self.foreign_attributes = attrs;
425    }
426}
427