"""
Verify that the instances of the meta-model satisfy the invariants.

Here is an example how to verify an instance of :py:class:`aas_core3.types.Extension`:

.. code-block::

    import aas_core3.types as aas_types
    import aas_core3.verification as aas_verification

    an_instance = aas_types.Extension(
        # ... some constructor arguments ...
    )

    for error in aas_verification.verify(an_instance):
        print(f"{error.cause} at: {error.path}")
"""

# This code has been automatically generated by aas-core-codegen.
# Do NOT edit or append.


import math
import re
import struct
import sys
from typing import (
    Callable,
    Iterable,
    Iterator,
    List,
    Mapping,
    Optional,
    Pattern,
    Sequence,
    Set,
    Union,
)

if sys.version_info >= (3, 8):
    from typing import Final
else:
    from typing_extensions import Final

from aas_core3 import (
    constants as aas_constants,
    types as aas_types,
)


class PropertySegment:
    """Represent a property access on a path to an erroneous value."""

    #: Instance containing the property
    instance: Final[aas_types.Class]

    #: Name of the property
    name: Final[str]

    def __init__(self, instance: aas_types.Class, name: str) -> None:
        """Initialize with the given values."""
        self.instance = instance
        self.name = name

    def __str__(self) -> str:
        return f".{self.name}"


class IndexSegment:
    """Represent an index access on a path to an erroneous value."""

    #: Sequence containing the item at :py:attr:`~index`
    sequence: Final[Sequence[aas_types.Class]]

    #: Index of the item
    index: Final[int]

    def __init__(self, sequence: Sequence[aas_types.Class], index: int) -> None:
        """Initialize with the given values."""
        self.sequence = sequence
        self.index = index

    def __str__(self) -> str:
        return f"[{self.index}]"


Segment = Union[PropertySegment, IndexSegment]


class Path:
    """Represent the relative path to the erroneous value."""

    def __init__(self) -> None:
        """Initialize as an empty path."""
        self._segments = []  # type: List[Segment]

    @property
    def segments(self) -> Sequence[Segment]:
        """Get the segments of the path."""
        return self._segments

    def _prepend(self, segment: Segment) -> None:
        """Insert the :paramref:`segment` in front of other segments."""
        self._segments.insert(0, segment)

    def __str__(self) -> str:
        return "".join(str(segment) for segment in self._segments)


class Error:
    """Represent a verification error in the data."""

    #: Human-readable description of the error
    cause: Final[str]

    #: Path to the erroneous value
    path: Final[Path]

    def __init__(self, cause: str) -> None:
        """Initialize as an error with an empty path."""
        self.cause = cause
        self.path = Path()

    def __repr__(self) -> str:
        return f"Error(path={self.path}, cause={self.cause})"


# noinspection SpellCheckingInspection
def _construct_matches_id_short() -> Pattern[str]:
    pattern = "^[a-zA-Z][a-zA-Z0-9_]*$"

    return re.compile(pattern)


_REGEX_MATCHES_ID_SHORT = _construct_matches_id_short()


def matches_id_short(text: str) -> bool:
    """Check that :paramref:`text` is a valid short ID."""
    return _REGEX_MATCHES_ID_SHORT.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_version_type() -> Pattern[str]:
    pattern = "^(0|[1-9][0-9]*)$"

    return re.compile(pattern)


_REGEX_MATCHES_VERSION_TYPE = _construct_matches_version_type()


def matches_version_type(text: str) -> bool:
    """Check that :paramref:`text` is a valid version string."""
    return _REGEX_MATCHES_VERSION_TYPE.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_revision_type() -> Pattern[str]:
    pattern = "^(0|[1-9][0-9]*)$"

    return re.compile(pattern)


_REGEX_MATCHES_REVISION_TYPE = _construct_matches_revision_type()


def matches_revision_type(text: str) -> bool:
    """Check that :paramref:`text` is a valid revision string."""
    return _REGEX_MATCHES_REVISION_TYPE.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_date_time_utc() -> Pattern[str]:
    digit = "[0-9]"
    year_frag = f"-?(([1-9]{digit}{digit}{digit}+)|(0{digit}{digit}{digit}))"
    month_frag = "((0[1-9])|(1[0-2]))"
    day_frag = f"((0[1-9])|([12]{digit})|(3[01]))"
    hour_frag = f"(([01]{digit})|(2[0-3]))"
    minute_frag = f"[0-5]{digit}"
    second_frag = f"([0-5]{digit})(\\.{digit}+)?"
    end_of_day_frag = "24:00:00(\\.0+)?"
    timezone_frag = "(Z|\\+00:00|-00:00)"
    date_time_lexical_rep = f"{year_frag}-{month_frag}-{day_frag}T(({hour_frag}:{minute_frag}:{second_frag})|{end_of_day_frag}){timezone_frag}"
    pattern = f"^{date_time_lexical_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_DATE_TIME_UTC = _construct_matches_xs_date_time_utc()


