Skip to main content

xsd_schema/parser/
assemble.rs

1//! Assemble schema components from parser frame results.
2//!
3//! Converts `SchemaFrameResult` into `SchemaDocument` and registers top-level
4//! components in the schema set arenas and namespace tables.
5
6use std::collections::HashSet;
7
8use crate::arenas::{
9    AttributeDeclData, AttributeGroupData, ComplexTypeDefData, ElementDeclData,
10    IdentityConstraintData, ModelGroupData, NotationData, SimpleTypeDefData,
11};
12use crate::error::{SchemaError, SchemaResult};
13use crate::ids::{
14    AttributeGroupKey, AttributeKey, DocumentId, ElementKey, IdentityConstraintKey, ModelGroupKey,
15    NameId, NotationKey, TypeKey,
16};
17use crate::namespace::QualifiedName;
18use crate::parser::frames::{
19    AttributeFrameResult, AttributeGroupDefResult, ComplexContentResult, ComplexTypeResult,
20    DirectiveResult, FrameResult, GroupFrameResult, ModelGroupDefResult, NotationResult,
21    OverrideResult, RedefineComponent, SchemaFrameResult, SimpleTypeResult, TypeFrameResult,
22};
23use crate::parser::location::SourceRef;
24use crate::schema::composition::{
25    ComponentIdentity, ComponentKey, ComponentKind, DocumentComponentIndex,
26};
27use crate::schema::model::{
28    FormChoice, ImportDirective, IncludeDirective, OverrideComponent, OverrideDirective,
29    RedefineDirective, SchemaDocument,
30};
31use crate::schema::wildcard::{
32    ElementWildcard, NamespaceConstraint, ProcessContents as SchemaProcessContents,
33};
34use crate::validation::asttree::Asttree;
35use crate::SchemaSet;
36
37/// Result type for convert_directives function
38type DirectivesResult = (
39    Vec<IncludeDirective>,
40    Vec<ImportDirective>,
41    Vec<RedefineDirective>,
42    Vec<OverrideDirective>,
43);
44
45pub struct SchemaAssembler<'a> {
46    schema_set: &'a mut SchemaSet,
47    target_namespace: Option<NameId>,
48    block_default: crate::schema::model::DerivationSet,
49    final_default: crate::schema::model::DerivationSet,
50    /// Identity constraint names seen in this document (for uniqueness checking)
51    /// XSD constraint: Identity Constraint Name Uniqueness - names must be unique per schema document
52    identity_constraint_names: HashSet<NameId>,
53    /// Per-document component index being built during assembly
54    doc_components: DocumentComponentIndex,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58enum GroupKeyResult {
59    Model(ModelGroupKey),
60    Attribute(AttributeGroupKey),
61}
62
63impl<'a> SchemaAssembler<'a> {
64    pub fn new(
65        schema_set: &'a mut SchemaSet,
66        target_namespace: Option<NameId>,
67        block_default: crate::schema::model::DerivationSet,
68        final_default: crate::schema::model::DerivationSet,
69    ) -> Self {
70        Self {
71            schema_set,
72            target_namespace,
73            block_default,
74            final_default,
75            identity_constraint_names: HashSet::new(),
76            doc_components: DocumentComponentIndex::new(),
77        }
78    }
79
80    pub fn assemble(
81        &mut self,
82        schema: SchemaFrameResult,
83        doc_id: DocumentId,
84        base_uri: &str,
85    ) -> SchemaResult<SchemaDocument> {
86        let mut doc =
87            build_schema_document(&schema, doc_id, base_uri, &mut self.schema_set.name_table)?;
88
89        let directives = schema.directives;
90        let components = schema.components;
91        let (includes, imports, redefines, overrides) = convert_directives(directives, self)?;
92        doc.includes = includes;
93        doc.imports = imports;
94        doc.redefines = redefines;
95        doc.overrides = overrides;
96
97        for component in components {
98            self.assemble_component(component)?;
99        }
100
101        doc.component_index = std::mem::take(&mut self.doc_components);
102        Ok(doc)
103    }
104
105    fn assemble_component(&mut self, component: FrameResult) -> SchemaResult<()> {
106        match component {
107            FrameResult::Type(result) => {
108                self.assemble_type(result, true)?;
109            }
110            FrameResult::Element(result) => {
111                self.assemble_element(result, true)?;
112            }
113            FrameResult::Attribute(result) => {
114                self.assemble_attribute(result, true)?;
115            }
116            FrameResult::Group(result) => {
117                self.assemble_group(result, true)?;
118            }
119            FrameResult::Notation(result) => {
120                self.assemble_notation(result, true)?;
121            }
122            _ => {}
123        }
124        Ok(())
125    }
126
127    fn assemble_type(&mut self, result: TypeFrameResult, register: bool) -> SchemaResult<TypeKey> {
128        match result {
129            TypeFrameResult::Simple(simple) => {
130                let SimpleTypeResult {
131                    name,
132                    variety,
133                    base_type,
134                    item_type,
135                    member_types,
136                    facets,
137                    final_derivation,
138                    id,
139                    derivation_id,
140                    annotation,
141                    source,
142                } = *simple;
143                // final="" explicitly overrides finalDefault; None (absent) inherits it.
144                let final_derivation = final_derivation.unwrap_or(self.final_default);
145                let source_ref = source.clone();
146                let name = name.ok_or_else(|| {
147                    missing_name("simpleType", source_ref.as_ref(), self.schema_set)
148                })?;
149                let data = SimpleTypeDefData {
150                    name: Some(name),
151                    target_namespace: self.target_namespace,
152                    variety,
153                    base_type,
154                    item_type,
155                    member_types,
156                    facets,
157                    final_derivation,
158                    id,
159                    derivation_id,
160                    annotation,
161                    source,
162                    // Resolved references (populated after reference resolution phase)
163                    resolved_base_type: None,
164                    resolved_item_type: None,
165                    resolved_member_types: Vec::new(),
166                    redefine_original: None,
167                    deferred_item_type_error: None,
168                };
169                let key = self.schema_set.arenas.alloc_simple_type(data);
170                let type_key = TypeKey::Simple(key);
171                if register {
172                    self.register_type(name, type_key, source_ref.as_ref())?;
173                }
174                Ok(type_key)
175            }
176            TypeFrameResult::Complex(complex) => {
177                let ComplexTypeResult {
178                    name,
179                    base_type,
180                    derivation_method,
181                    content,
182                    attributes,
183                    attribute_groups,
184                    attribute_wildcard,
185                    mixed,
186                    is_abstract,
187                    final_derivation,
188                    block,
189                    default_attributes_apply,
190                    id,
191                    #[cfg(feature = "xsd11")]
192                    xpath_default_namespace,
193                    annotation,
194                    source,
195                } = *complex;
196                // final="" explicitly overrides finalDefault; None (absent) inherits it.
197                let final_derivation = final_derivation.unwrap_or(self.final_default);
198                // block="" explicitly overrides blockDefault; None (absent) inherits it.
199                let block = block.unwrap_or(self.block_default);
200                let open_content = match &content {
201                    ComplexContentResult::Complex(def) => def.open_content.clone(),
202                    _ => None,
203                };
204                #[cfg(feature = "xsd11")]
205                let assertions = match &content {
206                    ComplexContentResult::Simple(sc) => sc.assertions.clone(),
207                    ComplexContentResult::Complex(cc) => cc.assertions.clone(),
208                    ComplexContentResult::Empty => Vec::new(),
209                };
210                let source_ref = source.clone();
211                let name = name.ok_or_else(|| {
212                    missing_name("complexType", source_ref.as_ref(), self.schema_set)
213                })?;
214                let data = ComplexTypeDefData {
215                    name: Some(name),
216                    target_namespace: self.target_namespace,
217                    base_type,
218                    derivation_method,
219                    content,
220                    open_content,
221                    attributes,
222                    attribute_groups,
223                    attribute_wildcard,
224                    mixed,
225                    is_abstract,
226                    final_derivation,
227                    block,
228                    default_attributes_apply,
229                    id,
230                    #[cfg(feature = "xsd11")]
231                    assertions,
232                    #[cfg(feature = "xsd11")]
233                    xpath_default_namespace,
234                    annotation,
235                    source,
236                    // Resolved references (populated after reference resolution phase)
237                    resolved_base_type: None,
238                    resolved_attribute_groups: Vec::new(),
239                    resolved_attributes: Vec::new(),
240                    resolved_content_particle_types: Vec::new(),
241                    resolved_content_particle_elements: Vec::new(),
242                    resolved_simple_content_type: None,
243                    redefine_original: None,
244                };
245                let key = self.schema_set.arenas.alloc_complex_type(data);
246                let type_key = TypeKey::Complex(key);
247                if register {
248                    self.register_type(name, type_key, source_ref.as_ref())?;
249                }
250                Ok(type_key)
251            }
252        }
253    }
254
255    fn assemble_element(
256        &mut self,
257        result: crate::parser::frames::ElementFrameResult,
258        register: bool,
259    ) -> SchemaResult<ElementKey> {
260        let crate::parser::frames::ElementFrameResult {
261            name,
262            ref_name,
263            target_namespace: local_namespace,
264            type_ref,
265            inline_type,
266            substitution_group,
267            default_value,
268            fixed_value,
269            nillable,
270            is_abstract,
271            min_occurs,
272            max_occurs,
273            block,
274            final_derivation,
275            form,
276            id,
277            alternatives,
278            identity_constraints,
279            identity_constraint_refs,
280            annotation,
281            source,
282        } = result;
283        let source_ref = source.clone();
284        let name =
285            name.ok_or_else(|| missing_name("element", source_ref.as_ref(), self.schema_set))?;
286        let target_namespace = local_namespace.or(self.target_namespace);
287        // final="" explicitly overrides finalDefault; None (absent) inherits it.
288        // block="" explicitly overrides blockDefault; None (absent) inherits it.
289        let (final_derivation, block) = if ref_name.is_none() {
290            (
291                final_derivation.unwrap_or(self.final_default),
292                block.unwrap_or(self.block_default),
293            )
294        } else {
295            (
296                final_derivation.unwrap_or_default(),
297                block.unwrap_or_default(),
298            )
299        };
300
301        // Check identity constraint name uniqueness (per schema document)
302        // XSD Constraint: Identity Constraint Name Uniqueness (§3.11.1)
303        for ic in &identity_constraints {
304            if !self.identity_constraint_names.insert(ic.name) {
305                // Name already exists in this document - duplicate error
306                let location = self.schema_set.locate(ic.source.as_ref());
307                let name_str = self.schema_set.name_table.resolve(ic.name);
308                return Err(SchemaError::structural(
309                    "ic-unique",
310                    format!(
311                        "Duplicate identity constraint name '{}' in schema document",
312                        name_str
313                    ),
314                    location,
315                ));
316            }
317        }
318
319        // Validate identity constraint XPath expressions at schema time (§3.11.4)
320        for ic in &identity_constraints {
321            let xsd_version = self.schema_set.xsd_version;
322            // Validate selector XPath
323            if let Err(e) = Asttree::compile_selector(
324                &ic.selector.xpath,
325                &ic.selector.ns_snapshot,
326                &self.schema_set.name_table,
327                ic.selector.xpath_default_namespace.as_deref(),
328                None, // schema-level xpathDefaultNamespace resolved later
329                self.target_namespace,
330                xsd_version,
331            ) {
332                let ic_name = self.schema_set.name_table.resolve_ref(ic.name);
333                let location = self.schema_set.locate(ic.source.as_ref());
334                return Err(SchemaError::structural(
335                    "src-identity-constraint",
336                    format!(
337                        "Identity constraint '{}': invalid selector XPath '{}': {}",
338                        ic_name, ic.selector.xpath, e
339                    ),
340                    location,
341                ));
342            }
343            // Validate field XPath expressions
344            for field in &ic.fields {
345                if let Err(e) = Asttree::compile_field(
346                    &field.xpath,
347                    &field.ns_snapshot,
348                    &self.schema_set.name_table,
349                    field.xpath_default_namespace.as_deref(),
350                    None,
351                    self.target_namespace,
352                    xsd_version,
353                ) {
354                    let ic_name = self.schema_set.name_table.resolve_ref(ic.name);
355                    let location = self.schema_set.locate(ic.source.as_ref());
356                    return Err(SchemaError::structural(
357                        "src-identity-constraint",
358                        format!(
359                            "Identity constraint '{}': invalid field XPath '{}': {}",
360                            ic_name, field.xpath, e
361                        ),
362                        location,
363                    ));
364                }
365            }
366        }
367
368        // Validate keyref constraints: refer must resolve to a key/unique
369        // with matching field count (§3.11.4, §3.11.6)
370        crate::schema::inline::validate_keyref_refers(
371            &identity_constraints,
372            self.target_namespace,
373            &self.schema_set.name_table,
374            &self.schema_set.source_maps,
375            &self.schema_set.arenas.identity_constraints,
376            &self.schema_set.documents,
377        )?;
378
379        // Allocate identity constraints into the arena and register in namespace table
380        let identity_constraint_keys: Vec<IdentityConstraintKey> = identity_constraints
381            .into_iter()
382            .map(|ic| {
383                let ic_name = ic.name;
384                let key =
385                    self.schema_set
386                        .arenas
387                        .alloc_identity_constraint(IdentityConstraintData {
388                            kind: ic.kind,
389                            name: ic.name,
390                            ref_name: ic.ref_name,
391                            refer: ic.refer,
392                            selector: ic.selector,
393                            fields: ic.fields,
394                            id: ic.id,
395                            annotation: ic.annotation,
396                            source: ic.source,
397                        });
398                // Register in namespace table for @ref resolution
399                let ns_table = self.schema_set.get_or_create_namespace(target_namespace);
400                ns_table.identity_constraints.insert(ic_name, key);
401                key
402            })
403            .collect();
404
405        // Defer XSD 1.1 @ref identity constraint references for resolution
406        // in resolve_all_references() — the target IC may not exist yet
407        // (forward references / included schemas).
408        let pending_ic_refs: Vec<_> = identity_constraint_refs
409            .into_iter()
410            .map(|r| (r.kind, r.ref_name, r.source))
411            .collect();
412
413        let data = ElementDeclData {
414            name: Some(name),
415            target_namespace,
416            ref_name,
417            type_ref,
418            inline_type,
419            substitution_group,
420            default_value,
421            fixed_value,
422            nillable,
423            is_abstract,
424            min_occurs,
425            max_occurs,
426            block,
427            final_derivation,
428            form,
429            id,
430            alternatives,
431            identity_constraints: identity_constraint_keys,
432            pending_ic_refs,
433            annotation,
434            source,
435            // Resolved references (populated after reference resolution phase)
436            resolved_type: None,
437            resolved_ref: None,
438            resolved_substitution_groups: Vec::new(),
439            deferred_type_error: None,
440        };
441        let key = self.schema_set.arenas.alloc_element(data);
442        if register {
443            self.register_element(name, key, source_ref.as_ref())?;
444        }
445        Ok(key)
446    }
447
448    fn assemble_attribute(
449        &mut self,
450        result: AttributeFrameResult,
451        register: bool,
452    ) -> SchemaResult<AttributeKey> {
453        let AttributeFrameResult {
454            name,
455            ref_name,
456            target_namespace: local_namespace,
457            type_ref,
458            inline_type,
459            default_value,
460            fixed_value,
461            use_kind,
462            form,
463            inheritable,
464            id,
465            annotation,
466            source,
467        } = result;
468        let source_ref = source.clone();
469        let name =
470            name.ok_or_else(|| missing_name("attribute", source_ref.as_ref(), self.schema_set))?;
471        let target_namespace = local_namespace.or(self.target_namespace);
472        let data = AttributeDeclData {
473            name: Some(name),
474            target_namespace,
475            ref_name,
476            type_ref,
477            inline_type,
478            default_value,
479            fixed_value,
480            use_kind,
481            form,
482            inheritable,
483            id,
484            annotation,
485            source,
486            // Resolved references (populated after reference resolution phase)
487            resolved_type: None,
488            resolved_ref: None,
489        };
490        let key = self.schema_set.arenas.alloc_attribute(data);
491        if register {
492            self.register_attribute(name, key, source_ref.as_ref())?;
493        }
494        Ok(key)
495    }
496
497    fn assemble_group(
498        &mut self,
499        result: GroupFrameResult,
500        register: bool,
501    ) -> SchemaResult<GroupKeyResult> {
502        match result {
503            GroupFrameResult::Model(group) => {
504                let ModelGroupDefResult {
505                    name,
506                    ref_name,
507                    compositor,
508                    particles,
509                    min_occurs,
510                    max_occurs,
511                    id,
512                    annotation,
513                    source,
514                } = *group;
515                let source_ref = source.clone();
516                let name = name
517                    .ok_or_else(|| missing_name("group", source_ref.as_ref(), self.schema_set))?;
518                let data = ModelGroupData {
519                    name: Some(name),
520                    target_namespace: self.target_namespace,
521                    ref_name,
522                    compositor,
523                    particles,
524                    min_occurs,
525                    max_occurs,
526                    id,
527                    annotation,
528                    source,
529                    // Resolved references (populated after reference resolution phase)
530                    resolved_ref: None,
531                    resolved_particles: Vec::new(),
532                    resolved_particle_types: Vec::new(),
533                    resolved_particle_elements: Vec::new(),
534                    redefine_original: None,
535                    redefine_requires_restriction_check: false,
536                };
537                let key = self.schema_set.arenas.alloc_model_group(data);
538                if register {
539                    self.register_model_group(name, key, source_ref.as_ref())?;
540                }
541                Ok(GroupKeyResult::Model(key))
542            }
543            GroupFrameResult::Attribute(group) => {
544                let AttributeGroupDefResult {
545                    name,
546                    ref_name,
547                    attributes,
548                    attribute_groups,
549                    attribute_wildcard,
550                    id,
551                    annotation,
552                    source,
553                } = *group;
554                let source_ref = source.clone();
555                let name = name.ok_or_else(|| {
556                    missing_name("attributeGroup", source_ref.as_ref(), self.schema_set)
557                })?;
558                let data = AttributeGroupData {
559                    name: Some(name),
560                    target_namespace: self.target_namespace,
561                    ref_name,
562                    attributes,
563                    attribute_groups,
564                    attribute_wildcard,
565                    id,
566                    annotation,
567                    source,
568                    // Resolved references (populated after reference resolution phase)
569                    resolved_ref: None,
570                    resolved_attribute_groups: Vec::new(),
571                    resolved_attributes: Vec::new(),
572                    redefine_original: None,
573                    redefine_requires_restriction_check: false,
574                };
575                let key = self.schema_set.arenas.alloc_attribute_group(data);
576                if register {
577                    self.register_attribute_group(name, key, source_ref.as_ref())?;
578                }
579                Ok(GroupKeyResult::Attribute(key))
580            }
581        }
582    }
583
584    fn assemble_notation(
585        &mut self,
586        result: NotationResult,
587        register: bool,
588    ) -> SchemaResult<NotationKey> {
589        let NotationResult {
590            name,
591            public,
592            system,
593            id,
594            annotation,
595            source,
596        } = result;
597        let source_ref = source.clone();
598        let name =
599            name.ok_or_else(|| missing_name("notation", source_ref.as_ref(), self.schema_set))?;
600        let data = NotationData {
601            name,
602            target_namespace: self.target_namespace,
603            public,
604            system,
605            id,
606            annotation,
607            source,
608        };
609        let key = self.schema_set.arenas.alloc_notation(data);
610        if register {
611            self.register_notation(name, key, source_ref.as_ref())?;
612        }
613        Ok(key)
614    }
615
616    fn register_type(
617        &mut self,
618        name: NameId,
619        key: TypeKey,
620        source: Option<&SourceRef>,
621    ) -> SchemaResult<()> {
622        let location = source.and_then(|s| self.schema_set.source_maps.locate(s));
623        let name_str = self.schema_set.name_table.resolve(name).to_string();
624        let ns_table = self
625            .schema_set
626            .get_or_create_namespace(self.target_namespace);
627        if ns_table.register_type(name, key).is_some() {
628            return Err(SchemaError::structural(
629                "sch-props-correct",
630                format!("Duplicate type declaration '{}'", name_str),
631                location,
632            ));
633        }
634        let kind = match key {
635            TypeKey::Simple(_) => ComponentKind::SimpleType,
636            TypeKey::Complex(_) => ComponentKind::ComplexType,
637        };
638        self.record_component(kind, name, ComponentKey::Type(key));
639        Ok(())
640    }
641
642    /// Record a component in the per-document component index.
643    fn record_component(&mut self, kind: ComponentKind, name: NameId, key: ComponentKey) {
644        self.doc_components.insert(
645            ComponentIdentity {
646                kind,
647                name,
648                namespace: self.target_namespace,
649            },
650            key,
651        );
652    }
653
654    fn register_element(
655        &mut self,
656        name: NameId,
657        key: ElementKey,
658        source: Option<&SourceRef>,
659    ) -> SchemaResult<()> {
660        let location = source.and_then(|s| self.schema_set.source_maps.locate(s));
661        let name_str = self.schema_set.name_table.resolve(name).to_string();
662        let ns_table = self
663            .schema_set
664            .get_or_create_namespace(self.target_namespace);
665        if ns_table.register_element(name, key).is_some() {
666            return Err(SchemaError::structural(
667                "sch-props-correct",
668                format!("Duplicate element declaration '{}'", name_str),
669                location,
670            ));
671        }
672        self.record_component(ComponentKind::Element, name, ComponentKey::Element(key));
673        Ok(())
674    }
675
676    fn register_attribute(
677        &mut self,
678        name: NameId,
679        key: AttributeKey,
680        source: Option<&SourceRef>,
681    ) -> SchemaResult<()> {
682        let location = source.and_then(|s| self.schema_set.source_maps.locate(s));
683        let name_str = self.schema_set.name_table.resolve(name).to_string();
684        let ns_table = self
685            .schema_set
686            .get_or_create_namespace(self.target_namespace);
687        if ns_table.register_attribute(name, key).is_some() {
688            return Err(SchemaError::structural(
689                "sch-props-correct",
690                format!("Duplicate attribute declaration '{}'", name_str),
691                location,
692            ));
693        }
694        self.record_component(ComponentKind::Attribute, name, ComponentKey::Attribute(key));
695        Ok(())
696    }
697
698    fn register_model_group(
699        &mut self,
700        name: NameId,
701        key: ModelGroupKey,
702        source: Option<&SourceRef>,
703    ) -> SchemaResult<()> {
704        let location = source.and_then(|s| self.schema_set.source_maps.locate(s));
705        let name_str = self.schema_set.name_table.resolve(name).to_string();
706        let ns_table = self
707            .schema_set
708            .get_or_create_namespace(self.target_namespace);
709        if ns_table.register_model_group(name, key).is_some() {
710            return Err(SchemaError::structural(
711                "sch-props-correct",
712                format!("Duplicate group declaration '{}'", name_str),
713                location,
714            ));
715        }
716        self.record_component(
717            ComponentKind::ModelGroup,
718            name,
719            ComponentKey::ModelGroup(key),
720        );
721        Ok(())
722    }
723
724    fn register_attribute_group(
725        &mut self,
726        name: NameId,
727        key: AttributeGroupKey,
728        source: Option<&SourceRef>,
729    ) -> SchemaResult<()> {
730        let location = source.and_then(|s| self.schema_set.source_maps.locate(s));
731        let name_str = self.schema_set.name_table.resolve(name).to_string();
732        let ns_table = self
733            .schema_set
734            .get_or_create_namespace(self.target_namespace);
735        if ns_table.register_attribute_group(name, key).is_some() {
736            return Err(SchemaError::structural(
737                "sch-props-correct",
738                format!("Duplicate attribute group declaration '{}'", name_str),
739                location,
740            ));
741        }
742        self.record_component(
743            ComponentKind::AttributeGroup,
744            name,
745            ComponentKey::AttributeGroup(key),
746        );
747        Ok(())
748    }
749
750    fn register_notation(
751        &mut self,
752        name: NameId,
753        key: NotationKey,
754        source: Option<&SourceRef>,
755    ) -> SchemaResult<()> {
756        let location = source.and_then(|s| self.schema_set.source_maps.locate(s));
757        let name_str = self.schema_set.name_table.resolve(name).to_string();
758        let ns_table = self
759            .schema_set
760            .get_or_create_namespace(self.target_namespace);
761        if ns_table.register_notation(name, key).is_some() {
762            return Err(SchemaError::structural(
763                "sch-props-correct",
764                format!("Duplicate notation declaration '{}'", name_str),
765                location,
766            ));
767        }
768        self.record_component(ComponentKind::Notation, name, ComponentKey::Notation(key));
769        Ok(())
770    }
771}
772
773pub fn assemble_schema(
774    schema_set: &mut SchemaSet,
775    doc_id: DocumentId,
776    base_uri: &str,
777    result: SchemaFrameResult,
778) -> SchemaResult<SchemaDocument> {
779    let target_namespace = result.target_namespace;
780    let mut assembler = SchemaAssembler::new(
781        schema_set,
782        target_namespace,
783        result.block_default,
784        result.final_default,
785    );
786    assembler.assemble(result, doc_id, base_uri)
787}
788
789pub fn build_schema_document(
790    result: &SchemaFrameResult,
791    doc_id: DocumentId,
792    base_uri: &str,
793    name_table: &mut crate::namespace::NameTable,
794) -> SchemaResult<SchemaDocument> {
795    let mut doc = SchemaDocument::new(doc_id, base_uri.to_string());
796
797    doc.target_namespace = result.target_namespace;
798    doc.element_form_default = parse_form_choice(result.element_form_default.as_deref());
799    doc.attribute_form_default = parse_form_choice(result.attribute_form_default.as_deref());
800    doc.block_default = result.block_default;
801    doc.final_default = result.final_default;
802    doc.version = result.version.clone();
803    doc.source = result.source.clone();
804    doc.schema_id = result.id.clone();
805    doc.xml_lang = result.xml_lang.clone();
806    doc.annotations = result.annotations.clone();
807
808    if let Some(default_attrs) = &result.default_attributes {
809        doc.default_attributes = Some(QualifiedName::new(
810            default_attrs.namespace,
811            default_attrs.local_name,
812            default_attrs.prefix,
813        ));
814    }
815
816    if let Some(xpath_ns) = result.xpath_default_namespace.as_deref() {
817        doc.xpath_default_namespace = name_table
818            .get(xpath_ns)
819            .or_else(|| Some(name_table.add(xpath_ns)));
820    }
821
822    if let Some(doc_result) = &result.default_open_content {
823        doc.default_open_content = Some(crate::schema::DefaultOpenContent {
824            source: doc_result.source.clone(),
825            applies_to_empty: doc_result.applies_to_empty,
826            mode: doc_result.mode.into(),
827            wildcard: doc_result
828                .wildcard
829                .as_ref()
830                .map(|wc| convert_element_wildcard(wc, result.target_namespace)),
831        });
832    }
833
834    Ok(doc)
835}
836
837pub fn convert_directives(
838    directives: Vec<DirectiveResult>,
839    assembler: &mut SchemaAssembler<'_>,
840) -> SchemaResult<DirectivesResult> {
841    let mut includes = Vec::new();
842    let mut imports = Vec::new();
843    let mut redefines = Vec::new();
844    let mut overrides = Vec::new();
845
846    for directive in directives {
847        match directive {
848            DirectiveResult::Include(inc) => {
849                includes.push(IncludeDirective {
850                    source: inc.source.clone(),
851                    schema_location: inc.schema_location.clone(),
852                    resolved_doc_id: None,
853                });
854            }
855            DirectiveResult::Import(imp) => {
856                imports.push(ImportDirective {
857                    source: imp.source.clone(),
858                    namespace: imp.namespace.clone(),
859                    schema_location: imp.schema_location.clone(),
860                    resolved_doc_id: None,
861                });
862            }
863            DirectiveResult::Redefine(red) => {
864                let mut simple_types = Vec::new();
865                let mut complex_types = Vec::new();
866                let mut groups = Vec::new();
867                let mut attribute_groups = Vec::new();
868
869                // §src-redefine clause 5 / 7.2.1: each named component can be
870                // redefined at most once within a single `<xs:redefine>`
871                // block. The W3C `schT2` fixture exercises this. The check
872                // must run before `assemble_*` so a duplicate's allocation
873                // does not pollute the arenas before we error out.
874                let mut seen_simple_types: HashSet<NameId> = HashSet::new();
875                let mut seen_complex_types: HashSet<NameId> = HashSet::new();
876                let mut seen_groups: HashSet<NameId> = HashSet::new();
877                let mut seen_attribute_groups: HashSet<NameId> = HashSet::new();
878
879                fn dup_redefine_err(
880                    schema_set: &SchemaSet,
881                    kind_label: &str,
882                    name: NameId,
883                    source: Option<&SourceRef>,
884                ) -> SchemaError {
885                    let location = source.and_then(|s| schema_set.source_maps.locate(s));
886                    SchemaError::structural(
887                        "src-redefine",
888                        format!(
889                            "Duplicate <xs:{} name=\"{}\"> within a single <xs:redefine> block",
890                            kind_label,
891                            schema_set.name_table.resolve(name),
892                        ),
893                        location,
894                    )
895                }
896
897                for component in red.components {
898                    match component {
899                        RedefineComponent::SimpleType(st) => {
900                            if let Some(name) = st.name {
901                                if !seen_simple_types.insert(name) {
902                                    return Err(dup_redefine_err(
903                                        assembler.schema_set,
904                                        "simpleType",
905                                        name,
906                                        st.source.as_ref(),
907                                    ));
908                                }
909                            }
910                            let key =
911                                assembler.assemble_type(TypeFrameResult::Simple(st), false)?;
912                            if let TypeKey::Simple(simple) = key {
913                                simple_types.push(simple);
914                            }
915                        }
916                        RedefineComponent::ComplexType(ct) => {
917                            if let Some(name) = ct.name {
918                                if !seen_complex_types.insert(name) {
919                                    return Err(dup_redefine_err(
920                                        assembler.schema_set,
921                                        "complexType",
922                                        name,
923                                        ct.source.as_ref(),
924                                    ));
925                                }
926                            }
927                            let key =
928                                assembler.assemble_type(TypeFrameResult::Complex(ct), false)?;
929                            if let TypeKey::Complex(complex) = key {
930                                complex_types.push(complex);
931                            }
932                        }
933                        RedefineComponent::Group(group) => {
934                            if let Some(name) = group.name {
935                                if !seen_groups.insert(name) {
936                                    return Err(dup_redefine_err(
937                                        assembler.schema_set,
938                                        "group",
939                                        name,
940                                        group.source.as_ref(),
941                                    ));
942                                }
943                            }
944                            if let GroupKeyResult::Model(key) =
945                                assembler.assemble_group(GroupFrameResult::Model(group), false)?
946                            {
947                                groups.push(key);
948                            }
949                        }
950                        RedefineComponent::AttributeGroup(group) => {
951                            if let Some(name) = group.name {
952                                if !seen_attribute_groups.insert(name) {
953                                    return Err(dup_redefine_err(
954                                        assembler.schema_set,
955                                        "attributeGroup",
956                                        name,
957                                        group.source.as_ref(),
958                                    ));
959                                }
960                            }
961                            if let GroupKeyResult::Attribute(key) = assembler
962                                .assemble_group(GroupFrameResult::Attribute(group), false)?
963                            {
964                                attribute_groups.push(key);
965                            }
966                        }
967                    }
968                }
969
970                redefines.push(RedefineDirective {
971                    source: red.source.clone(),
972                    schema_location: red.schema_location.clone(),
973                    resolved_doc_id: None,
974                    simple_types,
975                    complex_types,
976                    groups,
977                    attribute_groups,
978                });
979            }
980            DirectiveResult::Override(override_result) => {
981                overrides.push(convert_override(override_result, assembler)?);
982            }
983        }
984    }
985
986    Ok((includes, imports, redefines, overrides))
987}
988
989fn convert_override(
990    override_result: OverrideResult,
991    assembler: &mut SchemaAssembler<'_>,
992) -> SchemaResult<OverrideDirective> {
993    // Override children should NOT inherit the overriding document's defaults.
994    // Per F.2, they are conceptually placed into the overridden document D2',
995    // so D2's blockDefault/finalDefault should apply instead. We assemble
996    // with empty defaults here; the correct defaults are applied later in
997    // `apply_override()` once D2 is known.
998    let saved_block = std::mem::replace(
999        &mut assembler.block_default,
1000        crate::schema::model::DerivationSet::empty(),
1001    );
1002    let saved_final = std::mem::replace(
1003        &mut assembler.final_default,
1004        crate::schema::model::DerivationSet::empty(),
1005    );
1006
1007    let result = convert_override_body(override_result, assembler);
1008
1009    // Restore the overriding document's defaults for any subsequent
1010    // non-override components in the same document.
1011    assembler.block_default = saved_block;
1012    assembler.final_default = saved_final;
1013
1014    result
1015}
1016
1017fn convert_override_body(
1018    override_result: OverrideResult,
1019    assembler: &mut SchemaAssembler<'_>,
1020) -> SchemaResult<OverrideDirective> {
1021    let mut components = Vec::new();
1022
1023    for st in override_result.simple_types {
1024        let key = assembler.assemble_type(TypeFrameResult::Simple(Box::new(st)), false)?;
1025        if let TypeKey::Simple(simple) = key {
1026            components.push(OverrideComponent::SimpleType(simple));
1027        }
1028    }
1029
1030    for ct in override_result.complex_types {
1031        let key = assembler.assemble_type(TypeFrameResult::Complex(Box::new(ct)), false)?;
1032        if let TypeKey::Complex(complex) = key {
1033            components.push(OverrideComponent::ComplexType(complex));
1034        }
1035    }
1036
1037    for el in override_result.elements {
1038        let key = assembler.assemble_element(el, false)?;
1039        components.push(OverrideComponent::Element(key));
1040    }
1041
1042    for attr in override_result.attributes {
1043        let key = assembler.assemble_attribute(attr, false)?;
1044        components.push(OverrideComponent::Attribute(key));
1045    }
1046
1047    for group in override_result.groups {
1048        match group {
1049            GroupFrameResult::Model(model) => {
1050                if let GroupKeyResult::Model(key) =
1051                    assembler.assemble_group(GroupFrameResult::Model(model), false)?
1052                {
1053                    components.push(OverrideComponent::Group(key));
1054                }
1055            }
1056            GroupFrameResult::Attribute(group) => {
1057                if let GroupKeyResult::Attribute(key) =
1058                    assembler.assemble_group(GroupFrameResult::Attribute(group), false)?
1059                {
1060                    components.push(OverrideComponent::AttributeGroup(key));
1061                }
1062            }
1063        }
1064    }
1065
1066    for group in override_result.attribute_groups {
1067        if let GroupFrameResult::Attribute(group) = group {
1068            if let GroupKeyResult::Attribute(key) =
1069                assembler.assemble_group(GroupFrameResult::Attribute(group), false)?
1070            {
1071                components.push(OverrideComponent::AttributeGroup(key));
1072            }
1073        }
1074    }
1075
1076    for notation in override_result.notations {
1077        let key = assembler.assemble_notation(notation, false)?;
1078        components.push(OverrideComponent::Notation(key));
1079    }
1080
1081    Ok(OverrideDirective {
1082        source: override_result.source.clone(),
1083        schema_location: override_result.schema_location.clone(),
1084        resolved_doc_id: None,
1085        components,
1086    })
1087}
1088
1089pub fn parse_form_choice(value: Option<&str>) -> FormChoice {
1090    match value {
1091        Some("qualified") => FormChoice::Qualified,
1092        Some("unqualified") | None => FormChoice::Unqualified,
1093        _ => FormChoice::Unqualified,
1094    }
1095}
1096
1097fn convert_element_wildcard(
1098    wildcard: &crate::parser::frames::WildcardResult,
1099    target_namespace: Option<NameId>,
1100) -> ElementWildcard {
1101    use crate::schema::wildcard::QNameDisallowed;
1102
1103    let mut result = ElementWildcard::new();
1104    result.namespace_constraint = match &wildcard.namespace {
1105        crate::parser::frames::WildcardNamespace::Any => NamespaceConstraint::Any,
1106        crate::parser::frames::WildcardNamespace::Other => NamespaceConstraint::Other,
1107        crate::parser::frames::WildcardNamespace::TargetNamespace => {
1108            NamespaceConstraint::Enumeration(vec![target_namespace])
1109        }
1110        crate::parser::frames::WildcardNamespace::Local => {
1111            NamespaceConstraint::Enumeration(vec![None])
1112        }
1113        crate::parser::frames::WildcardNamespace::List(list) => NamespaceConstraint::Enumeration(
1114            list.iter().map(|t| t.resolve(target_namespace)).collect(),
1115        ),
1116    };
1117
1118    // notNamespace → NamespaceConstraint::Not(...)
1119    if !wildcard.not_namespace.is_empty() {
1120        let excluded: Vec<Option<NameId>> = wildcard
1121            .not_namespace
1122            .iter()
1123            .map(|t| t.resolve(target_namespace))
1124            .collect();
1125        result.namespace_constraint = NamespaceConstraint::Not(excluded);
1126    }
1127
1128    // notQName → not_qnames
1129    result.not_qnames = wildcard
1130        .not_qname
1131        .iter()
1132        .map(|item| match item {
1133            crate::parser::frames::NotQNameItem::QName {
1134                namespace,
1135                local_name,
1136            } => QNameDisallowed::QName {
1137                namespace: *namespace,
1138                local_name: *local_name,
1139            },
1140            crate::parser::frames::NotQNameItem::Defined => QNameDisallowed::Defined,
1141            crate::parser::frames::NotQNameItem::DefinedSibling => QNameDisallowed::DefinedSibling,
1142        })
1143        .collect();
1144
1145    result.process_contents = match wildcard.process_contents {
1146        crate::parser::frames::ProcessContents::Strict => SchemaProcessContents::Strict,
1147        crate::parser::frames::ProcessContents::Lax => SchemaProcessContents::Lax,
1148        crate::parser::frames::ProcessContents::Skip => SchemaProcessContents::Skip,
1149    };
1150    result.id = wildcard.id.clone();
1151    result.source = wildcard.source.clone();
1152    result
1153}
1154
1155fn missing_name(kind: &str, source: Option<&SourceRef>, schema_set: &SchemaSet) -> SchemaError {
1156    let location = source.and_then(|s| schema_set.source_maps.locate(s));
1157    SchemaError::structural(
1158        "src-resolve",
1159        format!("Missing required name for {}", kind),
1160        location,
1161    )
1162}