Skip to content

# validate_references

## `xsdata.codegen.handlers.validate_references`

### `ValidateReferences`

Bases: `ContainerHandlerInterface`

Validate type references.

Rules

- An extension, type, restriction can not be shared
- All user types have to match the reference number and qualified name of a class.
- All global class qualified names must be unique

Source code in `xsdata/codegen/handlers/validate_references.py`

      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108

    class ValidateReferences(ContainerHandlerInterface):
        """Validate type references.

        Rules:
            - An extension, type, restriction can not be shared
            - All user types have to match the reference number
              and qualified name of a class.
            - All global class qualified names must be unique
        """

        def run(self) -> None:
            """Validate type references."""
            self.validate_unique_qualified_names()
            self.validate_unique_instances()
            self.validate_resolved_references()
            self.validate_parent_references()

        def validate_unique_qualified_names(self) -> None:
            """Validate all root classes have unique qualified names."""
            duplicate_types = []
            groups = collections.group_by(self.container, get_qname)
            for qname, items in groups.items():
                if len(items) > 1:
                    duplicate_types.append(qname)

            if duplicate_types:
                raise CodegenError("Duplicate types found", qnames=duplicate_types)

        def validate_unique_instances(self) -> None:
            """Validate all codegen instances are unique."""
            references: set[int] = set()
            for item in self.container:
                item_references = {id(child) for child in item.children()}
                if item_references.intersection(references):
                    raise CodegenError("Cross reference detected", type=item.qname)

                references.update(item_references)

        def validate_resolved_references(self) -> None:
            """Validate all types match a class reference and qualified name."""

            def build_reference_map() -> Iterator[tuple[int, str]]:
                def build(target: Class) -> Iterator[tuple[int, str]]:
                    yield target.ref, target.qname

                    for inner in target.inner:
                        yield from build(inner)

                for target in self.container:
                    yield from build(target)

            references = dict(build_reference_map())
            for item in self.container:
                for tp in item.types():
                    if tp.native:
                        continue

                    if tp.reference not in references:
                        raise CodegenError(
                            "Unresolved reference detected", cls=item.qname, type=tp.qname
                        )

                    if tp.qname != references[tp.reference]:
                        raise CodegenError(
                            "Misrepresented reference", cls=item.qname, type=tp.qname
                        )

        def validate_parent_references(self) -> None:
            """Validate inner to outer classes is accurate."""

            def _validate(target: Class, parent: Class | None = None) -> None:
                actual_qname = actual_ref = expected_qname = expected_ref = None
                if target.parent:
                    actual_qname = target.parent.qname
                    actual_ref = target.parent.ref

                if parent:
                    expected_qname = parent.qname
                    expected_ref = parent.ref

                if actual_qname != expected_qname:
                    raise CodegenError(
                        "Invalid parent class reference",
                        cls=target.qname,
                        expected=expected_qname,
                        actual=actual_qname,
                    )

                if actual_ref != expected_ref:
                    raise CodegenError(
                        "Invalid parent class reference",
                        cls=target.qname,
                        ref=actual_qname,
                    )

                for inner in target.inner:
                    _validate(inner, target)

            for item in self.container:
                _validate(item)

#### `run()`

Validate type references.

Source code in `xsdata/codegen/handlers/validate_references.py`

    19
    20
    21
    22
    23
    24

    def run(self) -> None:
        """Validate type references."""
        self.validate_unique_qualified_names()
        self.validate_unique_instances()
        self.validate_resolved_references()
        self.validate_parent_references()

#### `validate_unique_qualified_names()`

Validate all root classes have unique qualified names.

Source code in `xsdata/codegen/handlers/validate_references.py`

    26
    27
    28
    29
    30
    31
    32
    33
    34
    35

    def validate_unique_qualified_names(self) -> None:
        """Validate all root classes have unique qualified names."""
        duplicate_types = []
        groups = collections.group_by(self.container, get_qname)
        for qname, items in groups.items():
            if len(items) > 1:
                duplicate_types.append(qname)

        if duplicate_types:
            raise CodegenError("Duplicate types found", qnames=duplicate_types)

#### `validate_unique_instances()`

Validate all codegen instances are unique.

Source code in `xsdata/codegen/handlers/validate_references.py`

    37
    38
    39
    40
    41
    42
    43
    44
    45

    def validate_unique_instances(self) -> None:
        """Validate all codegen instances are unique."""
        references: set[int] = set()
        for item in self.container:
            item_references = {id(child) for child in item.children()}
            if item_references.intersection(references):
                raise CodegenError("Cross reference detected", type=item.qname)

            references.update(item_references)

#### `validate_resolved_references()`

Validate all types match a class reference and qualified name.

Source code in `xsdata/codegen/handlers/validate_references.py`

    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74

    def validate_resolved_references(self) -> None:
        """Validate all types match a class reference and qualified name."""

        def build_reference_map() -> Iterator[tuple[int, str]]:
            def build(target: Class) -> Iterator[tuple[int, str]]:
                yield target.ref, target.qname

                for inner in target.inner:
                    yield from build(inner)

            for target in self.container:
                yield from build(target)

        references = dict(build_reference_map())
        for item in self.container:
            for tp in item.types():
                if tp.native:
                    continue

                if tp.reference not in references:
                    raise CodegenError(
                        "Unresolved reference detected", cls=item.qname, type=tp.qname
                    )

                if tp.qname != references[tp.reference]:
                    raise CodegenError(
                        "Misrepresented reference", cls=item.qname, type=tp.qname
                    )

#### `validate_parent_references()`

Validate inner to outer classes is accurate.

Source code in `xsdata/codegen/handlers/validate_references.py`

     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108

    def validate_parent_references(self) -> None:
        """Validate inner to outer classes is accurate."""

        def _validate(target: Class, parent: Class | None = None) -> None:
            actual_qname = actual_ref = expected_qname = expected_ref = None
            if target.parent:
                actual_qname = target.parent.qname
                actual_ref = target.parent.ref

            if parent:
                expected_qname = parent.qname
                expected_ref = parent.ref

            if actual_qname != expected_qname:
                raise CodegenError(
                    "Invalid parent class reference",
                    cls=target.qname,
                    expected=expected_qname,
                    actual=actual_qname,
                )

            if actual_ref != expected_ref:
                raise CodegenError(
                    "Invalid parent class reference",
                    cls=target.qname,
                    ref=actual_qname,
                )

            for inner in target.inner:
                _validate(inner, target)

        for item in self.container:
            _validate(item)