def matches_xs_date_time_utc(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:dateTime``.

    The time zone must be fixed to UTC. We verify only that the ``text`` matches
    a pre-defined pattern. We *do not* verify that the day of month is
    correct nor do we check for leap seconds.

    See: https://www.w3.org/TR/xmlschema-2/#dateTime

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_DATE_TIME_UTC.match(text) is not None


def is_xs_date_time_utc(value: str) -> bool:
    """
    Check that :paramref:`value` is a ``xs:dateTime`` with
    the time zone set to UTC.
    """
    if not matches_xs_date_time_utc(value):
        return False

    date, _ = value.split("T")
    return is_xs_date(date)


# noinspection SpellCheckingInspection
def _construct_matches_mime_type() -> Pattern[str]:
    tchar = "[!#$%&'*+\\-.^_`|~0-9a-zA-Z]"
    token = f"({tchar})+"
    type = f"{token}"
    subtype = f"{token}"
    ows = "[ \\t]*"
    obs_text = "[\\x80-\\xff]"
    qd_text = f"([\\t !#-\\[\\]-~]|{obs_text})"
    quoted_pair = f"\\\\([\\t !-~]|{obs_text})"
    quoted_string = f'"({qd_text}|{quoted_pair})*"'
    parameter = f"{token}=({token}|{quoted_string})"
    media_type = f"^{type}/{subtype}({ows};{ows}{parameter})*$"

    return re.compile(media_type)


_REGEX_MATCHES_MIME_TYPE = _construct_matches_mime_type()


def matches_mime_type(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of MIME type.

    The definition has been taken from:
    https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1,
    https://www.rfc-editor.org/rfc/rfc7230#section-3.2.3 and
    https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6.

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_MIME_TYPE.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_rfc_2396() -> Pattern[str]:
    alphanum = "[a-zA-Z0-9]"
    mark = "[-_.!~*'()]"
    unreserved = f"({alphanum}|{mark})"
    hex = "([0-9]|[aA]|[bB]|[cC]|[dD]|[eE]|[fF]|[aA]|[bB]|[cC]|[dD]|[eE]|[fF])"
    escaped = f"%{hex}{hex}"
    pchar = f"({unreserved}|{escaped}|[:@&=+$,])"
    param = f"({pchar})*"
    segment = f"({pchar})*(;{param})*"
    path_segments = f"{segment}(/{segment})*"
    abs_path = f"/{path_segments}"
    scheme = "[a-zA-Z][a-zA-Z0-9+\\-.]*"
    userinfo = f"({unreserved}|{escaped}|[;:&=+$,])*"
    domainlabel = f"({alphanum}|{alphanum}({alphanum}|-)*{alphanum})"
    toplabel = f"([a-zA-Z]|[a-zA-Z]({alphanum}|-)*{alphanum})"
    hostname = f"({domainlabel}\\.)*{toplabel}(\\.)?"
    ipv4address = "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"
    host = f"({hostname}|{ipv4address})"
    port = "[0-9]*"
    hostport = f"{host}(:{port})?"
    server = f"(({userinfo}@)?{hostport})?"
    reg_name = f"({unreserved}|{escaped}|[$,;:@&=+])+"
    authority = f"({server}|{reg_name})"
    net_path = f"//{authority}({abs_path})?"
    reserved = "[;/?:@&=+$,]"
    uric = f"({reserved}|{unreserved}|{escaped})"
    query = f"({uric})*"
    hier_part = f"({net_path}|{abs_path})(\\?{query})?"
    uric_no_slash = f"({unreserved}|{escaped}|[;?:@&=+$,])"
    opaque_part = f"{uric_no_slash}({uric})*"
    absoluteuri = f"{scheme}:({hier_part}|{opaque_part})"
    fragment = f"({uric})*"
    rel_segment = f"({unreserved}|{escaped}|[;@&=+$,])+"
    rel_path = f"{rel_segment}({abs_path})?"
    relativeuri = f"({net_path}|{abs_path}|{rel_path})(\\?{query})?"
    uri_reference = f"^({absoluteuri}|{relativeuri})?(#{fragment})?$"

    return re.compile(uri_reference)


_REGEX_MATCHES_RFC_2396 = _construct_matches_rfc_2396()


def matches_rfc_2396(text: str) -> bool:
    """
    Check that :paramref:`text` matches to the URI pattern defined in RFC 2396

    The definition has been taken from:
    https://datatracker.ietf.org/doc/html/rfc2396

    Note that RFX 2396 alone is not enough for specifying ``xs:anyURI`` for
    XSD version 1.0, as that specifies URI together with the amendment of
    RFC 2732.

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_RFC_2396.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_bcp_47() -> Pattern[str]:
    alphanum = "[a-zA-Z0-9]"
    singleton = "[0-9A-WY-Za-wy-z]"
    extension = f"{singleton}(-({alphanum}){{2,8}})+"
    extlang = "[a-zA-Z]{3}(-[a-zA-Z]{3}){0,2}"
    irregular = "(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)"
    regular = "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)"
    grandfathered = f"({irregular}|{regular})"
    language = f"([a-zA-Z]{{2,3}}(-{extlang})?|[a-zA-Z]{{4}}|[a-zA-Z]{{5,8}})"
    script = "[a-zA-Z]{4}"
    region = "([a-zA-Z]{2}|[0-9]{3})"
    variant = f"(({alphanum}){{5,8}}|[0-9]({alphanum}){{3}})"
    privateuse = f"[xX](-({alphanum}){{1,8}})+"
    langtag = f"{language}(-{script})?(-{region})?(-{variant})*(-{extension})*(-{privateuse})?"
    language_tag = f"({langtag}|{privateuse}|{grandfathered})"
    pattern = f"^{language_tag}$"

    return re.compile(pattern)


_REGEX_MATCHES_BCP_47 = _construct_matches_bcp_47()


def matches_bcp_47(text: str) -> bool:
    """
    Check that :paramref:`text` is a valid BCP 47 language tag.

    See: https://en.wikipedia.org/wiki/IETF_language_tag
    """
    return _REGEX_MATCHES_BCP_47.match(text) is not None


def lang_strings_have_unique_languages(
    lang_strings: Iterable[aas_types.AbstractLangString],
) -> bool:
    """
    Check that :paramref:`lang_strings` are specified each for a unique
    language.
    """
    language_set = set()  # type: Set[str]
    for lang_string in lang_strings:
        if lang_string.language in language_set:
            return False

        language_set.add(lang_string.language)

    return True


def qualifier_types_are_unique(qualifiers: Iterable[aas_types.Qualifier]) -> bool:
    """
    Check that there are no duplicate
    :py:attr:`.types.Qualifier.type`'s
    in the :paramref:`qualifiers`.
    """
    type_set = set()  # type: Set[str]
    for qualifier in qualifiers:
        if qualifier.type in type_set:
            return False

        type_set.add(qualifier.type)

    return True


# noinspection SpellCheckingInspection
def _construct_matches_xml_serializable_string() -> Pattern[str]:
    pattern = "^[\\x09\\x0a\\x0d\\x20-\\ud7ff\\ue000-\\ufffd\\U00010000-\\U0010ffff]*$"

    return re.compile(pattern)


_REGEX_MATCHES_XML_SERIALIZABLE_STRING = _construct_matches_xml_serializable_string()


def matches_xml_serializable_string(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of the Constraint AASd-130.

    Ensures that encoding is possible and interoperability between different
    serializations is possible.

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XML_SERIALIZABLE_STRING.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_any_uri() -> Pattern[str]:
    scheme = "[a-zA-Z][a-zA-Z0-9+\\-.]*"
    ucschar = "[\\xa0-\\ud7ff\\uf900-\\ufdcf\\ufdf0-\\uffef\\U00010000-\\U0001fffd\\U00020000-\\U0002fffd\\U00030000-\\U0003fffd\\U00040000-\\U0004fffd\\U00050000-\\U0005fffd\\U00060000-\\U0006fffd\\U00070000-\\U0007fffd\\U00080000-\\U0008fffd\\U00090000-\\U0009fffd\\U000a0000-\\U000afffd\\U000b0000-\\U000bfffd\\U000c0000-\\U000cfffd\\U000d0000-\\U000dfffd\\U000e1000-\\U000efffd]"
    iunreserved = f"([a-zA-Z0-9\\-._~]|{ucschar})"
    pct_encoded = "%[0-9A-Fa-f][0-9A-Fa-f]"
    sub_delims = "[!$&'()*+,;=]"
    iuserinfo = f"({iunreserved}|{pct_encoded}|{sub_delims}|:)*"
    h16 = "[0-9A-Fa-f]{1,4}"
    dec_octet = "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
    ipv4address = f"{dec_octet}\\.{dec_octet}\\.{dec_octet}\\.{dec_octet}"
    ls32 = f"({h16}:{h16}|{ipv4address})"
    ipv6address = f"(({h16}:){{6}}{ls32}|::({h16}:){{5}}{ls32}|({h16})?::({h16}:){{4}}{ls32}|(({h16}:)?{h16})?::({h16}:){{3}}{ls32}|(({h16}:){{0,2}}{h16})?::({h16}:){{2}}{ls32}|(({h16}:){{0,3}}{h16})?::{h16}:{ls32}|(({h16}:){{0,4}}{h16})?::{ls32}|(({h16}:){{0,5}}{h16})?::{h16}|(({h16}:){{0,6}}{h16})?::)"
    unreserved = "[a-zA-Z0-9\\-._~]"
    ipvfuture = f"[vV][0-9A-Fa-f]+\\.({unreserved}|{sub_delims}|:)+"
    ip_literal = f"\\[({ipv6address}|{ipvfuture})\\]"
    ireg_name = f"({iunreserved}|{pct_encoded}|{sub_delims})*"
    ihost = f"({ip_literal}|{ipv4address}|{ireg_name})"
    port = "[0-9]*"
    iauthority = f"({iuserinfo}@)?{ihost}(:{port})?"
    ipchar = f"({iunreserved}|{pct_encoded}|{sub_delims}|[:@])"
    isegment = f"({ipchar})*"
    ipath_abempty = f"(/{isegment})*"
    isegment_nz = f"({ipchar})+"
    ipath_absolute = f"/({isegment_nz}(/{isegment})*)?"
    ipath_rootless = f"{isegment_nz}(/{isegment})*"
    ipath_empty = f"({ipchar}){{0}}"
    ihier_part = f"(//{iauthority}{ipath_abempty}|{ipath_absolute}|{ipath_rootless}|{ipath_empty})"
    iprivate = "[\\ue000-\\uf8ff\\U000f0000-\\U000ffffd\\U00100000-\\U0010fffd]"
    iquery = f"({ipchar}|{iprivate}|[/?])*"
    ifragment = f"({ipchar}|[/?])*"
    isegment_nz_nc = f"({iunreserved}|{pct_encoded}|{sub_delims}|@)+"
    ipath_noscheme = f"{isegment_nz_nc}(/{isegment})*"
    irelative_part = f"(//{iauthority}{ipath_abempty}|{ipath_absolute}|{ipath_noscheme}|{ipath_empty})"
    irelative_ref = f"{irelative_part}(\\?{iquery})?(#{ifragment})?"
    iri = f"{scheme}:{ihier_part}(\\?{iquery})?(#{ifragment})?"
    iri_reference = f"({iri}|{irelative_ref})"
    pattern = f"^{iri_reference}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_ANY_URI = _construct_matches_xs_any_uri()


def matches_xs_any_uri(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:anyURI``.

    See: https://www.w3.org/TR/xmlschema-2/#anyURI and
    https://datatracker.ietf.org/doc/html/rfc3987

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_ANY_URI.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_base_64_binary() -> Pattern[str]:
    b04_char = "[AQgw]"
    b04 = f"{b04_char}\\x20?"
    b16_char = "[AEIMQUYcgkosw048]"
    b16 = f"{b16_char}\\x20?"
    b64_char = "[A-Za-z0-9+/]"
    b64 = f"{b64_char}\\x20?"
    b64quad = f"({b64}{b64}{b64}{b64})"
    b64_final_quad = f"({b64}{b64}{b64}{b64_char})"
    padded_8 = f"{b64}{b04}= ?="
    padded_16 = f"{b64}{b64}{b16}="
    b64final = f"({b64_final_quad}|{padded_16}|{padded_8})"
    base64_binary = f"({b64quad}*{b64final})?"
    pattern = f"^{base64_binary}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_BASE_64_BINARY = _construct_matches_xs_base_64_binary()


def matches_xs_base_64_binary(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:base64Binary``.

    See: https://www.w3.org/TR/xmlschema-2/#base64Binary

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_BASE_64_BINARY.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_boolean() -> Pattern[str]:
    pattern = "^(true|false|1|0)$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_BOOLEAN = _construct_matches_xs_boolean()


def matches_xs_boolean(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:boolean``.

    See: https://www.w3.org/TR/xmlschema-2/#boolean

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_BOOLEAN.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_date() -> Pattern[str]:
    digit = "[0-9]"
    year_frag = f"-?(([1-9]{digit}{digit}{digit}+)|(0{digit}{digit}{digit}))"
    month_frag = "((0[1-9])|(1[0-2]))"
    day_frag = f"((0[1-9])|([12]{digit})|(3[01]))"
    minute_frag = f"[0-5]{digit}"
    timezone_frag = f"(Z|(\\+|-)((0{digit}|1[0-3]):{minute_frag}|14:00))"
    date_lexical_rep = f"{year_frag}-{month_frag}-{day_frag}{timezone_frag}?"
    pattern = f"^{date_lexical_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_DATE = _construct_matches_xs_date()


def matches_xs_date(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:date``.

    See: https://www.w3.org/TR/xmlschema-2/#date

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_DATE.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_date_time() -> Pattern[str]:
    digit = "[0-9]"
    year_frag = f"-?(([1-9]{digit}{digit}{digit}+)|(0{digit}{digit}{digit}))"
    month_frag = "((0[1-9])|(1[0-2]))"
    day_frag = f"((0[1-9])|([12]{digit})|(3[01]))"
    hour_frag = f"(([01]{digit})|(2[0-3]))"
    minute_frag = f"[0-5]{digit}"
    second_frag = f"([0-5]{digit})(\\.{digit}+)?"
    end_of_day_frag = "24:00:00(\\.0+)?"
    timezone_frag = f"(Z|(\\+|-)((0{digit}|1[0-3]):{minute_frag}|14:00))"
    date_time_lexical_rep = f"{year_frag}-{month_frag}-{day_frag}T(({hour_frag}:{minute_frag}:{second_frag})|{end_of_day_frag}){timezone_frag}?"
    pattern = f"^{date_time_lexical_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_DATE_TIME = _construct_matches_xs_date_time()


def matches_xs_date_time(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:dateTime``.

    See: https://www.w3.org/TR/xmlschema-2/#dateTime

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_DATE_TIME.match(text) is not None


def is_xs_date_time(value: str) -> bool:
    """
    Check that :paramref:`value` is a ``xs:dateTime`` with
    the time zone set to UTC.
    """
    if not matches_xs_date_time(value):
        return False

    date, _ = value.split("T")
    return is_xs_date(date)


# noinspection SpellCheckingInspection
def _construct_matches_xs_decimal() -> Pattern[str]:
    digit = "[0-9]"
    unsigned_no_decimal_pt_numeral = f"{digit}+"
    no_decimal_pt_numeral = f"(\\+|-)?{unsigned_no_decimal_pt_numeral}"
    frac_frag = f"{digit}+"
    unsigned_decimal_pt_numeral = (
        f"({unsigned_no_decimal_pt_numeral}\\.{frac_frag}|\\.{frac_frag})"
    )
    decimal_pt_numeral = f"(\\+|-)?{unsigned_decimal_pt_numeral}"
    decimal_lexical_rep = f"({decimal_pt_numeral}|{no_decimal_pt_numeral})"
    pattern = f"^{decimal_lexical_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_DECIMAL = _construct_matches_xs_decimal()


def matches_xs_decimal(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:decimal``.

    See: https://www.w3.org/TR/xmlschema-2/#decimal

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_DECIMAL.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_double() -> Pattern[str]:
    double_rep = (
        "((\\+|-)?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([Ee](\\+|-)?[0-9]+)?|-?INF|NaN)"
    )
    pattern = f"^{double_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_DOUBLE = _construct_matches_xs_double()


def matches_xs_double(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:double``.

    See: https://www.w3.org/TR/xmlschema-2/#double

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_DOUBLE.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_duration() -> Pattern[str]:
    duration_rep = "-?P((([0-9]+Y([0-9]+M)?([0-9]+D)?|([0-9]+M)([0-9]+D)?|([0-9]+D))(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S)))?)|(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S))))"
    pattern = f"^{duration_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_DURATION = _construct_matches_xs_duration()


def matches_xs_duration(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:duration``.

    See: https://www.w3.org/TR/xmlschema-2/#duration

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_DURATION.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_float() -> Pattern[str]:
    float_rep = (
        "((\\+|-)?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([Ee](\\+|-)?[0-9]+)?|-?INF|NaN)"
    )
    pattern = f"^{float_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_FLOAT = _construct_matches_xs_float()


def matches_xs_float(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:float``.

    See: https://www.w3.org/TR/xmlschema-2/#float

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_FLOAT.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_g_day() -> Pattern[str]:
    g_day_lexical_rep = (
        "---(0[1-9]|[12][0-9]|3[01])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
    )
    pattern = f"^{g_day_lexical_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_G_DAY = _construct_matches_xs_g_day()


def matches_xs_g_day(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:gDay``.

    See: https://www.w3.org/TR/xmlschema-2/#gDay

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_G_DAY.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_g_month() -> Pattern[str]:
    g_month_lexical_rep = (
        "--(0[1-9]|1[0-2])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
    )
    pattern = f"^{g_month_lexical_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_G_MONTH = _construct_matches_xs_g_month()


def matches_xs_g_month(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:gMonth``.

    See: https://www.w3.org/TR/xmlschema-2/#gMonth

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_G_MONTH.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_g_month_day() -> Pattern[str]:
    g_month_day_rep = "--(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
    pattern = f"^{g_month_day_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_G_MONTH_DAY = _construct_matches_xs_g_month_day()


def matches_xs_g_month_day(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:gMonthDay``.

    See: https://www.w3.org/TR/xmlschema-2/#gMonthDay

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_G_MONTH_DAY.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_g_year() -> Pattern[str]:
    g_year_rep = (
        "-?([1-9][0-9]{3,}|0[0-9]{3})(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
    )
    pattern = f"^{g_year_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_G_YEAR = _construct_matches_xs_g_year()


def matches_xs_g_year(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:gYear``.

    See: https://www.w3.org/TR/xmlschema-2/#gYear

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_G_YEAR.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_g_year_month() -> Pattern[str]:
    g_year_month_rep = "-?([1-9][0-9]{3,}|0[0-9]{3})-(0[1-9]|1[0-2])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
    pattern = f"^{g_year_month_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_G_YEAR_MONTH = _construct_matches_xs_g_year_month()


def matches_xs_g_year_month(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:gYearMonth``.

    See: https://www.w3.org/TR/xmlschema-2/#gYearMonth

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_G_YEAR_MONTH.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_hex_binary() -> Pattern[str]:
    hex_binary = "([0-9a-fA-F]{2})*"
    pattern = f"^{hex_binary}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_HEX_BINARY = _construct_matches_xs_hex_binary()


def matches_xs_hex_binary(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:hexBinary``.

    See: https://www.w3.org/TR/xmlschema-2/#hexBinary

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_HEX_BINARY.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_time() -> Pattern[str]:
    time_rep = "(([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?|(24:00:00(\\.0+)?))(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
    pattern = f"^{time_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_TIME = _construct_matches_xs_time()


def matches_xs_time(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:time``.

    See: https://www.w3.org/TR/xmlschema-2/#time

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_TIME.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_integer() -> Pattern[str]:
    integer_rep = "[-+]?[0-9]+"
    pattern = f"^{integer_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_INTEGER = _construct_matches_xs_integer()


def matches_xs_integer(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:integer``.

    See: https://www.w3.org/TR/xmlschema-2/#integer

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_INTEGER.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_long() -> Pattern[str]:
    long_rep = "[-+]?0*[0-9]{1,20}"
    pattern = f"^{long_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_LONG = _construct_matches_xs_long()


def matches_xs_long(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:long``.

    See: https://www.w3.org/TR/xmlschema-2/#long

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_LONG.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_int() -> Pattern[str]:
    int_rep = "[-+]?0*[0-9]{1,10}"
    pattern = f"^{int_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_INT = _construct_matches_xs_int()


def matches_xs_int(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:int``.

    See: https://www.w3.org/TR/xmlschema-2/#int

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_INT.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_short() -> Pattern[str]:
    short_rep = "[-+]?0*[0-9]{1,5}"
    pattern = f"^{short_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_SHORT = _construct_matches_xs_short()


def matches_xs_short(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:short``.

    See: https://www.w3.org/TR/xmlschema-2/#short

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_SHORT.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_byte() -> Pattern[str]:
    byte_rep = "[-+]?0*[0-9]{1,3}"
    pattern = f"^{byte_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_BYTE = _construct_matches_xs_byte()


def matches_xs_byte(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:byte``.

    See: https://www.w3.org/TR/xmlschema-2/#byte

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_BYTE.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_non_negative_integer() -> Pattern[str]:
    non_negative_integer_rep = "(-0|\\+?[0-9]+)"
    pattern = f"^{non_negative_integer_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_NON_NEGATIVE_INTEGER = _construct_matches_xs_non_negative_integer()


def matches_xs_non_negative_integer(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:nonNegativeInteger``.

    See: https://www.w3.org/TR/xmlschema-2/#nonNegativeInteger

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_NON_NEGATIVE_INTEGER.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_positive_integer() -> Pattern[str]:
    positive_integer_rep = "\\+?0*[1-9][0-9]*"
    pattern = f"^{positive_integer_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_POSITIVE_INTEGER = _construct_matches_xs_positive_integer()


def matches_xs_positive_integer(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:positiveInteger``.

    See: https://www.w3.org/TR/xmlschema-2/#positiveInteger

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_POSITIVE_INTEGER.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_long() -> Pattern[str]:
    unsigned_long_rep = "(-0|\\+?0*[0-9]{1,20})"
    pattern = f"^{unsigned_long_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_UNSIGNED_LONG = _construct_matches_xs_unsigned_long()


def matches_xs_unsigned_long(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedLong``.

    See: https://www.w3.org/TR/xmlschema-2/#unsignedLong

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_UNSIGNED_LONG.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_int() -> Pattern[str]:
    unsigned_int_rep = "(-0|\\+?0*[0-9]{1,10})"
    pattern = f"^{unsigned_int_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_UNSIGNED_INT = _construct_matches_xs_unsigned_int()


def matches_xs_unsigned_int(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedInt``.

    See: https://www.w3.org/TR/xmlschema-2/#unsignedInt

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_UNSIGNED_INT.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_short() -> Pattern[str]:
    unsigned_short_rep = "(-0|\\+?0*[0-9]{1,5})"
    pattern = f"^{unsigned_short_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_UNSIGNED_SHORT = _construct_matches_xs_unsigned_short()


def matches_xs_unsigned_short(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedShort``.

    See: https://www.w3.org/TR/xmlschema-2/#unsignedShort

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_UNSIGNED_SHORT.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_byte() -> Pattern[str]:
    unsigned_byte_rep = "(-0|\\+?0*[0-9]{1,3})"
    pattern = f"^{unsigned_byte_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_UNSIGNED_BYTE = _construct_matches_xs_unsigned_byte()


def matches_xs_unsigned_byte(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedByte``.

    See: https://www.w3.org/TR/xmlschema-2/#unsignedByte

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_UNSIGNED_BYTE.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_non_positive_integer() -> Pattern[str]:
    non_positive_integer_rep = "(\\+0|0|-[0-9]+)"
    pattern = f"^{non_positive_integer_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_NON_POSITIVE_INTEGER = _construct_matches_xs_non_positive_integer()


def matches_xs_non_positive_integer(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:nonPositiveInteger``.

    See: https://www.w3.org/TR/xmlschema-2/#nonPositiveInteger

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_NON_POSITIVE_INTEGER.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_negative_integer() -> Pattern[str]:
    negative_integer_rep = "(-0*[1-9][0-9]*)"
    pattern = f"^{negative_integer_rep}$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_NEGATIVE_INTEGER = _construct_matches_xs_negative_integer()


def matches_xs_negative_integer(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:negativeInteger``.

    See: https://www.w3.org/TR/xmlschema-2/#negativeInteger

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_NEGATIVE_INTEGER.match(text) is not None


# noinspection SpellCheckingInspection
def _construct_matches_xs_string() -> Pattern[str]:
    pattern = "^[\\x09\\x0a\\x0d\\x20-\\ud7ff\\ue000-\\ufffd\\U00010000-\\U0010ffff]*$"

    return re.compile(pattern)


_REGEX_MATCHES_XS_STRING = _construct_matches_xs_string()


def matches_xs_string(text: str) -> bool:
    """
    Check that :paramref:`text` conforms to the pattern of an ``xs:string``.

    See: https://www.w3.org/TR/xmlschema-2/#string

    :param text: Text to be checked
    :return:
        True if the :paramref:`text` conforms to the pattern
    """
    return _REGEX_MATCHES_XS_STRING.match(text) is not None


def _is_leap_year(year: int) -> bool:
    """
    Check if :paramref:`year` is a leap year.

    >>> _is_leap_year(2016)
    True

    >>> _is_leap_year(1700)
    False

    >>> _is_leap_year(1600)
    True

    >>> _is_leap_year(2000)
    True
    """
    # We consider the years B.C. to be one-off.
    #
    # See the note at: https://www.w3.org/TR/xmlschema-2/#dateTime:
    # "'-0001' is the lexical representation of the year 1 Before Common Era
    # (1 BCE, sometimes written "1 BC")."
    #
    # Hence, -1 year in XML is 1 BCE, which is 0 year in astronomical years.
    if year < 0:
        year = abs(year) - 1

    # See: https://en.wikipedia.org/wiki/Leap_year#Algorithm
    if year % 4 > 0:
        return False

    if year % 100 > 0:
        return True

    if year % 400 > 0:
        return False

    return True


_DAYS_IN_MONTH: Mapping[int, int] = {
    1: 31,
    # Please use _is_leap_year if you need to check
    # whether a concrete February has 28 or 29 days.
    2: 29,
    3: 31,
    4: 30,
    5: 31,
    6: 30,
    7: 31,
    8: 31,
    9: 30,
    10: 31,
    11: 30,
    12: 31,
}


_DATE_PREFIX_RE = re.compile(r"^(-?[0-9]+)-([0-9]{2})-([0-9]{2})")


def is_xs_date(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:date``."""
    if not matches_xs_date(value):
        return False

    # NOTE (mristin, 2022-11-23):
    # We can not use :py:func:`datetime.datetime.strptime` as it does not
    # handle years below 1000 correctly on Windows (*e.g.*, ``-999-01-01``).

    # NOTE (mristin, 2022-10-30):
    # We need to match the prefix as zone offsets are allowed in the dates. Optimally,
    # we would re-use the pattern matching from :py:func`matches_xs_date`, but this
    # would make the code generation and constraint inference for schemas much more
    # difficult. Hence, we sacrifice the efficiency a bit for the clearer code & code
    # generation.
    match = _DATE_PREFIX_RE.match(value)
    assert match is not None

    year = int(match.group(1))
    month = int(match.group(2))
    day = int(match.group(3))

    # We do not accept year zero,
    # see the note at: https://www.w3.org/TR/xmlschema-2/#dateTime
    if year == 0:
        return False

    if day <= 0:
        return False

    if month <= 0 or month >= 13:
        return False

    if month == 2:
        max_days = 29 if _is_leap_year(year) else 28
    else:
        max_days = _DAYS_IN_MONTH[month]

    if day > max_days:
        return False

    return True


def is_xs_double(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:double``."""
    # We need to check explicitly for the regular expression since
    # ``float(.)`` is too permissive. For example,
    # it accepts "nan" although only "NaN" is valid.
    # See: https://www.w3.org/TR/xmlschema-2/#double
    if not matches_xs_double(value):
        return False

    converted = float(value)

    # Check that the value is either "INF" or "-INF".
    # Otherwise, the value is a decimal which is too big
    # to be represented as a double-precision floating point
    # number.
    #
    # Python simply rounds up/down to ``INF`` and ``-INF``,
    # respectively, if the number is too large.
    # For example: ``float("1e400") == math.inf``
    if math.isinf(converted) and value != "INF" and value != "-INF":
        return False

    return True


def is_xs_float(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:float``."""
    # We need to check explicitly for the regular expression since
    # ``float(.)`` is too permissive. For example,
    # it accepts "nan" although only "NaN" is valid.
    # See: https://www.w3.org/TR/xmlschema-2/#double
    if not matches_xs_float(value):
        return False

    converted = float(value)

    # Check that the value is either "INF" or "-INF".
    # Otherwise, the value is a decimal which is too big
    # to be represented as a single-precision floating point
    # number.
    #
    # Python simply rounds up/down to ``INF`` and ``-INF``,
    # respectively, if the number is too large.
    # For example: ``float("1e400") == math.inf``
    if math.isinf(converted) and value != "INF" and value != "-INF":
        return False

    # Python uses double-precision floating point numbers. Since
    # we check for a single-precision one, we have to explicitly
    # see if the number is within a range of a single-precision
    # floating point numbers.
    try:
        _ = struct.pack(">f", converted)
    except OverflowError:
        return False

    return True


def is_xs_g_month_day(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:gMonthDay``."""
    if not matches_xs_g_month_day(value):
        return False

    month = int(value[2:4])
    day = int(value[5:7])

    max_days = _DAYS_IN_MONTH[month]
    return day <= max_days


def is_xs_long(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:long``."""
    if not matches_xs_long(value):
        return False

    converted = int(value)
    return -9223372036854775808 <= converted <= 9223372036854775807


def is_xs_int(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:int``."""
    if not matches_xs_int(value):
        return False

    converted = int(value)
    return -2147483648 <= converted <= 2147483647


def is_xs_short(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:short``."""
    if not matches_xs_short(value):
        return False

    converted = int(value)
    return -32768 <= converted <= 32767


def is_xs_byte(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:byte``."""
    if not matches_xs_byte(value):
        return False

    converted = int(value)
    return -128 <= converted <= 127


def is_xs_unsigned_long(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:unsignedLong``."""
    if not matches_xs_unsigned_long(value):
        return False

    converted = int(value)
    return 0 <= converted <= 18446744073709551615


def is_xs_unsigned_int(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:unsignedInt``."""
    if not matches_xs_unsigned_int(value):
        return False

    converted = int(value)
    return 0 <= converted <= 4294967295


def is_xs_unsigned_short(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:unsignedShort``."""
    if not matches_xs_unsigned_short(value):
        return False

    converted = int(value)
    return 0 <= converted <= 65535


def is_xs_unsigned_byte(value: str) -> bool:
    """Check that :paramref:`value` is a valid ``xs:unsignedByte``."""
    if not matches_xs_unsigned_byte(value):
        return False

    converted = int(value)
    return 0 <= converted <= 255


_DATA_TYPE_DEF_XSD_TO_VALUE_CONSISTENCY: Mapping[
    aas_types.DataTypeDefXSD, Callable[[str], bool]
] = {
    aas_types.DataTypeDefXSD.ANY_URI: matches_xs_any_uri,
    aas_types.DataTypeDefXSD.BASE_64_BINARY: matches_xs_base_64_binary,
    aas_types.DataTypeDefXSD.BOOLEAN: matches_xs_boolean,
    aas_types.DataTypeDefXSD.BYTE: is_xs_byte,
    aas_types.DataTypeDefXSD.DATE: is_xs_date,
    aas_types.DataTypeDefXSD.DATE_TIME: is_xs_date_time,
    aas_types.DataTypeDefXSD.DECIMAL: matches_xs_decimal,
    aas_types.DataTypeDefXSD.DOUBLE: is_xs_double,
    aas_types.DataTypeDefXSD.DURATION: matches_xs_duration,
    aas_types.DataTypeDefXSD.FLOAT: is_xs_float,
    aas_types.DataTypeDefXSD.G_DAY: matches_xs_g_day,
    aas_types.DataTypeDefXSD.G_MONTH: matches_xs_g_month,
    aas_types.DataTypeDefXSD.G_MONTH_DAY: is_xs_g_month_day,
    aas_types.DataTypeDefXSD.G_YEAR: matches_xs_g_year,
    aas_types.DataTypeDefXSD.G_YEAR_MONTH: matches_xs_g_year_month,
    aas_types.DataTypeDefXSD.HEX_BINARY: matches_xs_hex_binary,
    aas_types.DataTypeDefXSD.INT: is_xs_int,
    aas_types.DataTypeDefXSD.INTEGER: matches_xs_integer,
    aas_types.DataTypeDefXSD.LONG: is_xs_long,
    aas_types.DataTypeDefXSD.NEGATIVE_INTEGER: matches_xs_negative_integer,
    aas_types.DataTypeDefXSD.NON_NEGATIVE_INTEGER: matches_xs_non_negative_integer,
    aas_types.DataTypeDefXSD.NON_POSITIVE_INTEGER: matches_xs_non_positive_integer,
    aas_types.DataTypeDefXSD.POSITIVE_INTEGER: matches_xs_positive_integer,
    aas_types.DataTypeDefXSD.SHORT: is_xs_short,
    aas_types.DataTypeDefXSD.STRING: matches_xs_string,
    aas_types.DataTypeDefXSD.TIME: matches_xs_time,
    aas_types.DataTypeDefXSD.UNSIGNED_BYTE: is_xs_unsigned_byte,
    aas_types.DataTypeDefXSD.UNSIGNED_INT: is_xs_unsigned_int,
    aas_types.DataTypeDefXSD.UNSIGNED_LONG: is_xs_unsigned_long,
    aas_types.DataTypeDefXSD.UNSIGNED_SHORT: is_xs_unsigned_short,
}
assert all(
    data_type_def_xsd in _DATA_TYPE_DEF_XSD_TO_VALUE_CONSISTENCY
    for data_type_def_xsd in aas_types.DataTypeDefXSD
)


def value_consistent_with_xsd_type(
    value: str, value_type: aas_types.DataTypeDefXSD
) -> bool:
    """
    Check that :paramref:`value` is consistent with the given
    :paramref:`value_type`.
    """
    return _DATA_TYPE_DEF_XSD_TO_VALUE_CONSISTENCY[value_type](value)


def is_model_reference_to(
    reference: aas_types.Reference, expected_type: aas_types.KeyTypes
) -> bool:
    """
    Check that the target of the model reference matches the :paramref:`expected_type`.
    """
    # pylint: disable=all
    return (
        reference.type == aas_types.ReferenceTypes.MODEL_REFERENCE
        and len(reference.keys) != 0
        and reference.keys[-1].type == expected_type
    )


def is_model_reference_to_referable(reference: aas_types.Reference) -> bool:
    """
    Check that the target of the reference matches a :py:attr:`.constants.AAS_REFERABLES`.
    """
    # pylint: disable=all
    return (
        reference.type == aas_types.ReferenceTypes.MODEL_REFERENCE
        and len(reference.keys) != 0
        and (reference.keys[-1].type in aas_constants.AAS_REFERABLES)
    )


def id_shorts_are_unique(referables: Iterable[aas_types.Referable]) -> bool:
    """
    Check that all :py:attr:`.types.Referable.id_short` are unique
    among :paramref:`referables`.
    """
    id_short_set = set()  # type: Set[str]
    for referable in referables:
        if referable.id_short in id_short_set:
            return False

        if referable.id_short is not None:
            id_short_set.add(referable.id_short)

    return True


def id_shorts_of_variables_are_unique(
    input_variables: Optional[List[aas_types.OperationVariable]],
    output_variables: Optional[List[aas_types.OperationVariable]],
    inoutput_variables: Optional[List[aas_types.OperationVariable]],
) -> bool:
    """
    Check that the :py:attr:`.types.Referable.id_short`'s among all the
    :paramref:`input_variables`, :paramref:`output_variables`
    and :paramref:`inoutput_variables` are unique.
    """
    id_short_set = set()
    if input_variables is not None:
        for variable in input_variables:
            if variable.value.id_short is not None:
                if variable.value.id_short in id_short_set:
                    return False

                id_short_set.add(variable.value.id_short)
    if output_variables is not None:
        for variable in output_variables:
            if variable.value.id_short is not None:
                if variable.value.id_short in id_short_set:
                    return False

                id_short_set.add(variable.value.id_short)
    if inoutput_variables is not None:
        for variable in inoutput_variables:
            if variable.value.id_short is not None:
                if variable.value.id_short in id_short_set:
                    return False

                id_short_set.add(variable.value.id_short)
    return True


def extension_names_are_unique(extensions: Iterable[aas_types.Extension]) -> bool:
    """
    Check that all :py:attr:`.types.Extension.name` are unique
    among :paramref:`extensions`.
    """
    name_set = set()  # type: Set[str]
    for extension in extensions:
        if extension.name in name_set:
            return False

        name_set.add(extension.name)

    return True


def submodel_elements_have_identical_semantic_ids(
    elements: Iterable[aas_types.SubmodelElement],
) -> bool:
    """
    Check that all :paramref:`elements` have the identical
    :py:attr:`.types.HasSemantics.semantic_id`.
    """
    that_semantic_id = None  # type: Optional[aas_types.Reference]

    for element in elements:
        if element.semantic_id is None:
            continue

        if that_semantic_id is None:
            that_semantic_id = element.semantic_id
            continue

        this_semantic_id = element.semantic_id

        if len(that_semantic_id.keys) != len(this_semantic_id.keys):
            return False

        for this_key, that_key in zip(this_semantic_id.keys, that_semantic_id.keys):
            if this_key.value != that_key.value:
                return False

    return True


# fmt: off
_AAS_SUBMODEL_ELEMENTS_TO_TYPE: Mapping[
    aas_types.AASSubmodelElements,
    type
] = {
    aas_types.AASSubmodelElements.ANNOTATED_RELATIONSHIP_ELEMENT:
        aas_types.AnnotatedRelationshipElement,

    aas_types.AASSubmodelElements.BASIC_EVENT_ELEMENT:
        aas_types.BasicEventElement,

    aas_types.AASSubmodelElements.BLOB:
        aas_types.Blob,

    aas_types.AASSubmodelElements.CAPABILITY:
        aas_types.Capability,

    aas_types.AASSubmodelElements.DATA_ELEMENT:
        aas_types.DataElement,

    aas_types.AASSubmodelElements.ENTITY:
        aas_types.Entity,

    aas_types.AASSubmodelElements.EVENT_ELEMENT:
        aas_types.EventElement,

    aas_types.AASSubmodelElements.FILE:
        aas_types.File,

    aas_types.AASSubmodelElements.MULTI_LANGUAGE_PROPERTY:
        aas_types.MultiLanguageProperty,

    aas_types.AASSubmodelElements.OPERATION:
        aas_types.Operation,

    aas_types.AASSubmodelElements.PROPERTY:
        aas_types.Property,

    aas_types.AASSubmodelElements.RANGE:
        aas_types.Range,

    aas_types.AASSubmodelElements.REFERENCE_ELEMENT:
        aas_types.ReferenceElement,

    aas_types.AASSubmodelElements.RELATIONSHIP_ELEMENT:
        aas_types.RelationshipElement,

    aas_types.AASSubmodelElements.SUBMODEL_ELEMENT:
        aas_types.SubmodelElement,

    aas_types.AASSubmodelElements.SUBMODEL_ELEMENT_LIST:
        aas_types.SubmodelElementList,

    aas_types.AASSubmodelElements.SUBMODEL_ELEMENT_COLLECTION:
        aas_types.SubmodelElementCollection,
}
# fmt: on


def _assert_all_types_covered_in_aas_submodel_elements_to_type() -> None:
    """
    Assert that we did not miss a type in :py:attr:`_AAS_SUBMODEL_ELEMENTS_TO_TYPE`.
    """
    missing_literals = [
        literal
        for literal in aas_types.AASSubmodelElements
        if literal not in _AAS_SUBMODEL_ELEMENTS_TO_TYPE
    ]

    assert len(missing_literals) == 0, (
        f"Some literals were missed in "
        f"_AAS_SUBMODEL_ELEMENTS_TO_TYPE: {missing_literals!r}"
    )


_assert_all_types_covered_in_aas_submodel_elements_to_type()


def submodel_element_is_of_type(
    element: aas_types.SubmodelElement, expected_type: aas_types.AASSubmodelElements
) -> bool:
    """
    Check that :paramref:`element` is an instance of class corresponding
    to :paramref:`expected_type`.
    """
    # noinspection PyTypeHints
    return isinstance(element, _AAS_SUBMODEL_ELEMENTS_TO_TYPE[expected_type])


def properties_or_ranges_have_value_type(
    elements: Iterable[aas_types.SubmodelElement], value_type: aas_types.DataTypeDefXSD
) -> bool:
    """
    Check that :paramref:`elements` which are
    :py:class:`.types.Property` or :py:class:`.types.Range`
    have the given :paramref:`value_type`.
    """
    range_or_property = (aas_types.Property, aas_types.Range)
    for element in elements:
        if isinstance(element, range_or_property):
            if element.value_type is not value_type:
                return False

    return True


def reference_key_values_equal(
    that: aas_types.Reference, other: aas_types.Reference
) -> bool:
    """
    Check that the two references, :paramref:`that` and :paramref:`other`,
    are equal by comparing their :py:attr:`.types.Reference.keys`
    by :py:attr:`.types.Key.value`'s.
    """
    if len(that.keys) != len(other.keys):
        return False

    for that_key, other_key in zip(that.keys, other.keys):
        if that_key.value != other_key.value:
            return False

    return True


def data_specification_iec_61360s_for_property_or_value_have_appropriate_data_type(
    embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
    """
    Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
    is defined appropriately for all data specifications whose content is given
    as IEC 61360.
    """
    for embedded_data_specification in embedded_data_specifications:
        if isinstance(
            embedded_data_specification.data_specification_content,
            aas_types.DataSpecificationIEC61360,
        ):
            iec61360 = embedded_data_specification.data_specification_content
            if (
                iec61360.data_type is None
                or iec61360.data_type
                not in aas_constants.DATA_TYPE_IEC_61360_FOR_PROPERTY_OR_VALUE
            ):
                return False

    return True


def data_specification_iec_61360s_for_reference_have_appropriate_data_type(
    embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
    """
    Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
    is defined appropriately for all data specifications whose content is given
    as IEC 61360.
    """
    for embedded_data_specification in embedded_data_specifications:
        if isinstance(
            embedded_data_specification.data_specification_content,
            aas_types.DataSpecificationIEC61360,
        ):
            iec61360 = embedded_data_specification.data_specification_content
            if (
                iec61360.data_type is None
                or iec61360.data_type
                not in aas_constants.DATA_TYPE_IEC_61360_FOR_REFERENCE
            ):
                return False

    return True


def data_specification_iec_61360s_for_document_have_appropriate_data_type(
    embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
    """
    Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
    is defined appropriately for all data specifications whose content is given as
    IEC 61360.
    """
    for embedded_data_specification in embedded_data_specifications:
        if isinstance(
            embedded_data_specification.data_specification_content,
            aas_types.DataSpecificationIEC61360,
        ):
            iec61360 = embedded_data_specification.data_specification_content
            if (
                iec61360.data_type is None
                or iec61360.data_type
                not in aas_constants.DATA_TYPE_IEC_61360_FOR_DOCUMENT
            ):
                return False

    return True


def data_specification_iec_61360s_have_data_type(
    embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
    """
    Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
    is defined for all data specifications whose content is given as IEC 61360.
    """
    for embedded_data_specification in embedded_data_specifications:
        if isinstance(
            embedded_data_specification.data_specification_content,
            aas_types.DataSpecificationIEC61360,
        ):
            iec61360 = embedded_data_specification.data_specification_content
            if iec61360.data_type is None:
                return False

    return True


def data_specification_iec_61360s_have_value(
    embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
    """
    Check that :py:attr:`.types.DataSpecificationIEC61360.value`
    is defined for all data specifications whose content is given as IEC 61360.
    """
    for embedded_data_specification in embedded_data_specifications:
        if isinstance(
            embedded_data_specification.data_specification_content,
            aas_types.DataSpecificationIEC61360,
        ):
            iec61360 = embedded_data_specification.data_specification_content
            if iec61360.value is None:
                return False

    return True


def data_specification_iec_61360s_have_definition_at_least_in_english(
    embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
    """
    Check that :py:attr:`.types.DataSpecificationIEC61360.definition`
    is defined for all data specifications whose content is given as IEC 61360
    at least in English.
    """
    for embedded_data_specification in embedded_data_specifications:
        if isinstance(
            embedded_data_specification.data_specification_content,
            aas_types.DataSpecificationIEC61360,
        ):
            iec61360 = embedded_data_specification.data_specification_content
            if iec61360.definition is None:
                return False

            no_definition_in_english = True
            for lang_string in iec61360.definition:
                if is_bcp_47_for_english(lang_string.language):
                    no_definition_in_english = False
                    break

            if no_definition_in_english:
                return False

    return True


# noinspection SpellCheckingInspection
def _construct_is_bcp_47_for_english() -> Pattern[str]:
    pattern = "^(en|EN)(-.*)?$"

    return re.compile(pattern)


_REGEX_IS_BCP_47_FOR_ENGLISH = _construct_is_bcp_47_for_english()


def is_bcp_47_for_english(text: str) -> bool:
    """
    Check that the :paramref:`text` corresponds to a BCP47 code for english.
    """
    return _REGEX_IS_BCP_47_FOR_ENGLISH.match(text) is not None


class _Transformer(aas_types.AbstractTransformer[Iterator[Error]]):
    # noinspection PyMethodMayBeStatic
    def transform_extension(self, that: aas_types.Extension) -> Iterator[Error]:
        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.refers_to is not None) or (len(that.refers_to) >= 1)):
            yield Error("Refers-to must be either not set or have at least one item.")

        if not (
            not (that.value is not None)
            or value_consistent_with_xsd_type(that.value, that.value_type_or_default())
        ):
            yield Error("The value must match the value type.")

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, an_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        for error in verify_name_type(that.name):
            error.path._prepend(PropertySegment(that, "name"))
            yield error

        if that.value is not None:
            for error in verify_value_data_type(that.value):
                error.path._prepend(PropertySegment(that, "value"))
                yield error

        if that.refers_to is not None:
            for i, another_item in enumerate(that.refers_to):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.refers_to, i))
                    error.path._prepend(PropertySegment(that, "refers_to"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_administrative_information(
        self, that: aas_types.AdministrativeInformation
    ) -> Iterator[Error]:
        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (not (that.revision is not None) or (that.version is not None)):
            yield Error(
                "Constraint AASd-005: If version is not specified then also "
                + "revision shall be unspecified. This means, a revision "
                + "requires a version. If there is no version there is no "
                + "revision either. Revision is optional."
            )

        if that.embedded_data_specifications is not None:
            for i, an_item in enumerate(that.embedded_data_specifications):
                for error in self.transform(an_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.version is not None:
            for error in verify_version_type(that.version):
                error.path._prepend(PropertySegment(that, "version"))
                yield error

        if that.revision is not None:
            for error in verify_revision_type(that.revision):
                error.path._prepend(PropertySegment(that, "revision"))
                yield error

        if that.creator is not None:
            for error in self.transform(that.creator):
                error.path._prepend(PropertySegment(that, "creator"))
                yield error

        if that.template_id is not None:
            for error in verify_identifier(that.template_id):
                error.path._prepend(PropertySegment(that, "template_id"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_qualifier(self, that: aas_types.Qualifier) -> Iterator[Error]:
        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (
            not (that.value is not None)
            or value_consistent_with_xsd_type(that.value, that.value_type)
        ):
            yield Error(
                "Constraint AASd-020: The value shall be consistent to "
                + "the data type as defined in value type."
            )

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, an_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        for error in verify_qualifier_type(that.type):
            error.path._prepend(PropertySegment(that, "type"))
            yield error

        if that.value is not None:
            for error in verify_value_data_type(that.value):
                error.path._prepend(PropertySegment(that, "value"))
                yield error

        if that.value_id is not None:
            for error in self.transform(that.value_id):
                error.path._prepend(PropertySegment(that, "value_id"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_asset_administration_shell(
        self, that: aas_types.AssetAdministrationShell
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (not (that.submodels is not None) or (len(that.submodels) >= 1)):
            yield Error("Submodels must be either not set or have at least one item.")

        if not (
            not (that.derived_from is not None)
            or is_model_reference_to(
                that.derived_from, aas_types.KeyTypes.ASSET_ADMINISTRATION_SHELL
            )
        ):
            yield Error(
                "Derived-from must be a model reference to an asset "
                + "administration shell."
            )

        if not (
            not (that.submodels is not None)
            or (
                all(
                    is_model_reference_to(reference, aas_types.KeyTypes.SUBMODEL)
                    for reference in that.submodels
                )
            )
        ):
            yield Error("All submodels must be model references to a submodel.")

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.administration is not None:
            for error in self.transform(that.administration):
                error.path._prepend(PropertySegment(that, "administration"))
                yield error

        for error in verify_identifier(that.id):
            error.path._prepend(PropertySegment(that, "id"))
            yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_another_item in enumerate(that.embedded_data_specifications):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.derived_from is not None:
            for error in self.transform(that.derived_from):
                error.path._prepend(PropertySegment(that, "derived_from"))
                yield error

        for error in self.transform(that.asset_information):
            error.path._prepend(PropertySegment(that, "asset_information"))
            yield error

        if that.submodels is not None:
            for i, yet_yet_yet_another_item in enumerate(that.submodels):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.submodels, i))
                    error.path._prepend(PropertySegment(that, "submodels"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_asset_information(
        self, that: aas_types.AssetInformation
    ) -> Iterator[Error]:
        if not (
            not (that.specific_asset_ids is not None)
            or (
                all(
                    (
                        specific_asset_id.name != "globalAssetId"
                        or (
                            (
                                (that.global_asset_id is not None)
                                and specific_asset_id.name == "globalAssetId"
                                and specific_asset_id.value == that.global_asset_id
                            )
                        )
                    )
                    for specific_asset_id in that.specific_asset_ids
                )
            )
        ):
            yield Error(
                "Constraint AASd-116: ``globalAssetId`` is a reserved key. "
                + "If used as value for the name of specific asset ID then "
                + "the value of specific asset ID shall be identical to "
                + "the global asset ID."
            )

        if not (
            (
                (
                    (
                        (that.global_asset_id is not None)
                        or (that.specific_asset_ids is not None)
                    )
                )
                and (
                    not (that.specific_asset_ids is not None)
                    or (len(that.specific_asset_ids) >= 1)
                )
            )
        ):
            yield Error(
                "Constraint AASd-131: Either the global asset ID shall be "
                + "defined or at least one specific asset ID."
            )

        if not (
            not (that.specific_asset_ids is not None)
            or (len(that.specific_asset_ids) >= 1)
        ):
            yield Error(
                "Specific asset IDs must be either not set or have at least "
                + "one item."
            )

        if that.global_asset_id is not None:
            for error in verify_identifier(that.global_asset_id):
                error.path._prepend(PropertySegment(that, "global_asset_id"))
                yield error

        if that.specific_asset_ids is not None:
            for i, an_item in enumerate(that.specific_asset_ids):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.specific_asset_ids, i))
                    error.path._prepend(PropertySegment(that, "specific_asset_ids"))
                    yield error

        if that.asset_type is not None:
            for error in verify_identifier(that.asset_type):
                error.path._prepend(PropertySegment(that, "asset_type"))
                yield error

        if that.default_thumbnail is not None:
            for error in self.transform(that.default_thumbnail):
                error.path._prepend(PropertySegment(that, "default_thumbnail"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_resource(self, that: aas_types.Resource) -> Iterator[Error]:
        for error in verify_path_type(that.path):
            error.path._prepend(PropertySegment(that, "path"))
            yield error

        if that.content_type is not None:
            for error in verify_content_type(that.content_type):
                error.path._prepend(PropertySegment(that, "content_type"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_specific_asset_id(
        self, that: aas_types.SpecificAssetID
    ) -> Iterator[Error]:
        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (
            not (that.external_subject_id is not None)
            or (
                that.external_subject_id.type
                == aas_types.ReferenceTypes.EXTERNAL_REFERENCE
            )
        ):
            yield Error(
                "Constraint AASd-133: External subject ID shall be "
                + "an external reference."
            )

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, an_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        for error in verify_label_type(that.name):
            error.path._prepend(PropertySegment(that, "name"))
            yield error

        for error in verify_identifier(that.value):
            error.path._prepend(PropertySegment(that, "value"))
            yield error

        if that.external_subject_id is not None:
            for error in self.transform(that.external_subject_id):
                error.path._prepend(PropertySegment(that, "external_subject_id"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_submodel(self, that: aas_types.Submodel) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.submodel_elements is not None)
            or (len(that.submodel_elements) >= 1)
        ):
            yield Error(
                "Submodel elements must be either not set or have at least "
                + "one item."
            )

        if not (
            not (that.submodel_elements is not None)
            or (all(item.id_short is not None for item in that.submodel_elements))
        ):
            yield Error(
                "ID-shorts need to be defined for all the items of submodel "
                + "elements according to AASd-117 (ID-short of Referables not "
                + "being a direct child of a Submodel element list shall be "
                + "specified)."
            )

        if not (
            not (that.submodel_elements is not None)
            or id_shorts_are_unique(that.submodel_elements)
        ):
            yield Error(
                "Constraint AASd-022: ID-short of non-identifiable "
                + "referables within the same name space shall be unique "
                + "(case-sensitive)."
            )

        if not (
            not (that.submodel_elements is not None)
            or (
                not (that.kind_or_default() != aas_types.ModellingKind.TEMPLATE)
                or (
                    all(
                        not (submodel_element.qualifiers is not None)
                        or (
                            all(
                                qualifier.kind_or_default()
                                != aas_types.QualifierKind.TEMPLATE_QUALIFIER
                                for qualifier in submodel_element.qualifiers
                            )
                        )
                        for submodel_element in that.submodel_elements
                    )
                )
            )
        ):
            yield Error(
                "Constraint AASd-129: If any qualifier kind value of "
                + "a Submodel element qualifier (attribute qualifier inherited "
                + "via Qualifiable) is equal to Template Qualifier then "
                + "the submodel element shall be part of a submodel template, "
                + "i.e. a Submodel with submodel kind (attribute kind "
                + "inherited via Has-Kind) value is equal to Template."
            )

        if not (
            not (that.qualifiers is not None)
            or (
                not (
                    any(
                        qualifier.kind_or_default()
                        == aas_types.QualifierKind.TEMPLATE_QUALIFIER
                        for qualifier in that.qualifiers
                    )
                )
                or (that.kind_or_default() == aas_types.ModellingKind.TEMPLATE)
            )
        ):
            yield Error(
                "Constraint AASd-119: If any qualifier kind value of "
                + "a qualifiable qualifier is equal to template qualifier and "
                + "the qualified element has kind then the qualified element "
                + "shall be of kind template."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.administration is not None:
            for error in self.transform(that.administration):
                error.path._prepend(PropertySegment(that, "administration"))
                yield error

        for error in verify_identifier(that.id):
            error.path._prepend(PropertySegment(that, "id"))
            yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.submodel_elements is not None:
            for i, yet_yet_yet_yet_yet_another_item in enumerate(
                that.submodel_elements
            ):
                for error in self.transform(yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.submodel_elements, i))
                    error.path._prepend(PropertySegment(that, "submodel_elements"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_relationship_element(
        self, that: aas_types.RelationshipElement
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        for error in self.transform(that.first):
            error.path._prepend(PropertySegment(that, "first"))
            yield error

        for error in self.transform(that.second):
            error.path._prepend(PropertySegment(that, "second"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_submodel_element_list(
        self, that: aas_types.SubmodelElementList
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (not (that.value is not None) or (len(that.value) >= 1)):
            yield Error("Value must be either not set or have at least one item.")

        if not (
            not (
                (
                    (that.value is not None)
                    and (that.semantic_id_list_element is not None)
                )
            )
            or (
                all(
                    not (child.semantic_id is not None)
                    or reference_key_values_equal(
                        child.semantic_id, that.semantic_id_list_element
                    )
                    for child in that.value
                )
            )
        ):
            yield Error(
                "Constraint AASd-107: If a first level child element has "
                + "a semantic ID it shall be identical to semantic ID list "
                + "element."
            )

        if not (
            not (that.value is not None)
            or submodel_elements_have_identical_semantic_ids(that.value)
        ):
            yield Error(
                "Constraint AASd-114: If two first level child elements have "
                + "a semantic ID then they shall be identical."
            )

        if not (
            not (that.value is not None)
            or (
                all(
                    submodel_element_is_of_type(element, that.type_value_list_element)
                    for element in that.value
                )
            )
        ):
            yield Error(
                "Constraint AASd-108: All first level child elements shall "
                + "have the same submodel element type as specified in type "
                + "value list element."
            )

        if not (
            not (
                (
                    that.type_value_list_element
                    == aas_types.AASSubmodelElements.PROPERTY
                    or that.type_value_list_element
                    == aas_types.AASSubmodelElements.RANGE
                )
            )
            or (
                (
                    (that.value_type_list_element is not None)
                    and (
                        (
                            (that.value is None)
                            or properties_or_ranges_have_value_type(
                                that.value, that.value_type_list_element
                            )
                        )
                    )
                )
            )
        ):
            yield Error(
                "Constraint AASd-109: If type value list element is equal to "
                + "Property or Range value type list element shall be set and "
                + "all first level child elements shall have the value type as "
                + "specified in value type list element."
            )

        if not (
            not (that.value is not None)
            or (all(element.id_short is None for element in that.value))
        ):
            yield Error(
                "Constraint AASd-120: ID-short of submodel elements being "
                + "a direct child of a  Submodel element list shall not be "
                + "specified."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.semantic_id_list_element is not None:
            for error in self.transform(that.semantic_id_list_element):
                error.path._prepend(PropertySegment(that, "semantic_id_list_element"))
                yield error

        if that.value is not None:
            for i, yet_yet_yet_yet_yet_another_item in enumerate(that.value):
                for error in self.transform(yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.value, i))
                    error.path._prepend(PropertySegment(that, "value"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_submodel_element_collection(
        self, that: aas_types.SubmodelElementCollection
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (not (that.value is not None) or (len(that.value) >= 1)):
            yield Error("Value must be either not set or have at least one item.")

        if not (
            not (that.value is not None)
            or (all(item.id_short is not None for item in that.value))
        ):
            yield Error(
                "ID-shorts need to be defined for all the items of value "
                + "according to AASd-117 (ID-short of Referables not being "
                + "a direct child of a Submodel element list shall be "
                + "specified)."
            )

        if not (not (that.value is not None) or id_shorts_are_unique(that.value)):
            yield Error("ID-shorts of the value must be unique.")

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.value is not None:
            for i, yet_yet_yet_yet_yet_another_item in enumerate(that.value):
                for error in self.transform(yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.value, i))
                    error.path._prepend(PropertySegment(that, "value"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_property(self, that: aas_types.Property) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.category is not None)
            or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
        ):
            yield Error(
                "Constraint AASd-090: For data elements category shall be "
                + "one of the following values: CONSTANT, PARAMETER or "
                + "VARIABLE."
            )

        if not (
            not (that.value is not None)
            or value_consistent_with_xsd_type(that.value, that.value_type)
        ):
            yield Error("Value must be consistent with the value type.")

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.value is not None:
            for error in verify_value_data_type(that.value):
                error.path._prepend(PropertySegment(that, "value"))
                yield error

        if that.value_id is not None:
            for error in self.transform(that.value_id):
                error.path._prepend(PropertySegment(that, "value_id"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_multi_language_property(
        self, that: aas_types.MultiLanguageProperty
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.category is not None)
            or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
        ):
            yield Error(
                "Constraint AASd-090: For data elements category shall be "
                + "one of the following values: CONSTANT, PARAMETER or "
                + "VARIABLE."
            )

        if not (
            not (that.value is not None)
            or lang_strings_have_unique_languages(that.value)
        ):
            yield Error("Value must specify unique languages.")

        if not (not (that.value is not None) or (len(that.value) >= 1)):
            yield Error("Value must be either not set or have at least one item.")

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.value is not None:
            for i, yet_yet_yet_yet_yet_another_item in enumerate(that.value):
                for error in self.transform(yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.value, i))
                    error.path._prepend(PropertySegment(that, "value"))
                    yield error

        if that.value_id is not None:
            for error in self.transform(that.value_id):
                error.path._prepend(PropertySegment(that, "value_id"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_range(self, that: aas_types.Range) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.category is not None)
            or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
        ):
            yield Error(
                "Constraint AASd-090: For data elements category shall be "
                + "one of the following values: CONSTANT, PARAMETER or "
                + "VARIABLE."
            )

        if not (
            not (that.max is not None)
            or value_consistent_with_xsd_type(that.max, that.value_type)
        ):
            yield Error("Max must be consistent with the value type.")

        if not (
            not (that.min is not None)
            or value_consistent_with_xsd_type(that.min, that.value_type)
        ):
            yield Error("Min must be consistent with the value type.")

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.min is not None:
            for error in verify_value_data_type(that.min):
                error.path._prepend(PropertySegment(that, "min"))
                yield error

        if that.max is not None:
            for error in verify_value_data_type(that.max):
                error.path._prepend(PropertySegment(that, "max"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_reference_element(
        self, that: aas_types.ReferenceElement
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.category is not None)
            or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
        ):
            yield Error(
                "Constraint AASd-090: For data elements category shall be "
                + "one of the following values: CONSTANT, PARAMETER or "
                + "VARIABLE."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.value is not None:
            for error in self.transform(that.value):
                error.path._prepend(PropertySegment(that, "value"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_blob(self, that: aas_types.Blob) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.category is not None)
            or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
        ):
            yield Error(
                "Constraint AASd-090: For data elements category shall be "
                + "one of the following values: CONSTANT, PARAMETER or "
                + "VARIABLE."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.value is not None:
            for error in verify_blob_type(that.value):
                error.path._prepend(PropertySegment(that, "value"))
                yield error

        for error in verify_content_type(that.content_type):
            error.path._prepend(PropertySegment(that, "content_type"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_file(self, that: aas_types.File) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.category is not None)
            or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
        ):
            yield Error(
                "Constraint AASd-090: For data elements category shall be "
                + "one of the following values: CONSTANT, PARAMETER or "
                + "VARIABLE."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.value is not None:
            for error in verify_path_type(that.value):
                error.path._prepend(PropertySegment(that, "value"))
                yield error

        for error in verify_content_type(that.content_type):
            error.path._prepend(PropertySegment(that, "content_type"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_annotated_relationship_element(
        self, that: aas_types.AnnotatedRelationshipElement
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (not (that.annotations is not None) or (len(that.annotations) >= 1)):
            yield Error(
                "Annotations must be either not set or have at least one " + "item."
            )

        if not (
            not (that.annotations is not None)
            or (all(item.id_short is not None for item in that.annotations))
        ):
            yield Error(
                "ID-shorts need to be defined for all the items of "
                + "annotations according to AASd-117 (ID-short of Referables "
                + "not being a direct child of a Submodel element list shall "
                + "be specified)."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        for error in self.transform(that.first):
            error.path._prepend(PropertySegment(that, "first"))
            yield error

        for error in self.transform(that.second):
            error.path._prepend(PropertySegment(that, "second"))
            yield error

        if that.annotations is not None:
            for i, yet_yet_yet_yet_yet_another_item in enumerate(that.annotations):
                for error in self.transform(yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.annotations, i))
                    error.path._prepend(PropertySegment(that, "annotations"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_entity(self, that: aas_types.Entity) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (not (that.statements is not None) or (len(that.statements) >= 1)):
            yield Error("Statements must be either not set or have at least one item.")

        if not (
            not (that.statements is not None)
            or (all(item.id_short is not None for item in that.statements))
        ):
            yield Error(
                "ID-shorts need to be defined for all the items of "
                + "statements according to AASd-117 (ID-short of Referables "
                + "not being a direct child of a Submodel element list shall "
                + "be specified)."
            )

        if not (
            (
                (
                    (
                        that.entity_type == aas_types.EntityType.SELF_MANAGED_ENTITY
                        and (
                            (
                                (
                                    (
                                        (that.global_asset_id is not None)
                                        and (that.specific_asset_ids is None)
                                    )
                                )
                                or (
                                    (
                                        (that.global_asset_id is None)
                                        and (that.specific_asset_ids is not None)
                                        and len(that.specific_asset_ids) >= 1
                                    )
                                )
                            )
                        )
                    )
                )
                or (
                    (
                        that.entity_type != aas_types.EntityType.SELF_MANAGED_ENTITY
                        and (that.global_asset_id is None)
                        and (that.specific_asset_ids is None)
                    )
                )
            )
        ):
            yield Error(
                "Constraint AASd-014: Either the attribute global asset ID "
                + "or specific asset ID must be set if entity type is set to "
                + "self-managed entity. They are not existing otherwise."
            )

        if not (
            not (that.specific_asset_ids is not None)
            or (len(that.specific_asset_ids) >= 1)
        ):
            yield Error(
                "Specific asset IDs must be either not set or have at least "
                + "one item."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.statements is not None:
            for i, yet_yet_yet_yet_yet_another_item in enumerate(that.statements):
                for error in self.transform(yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.statements, i))
                    error.path._prepend(PropertySegment(that, "statements"))
                    yield error

        if that.global_asset_id is not None:
            for error in verify_identifier(that.global_asset_id):
                error.path._prepend(PropertySegment(that, "global_asset_id"))
                yield error

        if that.specific_asset_ids is not None:
            for i, yet_yet_yet_yet_yet_yet_another_item in enumerate(
                that.specific_asset_ids
            ):
                for error in self.transform(yet_yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.specific_asset_ids, i))
                    error.path._prepend(PropertySegment(that, "specific_asset_ids"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_event_payload(self, that: aas_types.EventPayload) -> Iterator[Error]:
        if not (
            (
                is_model_reference_to(that.source, aas_types.KeyTypes.EVENT_ELEMENT)
                or is_model_reference_to(
                    that.source, aas_types.KeyTypes.BASIC_EVENT_ELEMENT
                )
            )
        ):
            yield Error("Source must be a model reference to an Event element.")

        if not (is_model_reference_to_referable(that.observable_reference)):
            yield Error(
                "Observable reference must be a model reference to " + "a referable."
            )

        for error in self.transform(that.source):
            error.path._prepend(PropertySegment(that, "source"))
            yield error

        if that.source_semantic_id is not None:
            for error in self.transform(that.source_semantic_id):
                error.path._prepend(PropertySegment(that, "source_semantic_id"))
                yield error

        for error in self.transform(that.observable_reference):
            error.path._prepend(PropertySegment(that, "observable_reference"))
            yield error

        if that.observable_semantic_id is not None:
            for error in self.transform(that.observable_semantic_id):
                error.path._prepend(PropertySegment(that, "observable_semantic_id"))
                yield error

        if that.topic is not None:
            for error in verify_message_topic_type(that.topic):
                error.path._prepend(PropertySegment(that, "topic"))
                yield error

        if that.subject_id is not None:
            for error in self.transform(that.subject_id):
                error.path._prepend(PropertySegment(that, "subject_id"))
                yield error

        for error in verify_date_time_utc(that.time_stamp):
            error.path._prepend(PropertySegment(that, "time_stamp"))
            yield error

        if that.payload is not None:
            for error in verify_blob_type(that.payload):
                error.path._prepend(PropertySegment(that, "payload"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_basic_event_element(
        self, that: aas_types.BasicEventElement
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            not (that.direction == aas_types.Direction.INPUT)
            or (that.max_interval is None)
        ):
            yield Error("Max. interval is not applicable for input direction.")

        if not is_model_reference_to_referable(that.observed):
            yield Error("Observed must be a model reference to a referable.")

        if not (
            not (that.message_broker is not None)
            or is_model_reference_to_referable(that.message_broker)
        ):
            yield Error("Message broker must be a model reference to a referable.")

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        for error in self.transform(that.observed):
            error.path._prepend(PropertySegment(that, "observed"))
            yield error

        if that.message_topic is not None:
            for error in verify_message_topic_type(that.message_topic):
                error.path._prepend(PropertySegment(that, "message_topic"))
                yield error

        if that.message_broker is not None:
            for error in self.transform(that.message_broker):
                error.path._prepend(PropertySegment(that, "message_broker"))
                yield error

        if that.last_update is not None:
            for error in verify_date_time_utc(that.last_update):
                error.path._prepend(PropertySegment(that, "last_update"))
                yield error

        if that.min_interval is not None:
            for error in verify_duration(that.min_interval):
                error.path._prepend(PropertySegment(that, "min_interval"))
                yield error

        if that.max_interval is not None:
            for error in verify_duration(that.max_interval):
                error.path._prepend(PropertySegment(that, "max_interval"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_operation(self, that: aas_types.Operation) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (
            id_shorts_of_variables_are_unique(
                that.input_variables, that.output_variables, that.inoutput_variables
            )
        ):
            yield Error(
                "Constraint AASd-134: For an Operation the ID-short of all "
                + "values of input, output and in/output variables shall be "
                + "unique."
            )

        if not (
            not (that.input_variables is not None) or (len(that.input_variables) >= 1)
        ):
            yield Error(
                "Input variables must be either not set or have at least one " + "item."
            )

        if not (
            not (that.output_variables is not None) or (len(that.output_variables) >= 1)
        ):
            yield Error(
                "Output variables must be either not set or have at least "
                + "one item."
            )

        if not (
            not (that.inoutput_variables is not None)
            or (len(that.inoutput_variables) >= 1)
        ):
            yield Error(
                "Inoutput variables must be either not set or have at least "
                + "one item."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.input_variables is not None:
            for i, yet_yet_yet_yet_yet_another_item in enumerate(that.input_variables):
                for error in self.transform(yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.input_variables, i))
                    error.path._prepend(PropertySegment(that, "input_variables"))
                    yield error

        if that.output_variables is not None:
            for i, yet_yet_yet_yet_yet_yet_another_item in enumerate(
                that.output_variables
            ):
                for error in self.transform(yet_yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.output_variables, i))
                    error.path._prepend(PropertySegment(that, "output_variables"))
                    yield error

        if that.inoutput_variables is not None:
            for i, yet_yet_yet_yet_yet_yet_yet_another_item in enumerate(
                that.inoutput_variables
            ):
                for error in self.transform(yet_yet_yet_yet_yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.inoutput_variables, i))
                    error.path._prepend(PropertySegment(that, "inoutput_variables"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_operation_variable(
        self, that: aas_types.OperationVariable
    ) -> Iterator[Error]:
        if not (that.value.id_short is not None):
            yield Error(
                "Value must have the ID-short specified according to "
                + "Constraint AASd-117 (ID-short of Referables not being "
                + "a direct child of a Submodel element list shall be "
                + "specified)."
            )

        for error in self.transform(that.value):
            error.path._prepend(PropertySegment(that, "value"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_capability(self, that: aas_types.Capability) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (len(that.supplemental_semantic_ids) >= 1)
        ):
            yield Error(
                "Supplemental semantic IDs must be either not set or have at "
                + "least one item."
            )

        if not (
            not (that.supplemental_semantic_ids is not None)
            or (that.semantic_id is not None)
        ):
            yield Error(
                "Constraint AASd-118: If there are supplemental semantic IDs "
                + "defined then there shall be also a main semantic ID."
            )

        if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
            yield Error("Qualifiers must be either not set or have at least one item.")

        if not (
            not (that.qualifiers is not None)
            or qualifier_types_are_unique(that.qualifiers)
        ):
            yield Error(
                "Constraint AASd-021: Every qualifiable can only have one "
                + "qualifier with the same type."
            )

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.semantic_id is not None:
            for error in self.transform(that.semantic_id):
                error.path._prepend(PropertySegment(that, "semantic_id"))
                yield error

        if that.supplemental_semantic_ids is not None:
            for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
                    error.path._prepend(
                        PropertySegment(that, "supplemental_semantic_ids")
                    )
                    yield error

        if that.qualifiers is not None:
            for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.qualifiers, i))
                    error.path._prepend(PropertySegment(that, "qualifiers"))
                    yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_yet_yet_another_item in enumerate(
                that.embedded_data_specifications
            ):
                for error in self.transform(yet_yet_yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_concept_description(
        self, that: aas_types.ConceptDescription
    ) -> Iterator[Error]:
        if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
            yield Error("Extensions must be either not set or have at least one item.")

        if not (
            not (that.extensions is not None)
            or extension_names_are_unique(that.extensions)
        ):
            yield Error(
                "Constraint AASd-077: The name of an extension within "
                + "Has-Extensions needs to be unique."
            )

        if not (not (that.description is not None) or (len(that.description) >= 1)):
            yield Error(
                "Description must be either not set or have at least one " + "item."
            )

        if not (
            not (that.description is not None)
            or lang_strings_have_unique_languages(that.description)
        ):
            yield Error("Description must specify unique languages.")

        if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
            yield Error(
                "Display name must be either not set or have at least one " + "item."
            )

        if not (
            not (that.display_name is not None)
            or lang_strings_have_unique_languages(that.display_name)
        ):
            yield Error("Display name must specify unique languages.")

        if not (
            not (that.embedded_data_specifications is not None)
            or (len(that.embedded_data_specifications) >= 1)
        ):
            yield Error(
                "Embedded data specifications must be either not set or have "
                + "at least one item."
            )

        if not (not (that.is_case_of is not None) or (len(that.is_case_of) >= 1)):
            yield Error("Is-case-of must be either not set or have at least one item.")

        if not (
            not (that.embedded_data_specifications is not None)
            or (
                (
                    data_specification_iec_61360s_have_definition_at_least_in_english(
                        that.embedded_data_specifications
                    )
                    or data_specification_iec_61360s_have_value(
                        that.embedded_data_specifications
                    )
                )
            )
        ):
            yield Error(
                "Constraint AASc-3a-008: For a concept description using "
                + "data specification template IEC 61360, the definition is "
                + "mandatory and shall be defined at least in English. "
                + "Exception: The concept description describes a value."
            )

        if not (
            not (
                (
                    (that.category is not None)
                    and that.category == "QUALIFIER_TYPE"
                    and (that.embedded_data_specifications is not None)
                )
            )
            or data_specification_iec_61360s_have_data_type(
                that.embedded_data_specifications
            )
        ):
            yield Error(
                "Constraint AASc-3a-007: For a concept description with "
                + "category QUALIFIER_TYPE using data specification IEC 61360, "
                + "the data type of the data specification is mandatory and "
                + "shall be defined."
            )

        if not (
            not (
                (
                    (that.category is not None)
                    and that.category == "DOCUMENT"
                    and (that.embedded_data_specifications is not None)
                )
            )
            or data_specification_iec_61360s_for_document_have_appropriate_data_type(
                that.embedded_data_specifications
            )
        ):
            yield Error(
                "Constraint AASc-3a-006: For a concept description with "
                + "category DOCUMENT using data specification IEC 61360, "
                + "the data type of the data specification shall be one of: "
                + "FILE, BLOB, HTML."
            )

        if not (
            not (
                (
                    (that.category is not None)
                    and that.category == "REFERENCE"
                    and (that.embedded_data_specifications is not None)
                )
            )
            or data_specification_iec_61360s_for_reference_have_appropriate_data_type(
                that.embedded_data_specifications
            )
        ):
            yield Error(
                "Constraint AASc-3a-005: For a concept description with "
                + "category REFERENCE using data specification IEC 61360, "
                + "the data type of the data specification shall be one of: "
                + "STRING, IRI, IRDI."
            )

        if not (
            not (
                (
                    (that.category is not None)
                    and ((that.category == "PROPERTY" or that.category == "VALUE"))
                    and (that.embedded_data_specifications is not None)
                )
            )
            or data_specification_iec_61360s_for_property_or_value_have_appropriate_data_type(
                that.embedded_data_specifications
            )
        ):
            yield Error(
                "Constraint AASc-3a-004: For a concept description with "
                + "category PROPERTY or VALUE using data specification IEC "
                + "61360, the data type of the data specification is mandatory "
                + "and shall be one of: DATE, STRING, STRING_TRANSLATABLE, "
                + "INTEGER_MEASURE, INTEGER_COUNT, INTEGER_CURRENCY, "
                + "REAL_MEASURE, REAL_COUNT, REAL_CURRENCY, BOOLEAN, RATIONAL, "
                + "RATIONAL_MEASURE, TIME, TIMESTAMP."
            )

        if that.extensions is not None:
            for i, an_item in enumerate(that.extensions):
                for error in self.transform(an_item):
                    error.path._prepend(IndexSegment(that.extensions, i))
                    error.path._prepend(PropertySegment(that, "extensions"))
                    yield error

        if that.category is not None:
            for error in verify_name_type(that.category):
                error.path._prepend(PropertySegment(that, "category"))
                yield error

        if that.id_short is not None:
            for error in verify_id_short_type(that.id_short):
                error.path._prepend(PropertySegment(that, "id_short"))
                yield error

        if that.display_name is not None:
            for i, another_item in enumerate(that.display_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.display_name, i))
                    error.path._prepend(PropertySegment(that, "display_name"))
                    yield error

        if that.description is not None:
            for i, yet_another_item in enumerate(that.description):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.description, i))
                    error.path._prepend(PropertySegment(that, "description"))
                    yield error

        if that.administration is not None:
            for error in self.transform(that.administration):
                error.path._prepend(PropertySegment(that, "administration"))
                yield error

        for error in verify_identifier(that.id):
            error.path._prepend(PropertySegment(that, "id"))
            yield error

        if that.embedded_data_specifications is not None:
            for i, yet_yet_another_item in enumerate(that.embedded_data_specifications):
                for error in self.transform(yet_yet_another_item):
                    error.path._prepend(
                        IndexSegment(that.embedded_data_specifications, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "embedded_data_specifications")
                    )
                    yield error

        if that.is_case_of is not None:
            for i, yet_yet_yet_another_item in enumerate(that.is_case_of):
                for error in self.transform(yet_yet_yet_another_item):
                    error.path._prepend(IndexSegment(that.is_case_of, i))
                    error.path._prepend(PropertySegment(that, "is_case_of"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_reference(self, that: aas_types.Reference) -> Iterator[Error]:
        if not (len(that.keys) >= 1):
            yield Error("Keys must contain at least one item.")

        if not (
            not (len(that.keys) >= 1)
            or (that.keys[0].type in aas_constants.GLOBALLY_IDENTIFIABLES)
        ):
            yield Error(
                "Constraint AASd-121: For References the value of type of "
                + "the first key of keys shall be one of Globally "
                + "Identifiables."
            )

        if not (
            not (
                (
                    that.type == aas_types.ReferenceTypes.EXTERNAL_REFERENCE
                    and len(that.keys) >= 1
                )
            )
            or (that.keys[0].type in aas_constants.GENERIC_GLOBALLY_IDENTIFIABLES)
        ):
            yield Error(
                "Constraint AASd-122: For external references the value of "
                + "type of the first key of keys shall be one of Generic "
                + "Globally Identifiables."
            )

        if not (
            not (
                (
                    that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
                    and len(that.keys) >= 1
                )
            )
            or (that.keys[0].type in aas_constants.AAS_IDENTIFIABLES)
        ):
            yield Error(
                "Constraint AASd-123: For model references the value of type "
                + "of the first key of keys shall be one of AAS identifiables."
            )

        if not (
            not (
                (
                    that.type == aas_types.ReferenceTypes.EXTERNAL_REFERENCE
                    and len(that.keys) >= 1
                )
            )
            or (
                (
                    (that.keys[-1].type in aas_constants.GENERIC_GLOBALLY_IDENTIFIABLES)
                    or (that.keys[-1].type in aas_constants.GENERIC_FRAGMENT_KEYS)
                )
            )
        ):
            yield Error(
                "Constraint AASd-124: For external references the last key "
                + "of keys shall be either one of Generic Globally "
                + "Identifiables or one of Generic Fragment Keys."
            )

        if not (
            not (
                (
                    that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
                    and len(that.keys) > 1
                )
            )
            or (
                all(
                    that.keys[i].type in aas_constants.FRAGMENT_KEYS
                    for i in range(1, len(that.keys))
                )
            )
        ):
            yield Error(
                "Constraint AASd-125: For model references with more than "
                + "one key in keys the value of type of each of the keys "
                + "following the first key of keys shall be one of Fragment "
                + "Keys."
            )

        if not (
            not (
                (
                    that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
                    and len(that.keys) > 1
                )
            )
            or (
                all(
                    not (that.keys[i].type in aas_constants.GENERIC_FRAGMENT_KEYS)
                    for i in range(0, len(that.keys) - 1)
                )
            )
        ):
            yield Error(
                "Constraint AASd-126: For model references with more than "
                + "one key in keys the value of type of the last key in "
                + "the reference key chain may be one of Generic Fragment Keys "
                + "or no key at all shall have a value out of Generic Fragment "
                + "Keys."
            )

        if not (
            not (
                (
                    that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
                    and len(that.keys) > 1
                    and that.keys[-1].type == aas_types.KeyTypes.FRAGMENT_REFERENCE
                )
            )
            or (
                (
                    that.keys[-2].type == aas_types.KeyTypes.FILE
                    or that.keys[-2].type == aas_types.KeyTypes.BLOB
                )
            )
        ):
            yield Error(
                "Constraint AASd-127: For model references, with more than "
                + "one key in keys a key with type Fragment Reference shall be "
                + "preceded by a key with type File or Blob."
            )

        if not (
            not (
                (
                    that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
                    and len(that.keys) > 2
                )
            )
            or (
                all(
                    not (that.keys[i].type == aas_types.KeyTypes.SUBMODEL_ELEMENT_LIST)
                    or matches_xs_non_negative_integer(that.keys[i + 1].value)
                    for i in range(0, len(that.keys) - 1)
                )
            )
        ):
            yield Error(
                "Constraint AASd-128: For model references, the value of "
                + "a key preceded by a key with type Submodel element list is "
                + "an integer number denoting the position in the array of "
                + "the submodel element list."
            )

        if that.referred_semantic_id is not None:
            for error in self.transform(that.referred_semantic_id):
                error.path._prepend(PropertySegment(that, "referred_semantic_id"))
                yield error

        for i, an_item in enumerate(that.keys):
            for error in self.transform(an_item):
                error.path._prepend(IndexSegment(that.keys, i))
                error.path._prepend(PropertySegment(that, "keys"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_key(self, that: aas_types.Key) -> Iterator[Error]:
        for error in verify_identifier(that.value):
            error.path._prepend(PropertySegment(that, "value"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_lang_string_name_type(
        self, that: aas_types.LangStringNameType
    ) -> Iterator[Error]:
        if not (len(that.text) <= 128):
            yield Error("String shall have a maximum length of 128 characters.")

        for error in verify_bcp_47_language_tag(that.language):
            error.path._prepend(PropertySegment(that, "language"))
            yield error

        for error in verify_non_empty_xml_serializable_string(that.text):
            error.path._prepend(PropertySegment(that, "text"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_lang_string_text_type(
        self, that: aas_types.LangStringTextType
    ) -> Iterator[Error]:
        if not (len(that.text) <= 1023):
            yield Error("String shall have a maximum length of 1023 characters.")

        for error in verify_bcp_47_language_tag(that.language):
            error.path._prepend(PropertySegment(that, "language"))
            yield error

        for error in verify_non_empty_xml_serializable_string(that.text):
            error.path._prepend(PropertySegment(that, "text"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_environment(self, that: aas_types.Environment) -> Iterator[Error]:
        if not (
            not (that.concept_descriptions is not None)
            or (len(that.concept_descriptions) >= 1)
        ):
            yield Error(
                "Concept descriptions must be either not set or have at "
                + "least one item."
            )

        if not (not (that.submodels is not None) or (len(that.submodels) >= 1)):
            yield Error("Submodels must be either not set or have at least one item.")

        if not (
            not (that.asset_administration_shells is not None)
            or (len(that.asset_administration_shells) >= 1)
        ):
            yield Error(
                "Asset administration shells must be either not set or have "
                + "at least one item."
            )

        if that.asset_administration_shells is not None:
            for i, an_item in enumerate(that.asset_administration_shells):
                for error in self.transform(an_item):
                    error.path._prepend(
                        IndexSegment(that.asset_administration_shells, i)
                    )
                    error.path._prepend(
                        PropertySegment(that, "asset_administration_shells")
                    )
                    yield error

        if that.submodels is not None:
            for i, another_item in enumerate(that.submodels):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.submodels, i))
                    error.path._prepend(PropertySegment(that, "submodels"))
                    yield error

        if that.concept_descriptions is not None:
            for i, yet_another_item in enumerate(that.concept_descriptions):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.concept_descriptions, i))
                    error.path._prepend(PropertySegment(that, "concept_descriptions"))
                    yield error

    # noinspection PyMethodMayBeStatic
    def transform_embedded_data_specification(
        self, that: aas_types.EmbeddedDataSpecification
    ) -> Iterator[Error]:
        for error in self.transform(that.data_specification):
            error.path._prepend(PropertySegment(that, "data_specification"))
            yield error

        for error in self.transform(that.data_specification_content):
            error.path._prepend(PropertySegment(that, "data_specification_content"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_level_type(self, that: aas_types.LevelType) -> Iterator[Error]:
        # No verification has been defined for LevelType.
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    # noinspection PyMethodMayBeStatic
    def transform_value_reference_pair(
        self, that: aas_types.ValueReferencePair
    ) -> Iterator[Error]:
        for error in verify_value_type_iec_61360(that.value):
            error.path._prepend(PropertySegment(that, "value"))
            yield error

        for error in self.transform(that.value_id):
            error.path._prepend(PropertySegment(that, "value_id"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_value_list(self, that: aas_types.ValueList) -> Iterator[Error]:
        if not (len(that.value_reference_pairs) >= 1):
            yield Error("Value reference pair types must contain at least one item.")

        for i, an_item in enumerate(that.value_reference_pairs):
            for error in self.transform(an_item):
                error.path._prepend(IndexSegment(that.value_reference_pairs, i))
                error.path._prepend(PropertySegment(that, "value_reference_pairs"))
                yield error

    # noinspection PyMethodMayBeStatic
    def transform_lang_string_preferred_name_type_iec_61360(
        self, that: aas_types.LangStringPreferredNameTypeIEC61360
    ) -> Iterator[Error]:
        if not (len(that.text) <= 255):
            yield Error("String shall have a maximum length of 255 characters.")

        for error in verify_bcp_47_language_tag(that.language):
            error.path._prepend(PropertySegment(that, "language"))
            yield error

        for error in verify_non_empty_xml_serializable_string(that.text):
            error.path._prepend(PropertySegment(that, "text"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_lang_string_short_name_type_iec_61360(
        self, that: aas_types.LangStringShortNameTypeIEC61360
    ) -> Iterator[Error]:
        if not (len(that.text) <= 18):
            yield Error("String shall have a maximum length of 18 characters.")

        for error in verify_bcp_47_language_tag(that.language):
            error.path._prepend(PropertySegment(that, "language"))
            yield error

        for error in verify_non_empty_xml_serializable_string(that.text):
            error.path._prepend(PropertySegment(that, "text"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_lang_string_definition_type_iec_61360(
        self, that: aas_types.LangStringDefinitionTypeIEC61360
    ) -> Iterator[Error]:
        if not (len(that.text) <= 1023):
            yield Error("String shall have a maximum length of 1023 characters.")

        for error in verify_bcp_47_language_tag(that.language):
            error.path._prepend(PropertySegment(that, "language"))
            yield error

        for error in verify_non_empty_xml_serializable_string(that.text):
            error.path._prepend(PropertySegment(that, "text"))
            yield error

    # noinspection PyMethodMayBeStatic
    def transform_data_specification_iec_61360(
        self, that: aas_types.DataSpecificationIEC61360
    ) -> Iterator[Error]:
        if not (not (((that.value is not None) and (that.value_list is not None)))):
            yield Error(
                "Constraint AASc-3a-010: If value is not empty then value "
                + "list shall be empty and vice versa."
            )

        if not (
            not (
                (
                    (that.data_type is not None)
                    and (that.data_type in aas_constants.IEC_61360_DATA_TYPES_WITH_UNIT)
                )
            )
            or (((that.unit is not None) or (that.unit_id is not None)))
        ):
            yield Error(
                "Constraint AASc-3a-009: If data type is a an integer, real "
                + "or rational with a measure or currency, unit or unit ID "
                + "shall be defined."
            )

        if not (not (that.definition is not None) or (len(that.definition) >= 1)):
            yield Error("Definition must be either not set or have at least one item.")

        if not (
            not (that.definition is not None)
            or lang_strings_have_unique_languages(that.definition)
        ):
            yield Error("Definition must specify unique languages.")

        if not (not (that.short_name is not None) or (len(that.short_name) >= 1)):
            yield Error("Short name must be either not set or have at least one item.")

        if not (
            not (that.short_name is not None)
            or lang_strings_have_unique_languages(that.short_name)
        ):
            yield Error("Short name must specify unique languages.")

        if not (len(that.preferred_name) >= 1):
            yield Error("Preferred name must have at least one item.")

        if not (lang_strings_have_unique_languages(that.preferred_name)):
            yield Error("Preferred name must specify unique languages.")

        if not (
            any(
                is_bcp_47_for_english(lang_string.language)
                for lang_string in that.preferred_name
            )
        ):
            yield Error(
                "Constraint AASc-3a-002: preferred name shall be provided at "
                + "least in English."
            )

        for i, an_item in enumerate(that.preferred_name):
            for error in self.transform(an_item):
                error.path._prepend(IndexSegment(that.preferred_name, i))
                error.path._prepend(PropertySegment(that, "preferred_name"))
                yield error

        if that.short_name is not None:
            for i, another_item in enumerate(that.short_name):
                for error in self.transform(another_item):
                    error.path._prepend(IndexSegment(that.short_name, i))
                    error.path._prepend(PropertySegment(that, "short_name"))
                    yield error

        if that.unit is not None:
            for error in verify_non_empty_xml_serializable_string(that.unit):
                error.path._prepend(PropertySegment(that, "unit"))
                yield error

        if that.unit_id is not None:
            for error in self.transform(that.unit_id):
                error.path._prepend(PropertySegment(that, "unit_id"))
                yield error

        if that.source_of_definition is not None:
            for error in verify_non_empty_xml_serializable_string(
                that.source_of_definition
            ):
                error.path._prepend(PropertySegment(that, "source_of_definition"))
                yield error

        if that.symbol is not None:
            for error in verify_non_empty_xml_serializable_string(that.symbol):
                error.path._prepend(PropertySegment(that, "symbol"))
                yield error

        if that.definition is not None:
            for i, yet_another_item in enumerate(that.definition):
                for error in self.transform(yet_another_item):
                    error.path._prepend(IndexSegment(that.definition, i))
                    error.path._prepend(PropertySegment(that, "definition"))
                    yield error

        if that.value_format is not None:
            for error in verify_non_empty_xml_serializable_string(that.value_format):
                error.path._prepend(PropertySegment(that, "value_format"))
                yield error

        if that.value_list is not None:
            for error in self.transform(that.value_list):
                error.path._prepend(PropertySegment(that, "value_list"))
                yield error

        if that.value is not None:
            for error in verify_value_type_iec_61360(that.value):
                error.path._prepend(PropertySegment(that, "value"))
                yield error

        if that.level_type is not None:
            for error in self.transform(that.level_type):
                error.path._prepend(PropertySegment(that, "level_type"))
                yield error


_TRANSFORMER = _Transformer()


def verify(that: aas_types.Class) -> Iterator[Error]:
    """
    Verify the constraints of :paramref:`that` recursively.

    :param that: instance whose constraints we want to verify
    :yield: constraint violations
    """
    yield from _TRANSFORMER.transform(that)


def verify_xml_serializable_string(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )


def verify_non_empty_xml_serializable_string(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")


def verify_date_time_utc(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xs_date_time_utc(that):
        yield Error(
            "The value must match the pattern of xs:dateTime with "
            + "the time zone fixed to UTC."
        )

    if not is_xs_date_time_utc(that):
        yield Error(
            "The value must represent a valid xs:dateTime with the time "
            + "zone fixed to UTC."
        )


def verify_duration(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xs_duration(that):
        yield Error("The value must match the pattern of xs:duration.")


# noinspection PyUnusedLocal
def verify_blob_type(that: bytes) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    # There is no verification specified.
    return

    # Empty generator according to:
    # https://stackoverflow.com/a/13243870/1600678
    # noinspection PyUnreachableCode
    yield


def verify_identifier(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 2000):
        yield Error("Identifier shall have a maximum length of 2000 characters.")


def verify_value_type_iec_61360(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 2000):
        yield Error(
            "Value type IEC 61360 shall have a maximum length of 2000 " + "characters."
        )


def verify_name_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 128):
        yield Error("Name type shall have a maximum length of 128 characters.")


def verify_version_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not matches_version_type(that):
        yield Error("Version type shall match the version pattern.")

    if not (len(that) <= 4):
        yield Error("Version type shall have a maximum length of 4 characters.")


def verify_revision_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not matches_revision_type(that):
        yield Error("Revision type shall match the revision pattern.")

    if not (len(that) <= 4):
        yield Error("Revision type shall have a maximum length of 4 characters.")


def verify_label_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 64):
        yield Error("Label type shall have a maximum length of 64 characters.")


def verify_message_topic_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 255):
        yield Error(
            "Message topic type shall have a maximum length of 255 " + "characters."
        )


def verify_bcp_47_language_tag(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_bcp_47(that):
        yield Error(
            "The value must represent a value language tag conformant to " + "BCP 47."
        )


def verify_content_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 100):
        yield Error("Content type shall have a maximum length of 100 characters.")

    if not matches_mime_type(that):
        yield Error(
            "The value must represent a valid content MIME type "
            + "according to RFC 2046."
        )


def verify_path_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 2000):
        yield Error("Identifier shall have a maximum length of 2000 characters.")

    if not matches_rfc_2396(that):
        yield Error(
            "String with max 2048 and min 1 characters conformant to "
            + "a URI as per RFC 2396."
        )


def verify_qualifier_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 128):
        yield Error("Name type shall have a maximum length of 128 characters.")


def verify_value_data_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )


def verify_id_short_type(that: str) -> Iterator[Error]:
    """Verify the constraints of :paramref:`that`."""
    if not matches_xml_serializable_string(that):
        yield Error(
            "Constraint AASd-130: An attribute with data type 'string' "
            + "shall consist of these characters only: "
            + "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
        )

    if not (len(that) >= 1):
        yield Error("The value must not be empty.")

    if not (len(that) <= 128):
        yield Error("Name type shall have a maximum length of 128 characters.")

    if not matches_id_short(that):
        yield Error(
            "ID-short of Referables shall only feature letters, digits, "
            + "underscore (``_``); starting mandatory with a letter. "
            + "*I.e.* ``[a-zA-Z][a-zA-Z0-9_]*``."
        )


# This code has been automatically generated by aas-core-codegen.
# Do NOT edit or append.
