"""
Provide an implementation of the Asset Administration Shell (AAS) V3.0.

The presented version of the Metamodel is related to the work of
aas-core-works, which can be found here: https://github.com/aas-core-works.

The presented content is neither related to the IDTA nor
Plattform Industrie 4.0 and does not represent an official publication.

We diverge from the book in the following points.

We did not implement the following constraints as they are too general and can not
be formalized as part of the core library, but affects external components such as
AAS registry or AAS server:

* :ref:`Constraint AASd-022 <constraint_AASd-022>`

We did not implement the following constraints since they depend on registry and
de-referencing of :py:class:`Reference` objects:

* :ref:`Constraint AASd-006 <constraint_AASd-006>`
* :ref:`Constraint AASd-007 <constraint_AASd-007>`
* :ref:`Constraint AASc-3a-003 <constraint_AASc-3a-003>`

Some constraints are not enforceable as they depend on the wider context
such as language understanding, so we could not formalize them:

* :ref:`Constraint AASd-012 <constraint_AASd-012>`: This constraint requires that the texts inside
  ``Multi_language_property`` shall have the same meanings in the separate languages.
  This cannot be tested.
* :ref:`Constraint AASd-116 <constraint_AASd-116>`: In the book, :ref:`Constraint AASd-116 <constraint_AASd-116>` imposes a
  case-insensitive equality against ``globalAssetId``. This is culturally-dependent,
  and depends on the system settings. For example, the case-folding
  for the letters "i" and "I" is different in Turkish from English.

  We implement the constraint as case-sensitive instead to allow for interoperability
  across different culture settings.

Furthermore, we diverge from the book in the following points regarding
the enumerations. We have to implement subsets of enumerations as sets as common
programming languages do not support inheritance of enumerations. The relationship
between the properties and the sets is defined through invariants. This causes
the following divergences:

* We decided therefore to remove the enumeration ``DataTypeDefRDF``
  and keep only :py:class:`DataTypeDefXSD` as enumeration. Otherwise, we would have
  to write redundant invariants all over the meta-model because ``DataTypeDefRDF``
  is actually never used in any type definition.
* The enumeration :py:class:`AASSubmodelElements` is used in two different contexts.
  One context is the definition of key types in a reference. Another context is
  the definition of element types in a :py:class:`SubmodelElementList`.

  To avoid confusion, we introduce two separate enumerations for the separate contexts.
  Firstly, a set of :py:class:`KeyTypes`, :py:attr:`.constants.AAS_SUBMODEL_ELEMENTS_AS_KEYS` to
  represent the first context (key type in a reference).
  Secondly, the enumeration :py:class:`AASSubmodelElements` is kept as designator
  for :py:attr:`SubmodelElementList.type_value_list_element`.
* The specification introduces several types of ``Lang_string_set``.
  These types differ between the allowed length of their text inside the singular
  ``Lang_string`` objects. Since the native representation of ``Lang_string_set`` as
  ``List`` of ``Lang_string`` is required by specification, it is impossible to
  introduce separate ``Lang_string_set`` types. Therefore, the distinction is drawn here
  between the ``Lang_string`` types.

  ``DefinitionTypeIEC61360`` is represented as a
  ``List`` of :py:class:`LangStringDefinitionTypeIEC61360`

  ``MultiLanguageNameType`` is represented as a
  ``List`` of :py:class:`LangStringNameType`

  ``PreferredNameTypeIEC61360`` is represented as a
  ``List`` of :py:class:`LangStringPreferredNameTypeIEC61360`

  ``ShortNameTypeIEC61360`` is represented as a
  ``List`` of :py:class:`LangStringShortNameTypeIEC61360`

  ``MultiLanguageTextType`` is represented as a
  ``List`` of :py:class:`LangStringTextType`

  Furthermore, since ``Lang_string`` is not used anywhere, we rename it to
  :py:class:`AbstractLangString`.

Concerning the data specifications, we embed them within
:py:class:`HasDataSpecification` instead of referencing them *via* an external reference.
The working group decided to change the rules for serialization *after* the book was
published. The data specifications are critical in applications, but there is no
possibility to access them through a data channel as they are not part of
an environment.
"""

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


import abc
import enum
from typing import Generic, Iterator, Optional, TypeVar, List


T = TypeVar("T")
ContextT = TypeVar("ContextT")


class Class(abc.ABC):
    """Represent the most general class of an AAS model."""

    @abc.abstractmethod
    def descend_once(self) -> Iterator["Class"]:
        """Iterate over all the instances referenced from this one."""
        raise NotImplementedError()

    @abc.abstractmethod
    def descend(self) -> Iterator["Class"]:
        """Iterate recursively over all the instances referenced from this one."""
        raise NotImplementedError()

    @abc.abstractmethod
    def accept(self, visitor: "AbstractVisitor") -> None:
        """
        Dispatch the :paramref:`visitor` on this instance.

        :param visitor: to be dispatched
        """
        raise NotImplementedError()

    @abc.abstractmethod
    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """
        Dispatch the :paramref:`visitor` on this instance with :paramref:`context`.

        :param visitor: to be dispatched
        :param context: of the visitation
        """
        raise NotImplementedError()

    @abc.abstractmethod
    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """
        Dispatch the :paramref:`transformer` on this instance.

        :param transformer: to be dispatched
        :return: transformed self
        """
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance with :paramref:`context`.

        :param transformer: to be dispatched
        :return: transformed self
        """
        raise NotImplementedError()


# pylint: disable=redefined-builtin


class HasSemantics(Class):
    """
    Element that can have a semantic definition plus some supplemental semantic
    definitions.

    :constraint AASd-118:
        .. _constraint_AASd-118:

        If there are ID :py:attr:`supplemental_semantic_ids` defined
        then there shall be also a main semantic ID :py:attr:`semantic_id`.
    """

    #: Identifier of the semantic definition of the element. It is called semantic ID
    #: of the element or also main semantic ID of the element.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    semantic_id: Optional["Reference"]

    #: Identifier of a supplemental semantic definition of the element.
    #: It is called supplemental semantic ID of the element.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    supplemental_semantic_ids: Optional[List["Reference"]]

    def over_supplemental_semantic_ids_or_empty(self) -> Iterator["Reference"]:
        """Yield from :py:attr:`.supplemental_semantic_ids` if set."""
        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

    def __init__(
        self,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
    ) -> None:
        """Initialize with the given values."""
        self.semantic_id = semantic_id
        self.supplemental_semantic_ids = supplemental_semantic_ids


class Extension(HasSemantics):
    """Single extension of an element."""

    #: Name of the extension.
    #:
    #: :constraint AASd-077:
    #:     .. _constraint_AASd-077:
    #:
    #:     The name of an extension (Extension/name) within :py:class:`HasExtensions` needs
    #:     to be unique.
    name: str

    #: Type of the value of the extension.
    #:
    #: Default: :py:attr:`DataTypeDefXSD.STRING`
    value_type: Optional["DataTypeDefXSD"]

    #: Value of the extension
    value: Optional[str]

    #: Reference to an element the extension refers to.
    refers_to: Optional[List["Reference"]]

    def over_refers_to_or_empty(self) -> Iterator["Reference"]:
        """Yield from :py:attr:`.refers_to` if set."""
        if self.refers_to is not None:
            yield from self.refers_to

    def value_type_or_default(self) -> "DataTypeDefXSD":
        """Return the :py:attr:`value_type` if set, or the default otherwise."""
        return self.value_type if self.value_type is not None else DataTypeDefXSD.STRING

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.refers_to is not None:
            yield from self.refers_to

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for an_item in self.supplemental_semantic_ids:
                yield an_item

                yield from an_item.descend()

        if self.refers_to is not None:
            for another_item in self.refers_to:
                yield another_item

                yield from another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_extension(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_extension_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_extension(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_extension_with_context(self, context)

    def __init__(
        self,
        name: str,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        value_type: Optional["DataTypeDefXSD"] = None,
        value: Optional[str] = None,
        refers_to: Optional[List["Reference"]] = None,
    ) -> None:
        """Initialize with the given values."""
        HasSemantics.__init__(self, semantic_id, supplemental_semantic_ids)
        self.name = name
        self.value_type = value_type
        self.value = value
        self.refers_to = refers_to


class HasExtensions(Class):
    """
    Element that can be extended by proprietary extensions.

    .. note::

        Extensions are proprietary, i.e. they do not support global interoperability.
    """

    #: An extension of the element.
    extensions: Optional[List["Extension"]]

    def over_extensions_or_empty(self) -> Iterator["Extension"]:
        """Yield from :py:attr:`.extensions` if set."""
        if self.extensions is not None:
            yield from self.extensions

    def __init__(self, extensions: Optional[List["Extension"]] = None) -> None:
        """Initialize with the given values."""
        self.extensions = extensions


class Referable(HasExtensions):
    """
    An element that is referable by its :py:attr:`id_short`.

    This ID is not globally unique.
    This ID is unique within the name space of the element.

    :constraint AASd-022:
        .. _constraint_AASd-022:

        :py:attr:`id_short` of non-identifiable referables
        within the same name space shall be unique (case-sensitive).
    """

    #: The category is a value that gives further meta information
    #: w.r.t. to the class of the element.
    #: It affects the expected existence of attributes and the applicability of
    #: constraints.
    #:
    #: .. note::
    #:
    #:     The category is not identical to the semantic definition
    #:     (:py:class:`HasSemantics`) of an element. The category e.g. could denote that
    #:     the element is a measurement value whereas the semantic definition of
    #:     the element would denote that it is the measured temperature.
    category: Optional[str]

    #: In case of identifiables this attribute is a short name of the element.
    #: In case of referable this ID is an identifying string of the element within
    #: its name space.
    #:
    #: .. note::
    #:
    #:     In case the element is a property and the property has a semantic definition
    #:     (:py:attr:`HasSemantics.semantic_id`) conformant to IEC61360
    #:     the :py:attr:`id_short` is typically identical to the short name in English.
    id_short: Optional[str]

    #: Display name. Can be provided in several languages.
    display_name: Optional[List["LangStringNameType"]]

    #: Description or comments on the element.
    #:
    #: The description can be provided in several languages.
    #:
    #: If no description is defined, then the definition of the concept
    #: description that defines the semantics of the element is used.
    #:
    #: Additional information can be provided, e.g., if the element is
    #: qualified and which qualifier types can be expected in which
    #: context or which additional data specification templates are
    #: provided.
    description: Optional[List["LangStringTextType"]]

    def over_display_name_or_empty(self) -> Iterator["LangStringNameType"]:
        """Yield from :py:attr:`.display_name` if set."""
        if self.display_name is not None:
            yield from self.display_name

    def over_description_or_empty(self) -> Iterator["LangStringTextType"]:
        """Yield from :py:attr:`.description` if set."""
        if self.description is not None:
            yield from self.description

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
    ) -> None:
        """Initialize with the given values."""
        HasExtensions.__init__(self, extensions)
        self.id_short = id_short
        self.display_name = display_name
        self.category = category
        self.description = description


class Identifiable(Referable):
    """An element that has a globally unique identifier."""

    #: Administrative information of an identifiable element.
    #:
    #: .. note::
    #:
    #:     Some of the administrative information like the version number might need to
    #:     be part of the identification.
    administration: Optional["AdministrativeInformation"]

    #: The globally unique identification of the element.
    id: str

    def __init__(
        self,
        id: str,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        administration: Optional["AdministrativeInformation"] = None,
    ) -> None:
        """Initialize with the given values."""
        Referable.__init__(
            self, extensions, category, id_short, display_name, description
        )
        self.id = id
        self.administration = administration


class ModellingKind(enum.Enum):
    """
    Enumeration for denoting whether an element is a template or an instance.
    """

    #: Specification of the common features of a structured element in sufficient detail
    #: that such a instance can be instantiated using it
    TEMPLATE = "Template"

    #: Concrete, clearly identifiable element instance. Its creation and validation
    #: may be guided by a corresponding element template.
    INSTANCE = "Instance"


class HasKind(Class):
    """
    An element with a kind is an element that can either represent a template or an
    instance.

    Default for an element is that it is representing an instance.
    """

    #: Kind of the element: either type or instance.
    #:
    #: Default: :py:attr:`ModellingKind.INSTANCE`
    kind: Optional["ModellingKind"]

    def kind_or_default(self) -> "ModellingKind":
        """Return :py:attr:`kind` if set, and the default otherwise."""
        return self.kind if self.kind is not None else ModellingKind.INSTANCE

    def __init__(self, kind: Optional["ModellingKind"] = None) -> None:
        """Initialize with the given values."""
        self.kind = kind


class HasDataSpecification(Class):
    """
    Element that can be extended by using data specification templates.

    A data specification template defines a named set of additional attributes an
    element may or shall have. The data specifications used are explicitly specified
    with their global ID.
    """

    #: Embedded data specification.
    embedded_data_specifications: Optional[List["EmbeddedDataSpecification"]]

    def over_embedded_data_specifications_or_empty(
        self,
    ) -> Iterator["EmbeddedDataSpecification"]:
        """Yield from :py:attr:`.embedded_data_specifications` if set."""
        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

    def __init__(
        self,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
    ) -> None:
        """Initialize with the given values."""
        self.embedded_data_specifications = embedded_data_specifications


class AdministrativeInformation(HasDataSpecification):
    """
    Administrative meta-information for an element like version
    information.

    :constraint AASd-005:
        .. _constraint_AASd-005:

        If :py:attr:`version` is not specified then also :py:attr:`revision` shall be
        unspecified. This means, a revision requires a version. If there is no version
        there is no revision neither. Revision is optional.
    """

    #: Version of the element.
    version: Optional[str]

    #: Revision of the element.
    revision: Optional[str]

    #: The subject ID of the subject responsible for making the element.
    creator: Optional["Reference"]

    #: Identifier of the template that guided the creation of the element.
    #:
    #: .. note::
    #:
    #:     In case of a submodel the :py:attr:`template_id` is the identifier
    #:     of the submodel template ID that guided the creation of the submodel
    #:
    #: .. note::
    #:
    #:     The :py:attr:`template_id` is not relevant for validation in Submodels.
    #:     For validation the :py:attr:`Submodel.semantic_id` shall be used.
    #:
    #: .. note::
    #:
    #:     Usage of :py:attr:`template_id` is not restricted to submodel instances. So also
    #:     the creation of submodel templates can be guided by another submodel template.
    template_id: Optional[str]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.creator is not None:
            yield self.creator

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.embedded_data_specifications is not None:
            for an_item in self.embedded_data_specifications:
                yield an_item

                yield from an_item.descend()

        if self.creator is not None:
            yield self.creator

            yield from self.creator.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_administrative_information(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_administrative_information_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_administrative_information(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_administrative_information_with_context(
            self, context
        )

    def __init__(
        self,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        version: Optional[str] = None,
        revision: Optional[str] = None,
        creator: Optional["Reference"] = None,
        template_id: Optional[str] = None,
    ) -> None:
        """Initialize with the given values."""
        HasDataSpecification.__init__(self, embedded_data_specifications)
        self.version = version
        self.revision = revision
        self.creator = creator
        self.template_id = template_id


class Qualifiable(Class):
    """
    The value of a qualifiable element may be further qualified by one or more
    qualifiers.

    :constraint AASd-119:
        .. _constraint_AASd-119:

        If any :py:attr:`Qualifier.kind` value of :py:attr:`qualifiers` is
        equal to :py:attr:`QualifierKind.TEMPLATE_QUALIFIER` and the qualified element
        inherits from :py:class:`HasKind` then the qualified element shall be of
        kind Template (:py:attr:`HasKind.kind` = :py:attr:`ModellingKind.TEMPLATE`).

        .. note::

            This constraint is checked at :py:class:`Submodel`.
    """

    #: Additional qualification of a qualifiable element.
    #:
    #: :constraint AASd-021:
    #:     .. _constraint_AASd-021:
    #:
    #:     Every qualifiable can only have one qualifier with the same
    #:     :py:attr:`Qualifier.type`.
    qualifiers: Optional[List["Qualifier"]]

    def over_qualifiers_or_empty(self) -> Iterator["Qualifier"]:
        """Yield from :py:attr:`.qualifiers` if set."""
        if self.qualifiers is not None:
            yield from self.qualifiers

    def __init__(self, qualifiers: Optional[List["Qualifier"]] = None) -> None:
        """Initialize with the given values."""
        self.qualifiers = qualifiers


class QualifierKind(enum.Enum):
    """
    Enumeration for kinds of qualifiers.

    .. note::

        This element is experimental and therefore may be subject to change or may be
        removed completely in future versions of the meta-model.
    """

    #: qualifies the value of the element and can change during run-time.
    #:
    #: Value qualifiers are only applicable to elements with kind
    #: :py:attr:`ModellingKind.INSTANCE`.
    VALUE_QUALIFIER = "ValueQualifier"

    #: qualifies the semantic definition the element is referring to
    #: (:py:attr:`HasSemantics.semantic_id`)
    CONCEPT_QUALIFIER = "ConceptQualifier"

    #: qualifies the elements within a specific submodel on concept level.
    #:
    #: Template qualifiers are only applicable to elements with kind
    #: :py:attr:`ModellingKind.TEMPLATE`.
    TEMPLATE_QUALIFIER = "TemplateQualifier"


class Qualifier(HasSemantics):
    """
    A qualifier is a type-value-pair that makes additional statements w.r.t. the value
    of the element.

    :constraint AASd-006:
        .. _constraint_AASd-006:

        If both the :py:attr:`value` and the :py:attr:`value_id` of
        a :py:class:`Qualifier` are present then the :py:attr:`value` needs
        to be identical to the value of the referenced coded value
        in :py:attr:`value_id`.

    :constraint AASd-020:
        .. _constraint_AASd-020:

        The value of :py:attr:`value` shall be consistent to the data type as
        defined in :py:attr:`value_type`.
    """

    #: The qualifier kind describes the kind of the qualifier that is applied to the
    #: element.
    #:
    #: Default: :py:attr:`QualifierKind.CONCEPT_QUALIFIER`
    kind: Optional["QualifierKind"]

    #: The qualifier *type* describes the type of the qualifier that is applied to
    #: the element.
    type: str

    #: Data type of the qualifier value.
    value_type: "DataTypeDefXSD"

    #: The qualifier value is the value of the qualifier.
    value: Optional[str]

    #: Reference to the global unique ID of a coded value.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    value_id: Optional["Reference"]

    def kind_or_default(self) -> "QualifierKind":
        """Return :py:attr:`kind` if set, and the default otherwise."""
        return self.kind if self.kind is not None else QualifierKind.CONCEPT_QUALIFIER

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.value_id is not None:
            yield self.value_id

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for an_item in self.supplemental_semantic_ids:
                yield an_item

                yield from an_item.descend()

        if self.value_id is not None:
            yield self.value_id

            yield from self.value_id.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_qualifier(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_qualifier_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_qualifier(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_qualifier_with_context(self, context)

    def __init__(
        self,
        type: str,
        value_type: "DataTypeDefXSD",
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        kind: Optional["QualifierKind"] = None,
        value: Optional[str] = None,
        value_id: Optional["Reference"] = None,
    ) -> None:
        """Initialize with the given values."""
        HasSemantics.__init__(self, semantic_id, supplemental_semantic_ids)
        self.type = type
        self.value_type = value_type
        self.kind = kind
        self.value = value
        self.value_id = value_id


class AssetAdministrationShell(Identifiable, HasDataSpecification):
    """An asset administration shell."""

    #: The reference to the AAS the AAS was derived from.
    derived_from: Optional["Reference"]

    #: Meta-information about the asset the AAS is representing.
    asset_information: "AssetInformation"

    #: References to submodels of the AAS.
    #:
    #: A submodel is a description of an aspect of the asset the AAS is representing.
    #:
    #: The asset of an AAS is typically described by one or more submodels.
    #:
    #: Temporarily no submodel might be assigned to the AAS.
    submodels: Optional[List["Reference"]]

    def over_submodels_or_empty(self) -> Iterator["Reference"]:
        """Yield from :py:attr:`.submodels` if set."""
        if self.submodels is not None:
            yield from self.submodels

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.administration is not None:
            yield self.administration

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.derived_from is not None:
            yield self.derived_from

        yield self.asset_information

        if self.submodels is not None:
            yield from self.submodels

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.administration is not None:
            yield self.administration

            yield from self.administration.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.derived_from is not None:
            yield self.derived_from

            yield from self.derived_from.descend()

        yield self.asset_information

        yield from self.asset_information.descend()

        if self.submodels is not None:
            for yet_yet_yet_another_item in self.submodels:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_asset_administration_shell(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_asset_administration_shell_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_asset_administration_shell(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_asset_administration_shell_with_context(
            self, context
        )

    def __init__(
        self,
        id: str,
        asset_information: "AssetInformation",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        administration: Optional["AdministrativeInformation"] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        derived_from: Optional["Reference"] = None,
        submodels: Optional[List["Reference"]] = None,
    ) -> None:
        """Initialize with the given values."""
        Identifiable.__init__(
            self,
            id,
            extensions,
            category,
            id_short,
            display_name,
            description,
            administration,
        )
        HasDataSpecification.__init__(self, embedded_data_specifications)
        self.derived_from = derived_from
        self.asset_information = asset_information
        self.submodels = submodels


class AssetInformation(Class):
    """
    In :py:class:`AssetInformation` identifying meta data of the asset that is
    represented by an AAS is defined.

    The asset may either represent an asset type or an asset instance.

    The asset has a globally unique identifier plus – if needed – additional domain
    specific (proprietary) identifiers. However, to support the corner case of very
    first phase of lifecycle where a stabilised/constant_set global asset identifier
    does not already exist, the corresponding attribute :py:attr:`global_asset_id` is
    optional.

    :constraint AASd-116:
        .. _constraint_AASd-116:

        ``globalAssetId`` is a reserved key. If used as value for
        :py:attr:`SpecificAssetID.name` then :py:attr:`SpecificAssetID.value` shall be
        identical to :py:attr:`global_asset_id`.

        .. note::

            :ref:`Constraint AASd-116 <constraint_AASd-116>` is important to enable a generic search across
            global and specific asset IDs.

        .. note::

            In the book, :ref:`Constraint AASd-116 <constraint_AASd-116>` imposes a
            case-insensitive equality against ``globalAssetId``. This is
            culturally-dependent, and depends on the system settings.
            For example, the case-folding for the letters "i" and "I" is
            different in Turkish from English.

            We implement the constraint as case-sensitive instead to allow
            for interoperability across different culture settings.

    :constraint AASd-131:
        .. _constraint_AASd-131:

        For :py:class:`AssetInformation` either the :py:attr:`global_asset_id` shall be
        defined or at least one item in :py:attr:`specific_asset_ids`.
    """

    #: Denotes whether the Asset is of kind :py:attr:`AssetKind.TYPE` or
    #: :py:attr:`AssetKind.INSTANCE`.
    asset_kind: "AssetKind"

    #: Global identifier of the asset the AAS is representing.
    #:
    #: This attribute is required as soon as the AAS is exchanged via partners in the life
    #: cycle of the asset. In a first phase of the life cycle the asset might not yet have
    #: a global ID but already an internal identifier. The internal identifier would be
    #: modelled via :py:attr:`specific_asset_ids`.
    #:
    #: .. note::
    #:
    #:     This is a global reference.
    global_asset_id: Optional[str]

    #: Additional domain-specific, typically proprietary identifier for the asset like
    #: e.g., serial number etc.
    specific_asset_ids: Optional[List["SpecificAssetID"]]

    #: In case :py:attr:`asset_kind` is applicable the :py:attr:`asset_type` is the asset ID
    #: of the type asset of the asset under consideration
    #: as identified by :py:attr:`global_asset_id`.
    #:
    #: .. note::
    #:
    #:     In case :py:attr:`asset_kind` is "Instance" than the :py:attr:`asset_type` denotes
    #:     which "Type" the asset is of. But it is also possible
    #:     to have an :py:attr:`asset_type` of an asset of kind "Type".
    asset_type: Optional[str]

    #: Thumbnail of the asset represented by the Asset Administration Shell.
    #:
    #: Used as default.
    default_thumbnail: Optional["Resource"]

    def over_specific_asset_ids_or_empty(self) -> Iterator["SpecificAssetID"]:
        """Yield from :py:attr:`.specific_asset_ids` if set."""
        if self.specific_asset_ids is not None:
            yield from self.specific_asset_ids

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.specific_asset_ids is not None:
            yield from self.specific_asset_ids

        if self.default_thumbnail is not None:
            yield self.default_thumbnail

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.specific_asset_ids is not None:
            for an_item in self.specific_asset_ids:
                yield an_item

                yield from an_item.descend()

        if self.default_thumbnail is not None:
            yield self.default_thumbnail

            yield from self.default_thumbnail.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_asset_information(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_asset_information_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_asset_information(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_asset_information_with_context(self, context)

    def __init__(
        self,
        asset_kind: "AssetKind",
        global_asset_id: Optional[str] = None,
        specific_asset_ids: Optional[List["SpecificAssetID"]] = None,
        asset_type: Optional[str] = None,
        default_thumbnail: Optional["Resource"] = None,
    ) -> None:
        """Initialize with the given values."""
        self.asset_kind = asset_kind
        self.global_asset_id = global_asset_id
        self.specific_asset_ids = specific_asset_ids
        self.asset_type = asset_type
        self.default_thumbnail = default_thumbnail


class Resource(Class):
    """
    Resource represents an address to a file (a locator). The value is an URI that
    can represent an absolute or relative path
    """

    #: Path and name of the resource (with file extension).
    #:
    #: The path can be absolute or relative.
    path: str

    #: Content type of the content of the file.
    #:
    #: The content type states which file extensions the file can have.
    content_type: Optional[str]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_resource(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_resource_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_resource(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_resource_with_context(self, context)

    def __init__(self, path: str, content_type: Optional[str] = None) -> None:
        """Initialize with the given values."""
        self.path = path
        self.content_type = content_type


class AssetKind(enum.Enum):
    """
    Enumeration for denoting whether an asset is a type asset or an instance asset.
    """

    #: Type asset
    TYPE = "Type"

    #: Instance asset
    INSTANCE = "Instance"

    #: Neither a type asset nor an instance asset
    NOT_APPLICABLE = "NotApplicable"


class SpecificAssetID(HasSemantics):
    """
    A specific asset ID describes a generic supplementary identifying attribute of the
    asset.

    The specific asset ID is not necessarily globally unique.

    :constraint AASd-133:
        .. _constraint_AASd-133:

        :py:attr:`external_subject_id` shall be an external reference,
        i.e. :py:attr:`Reference.type` = :py:attr:`ReferenceTypes.EXTERNAL_REFERENCE`.
    """

    #: Name of the identifier
    name: str

    #: The value of the specific asset identifier with the corresponding name.
    value: str

    #: The (external) subject the key belongs to or has meaning to.
    #:
    #: .. note::
    #:
    #:     This is a global reference.
    external_subject_id: Optional["Reference"]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.external_subject_id is not None:
            yield self.external_subject_id

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for an_item in self.supplemental_semantic_ids:
                yield an_item

                yield from an_item.descend()

        if self.external_subject_id is not None:
            yield self.external_subject_id

            yield from self.external_subject_id.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_specific_asset_id(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_specific_asset_id_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_specific_asset_id(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_specific_asset_id_with_context(self, context)

    def __init__(
        self,
        name: str,
        value: str,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        external_subject_id: Optional["Reference"] = None,
    ) -> None:
        """Initialize with the given values."""
        HasSemantics.__init__(self, semantic_id, supplemental_semantic_ids)
        self.name = name
        self.value = value
        self.external_subject_id = external_subject_id


class Submodel(Identifiable, HasKind, HasSemantics, Qualifiable, HasDataSpecification):
    """
    A submodel defines a specific aspect of the asset represented by the AAS.

    A submodel is used to structure the digital representation and technical
    functionality of an Administration Shell into distinguishable parts. Each submodel
    refers to a well-defined domain or subject matter. Submodels can become
    standardized and, thus, become submodels templates.
    """

    #: A submodel consists of zero or more submodel elements.
    submodel_elements: Optional[List["SubmodelElement"]]

    def over_submodel_elements_or_empty(self) -> Iterator["SubmodelElement"]:
        """Yield from :py:attr:`.submodel_elements` if set."""
        if self.submodel_elements is not None:
            yield from self.submodel_elements

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.administration is not None:
            yield self.administration

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.submodel_elements is not None:
            yield from self.submodel_elements

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.administration is not None:
            yield self.administration

            yield from self.administration.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.submodel_elements is not None:
            for yet_yet_yet_yet_yet_another_item in self.submodel_elements:
                yield yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_submodel(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_submodel_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_submodel(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_submodel_with_context(self, context)

    def __init__(
        self,
        id: str,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        administration: Optional["AdministrativeInformation"] = None,
        kind: Optional["ModellingKind"] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        submodel_elements: Optional[List["SubmodelElement"]] = None,
    ) -> None:
        """Initialize with the given values."""
        Identifiable.__init__(
            self,
            id,
            extensions,
            category,
            id_short,
            display_name,
            description,
            administration,
        )
        HasKind.__init__(self, kind)
        HasSemantics.__init__(self, semantic_id, supplemental_semantic_ids)
        Qualifiable.__init__(self, qualifiers)
        HasDataSpecification.__init__(self, embedded_data_specifications)
        self.submodel_elements = submodel_elements


class SubmodelElement(Referable, HasSemantics, Qualifiable, HasDataSpecification):
    """
    A submodel element is an element suitable for the description and differentiation of
    assets.

    It is recommended to add a :py:attr:`HasSemantics.semantic_id` to a submodel element.

    :constraint AASd-129:
        .. _constraint_AASd-129:

        If any :py:attr:`Qualifier.kind` value of :py:attr:`qualifiers` (attribute qualifier
        inherited via Qualifiable) is equal to :py:attr:`QualifierKind.TEMPLATE_QUALIFIER`
        then the submodel element shall be part of a submodel template, i.e.
        a Submodel with :py:attr:`Submodel.kind` (attribute kind inherited via
        :py:class:`HasKind`) value is equal to :py:attr:`ModellingKind.TEMPLATE`.
    """

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
    ) -> None:
        """Initialize with the given values."""
        Referable.__init__(
            self, extensions, category, id_short, display_name, description
        )
        HasSemantics.__init__(self, semantic_id, supplemental_semantic_ids)
        Qualifiable.__init__(self, qualifiers)
        HasDataSpecification.__init__(self, embedded_data_specifications)


class RelationshipElement(SubmodelElement):
    """
    A relationship element is used to define a relationship between two elements
    being either referable (model reference) or external (global reference).
    """

    #: Reference to the first element in the relationship taking the role of the subject.
    first: "Reference"

    #: Reference to the second element in the relationship taking the role of the object.
    second: "Reference"

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        yield self.first

        yield self.second

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        yield self.first

        yield from self.first.descend()

        yield self.second

        yield from self.second.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_relationship_element(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_relationship_element_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_relationship_element(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_relationship_element_with_context(self, context)

    def __init__(
        self,
        first: "Reference",
        second: "Reference",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.first = first
        self.second = second


class AASSubmodelElements(enum.Enum):
    """
    Enumeration of all possible elements of a :py:class:`SubmodelElementList`.
    """

    ANNOTATED_RELATIONSHIP_ELEMENT = "AnnotatedRelationshipElement"

    BASIC_EVENT_ELEMENT = "BasicEventElement"

    BLOB = "Blob"

    CAPABILITY = "Capability"

    DATA_ELEMENT = "DataElement"

    ENTITY = "Entity"

    EVENT_ELEMENT = "EventElement"

    FILE = "File"

    MULTI_LANGUAGE_PROPERTY = "MultiLanguageProperty"

    OPERATION = "Operation"

    PROPERTY = "Property"

    RANGE = "Range"

    REFERENCE_ELEMENT = "ReferenceElement"

    RELATIONSHIP_ELEMENT = "RelationshipElement"

    SUBMODEL_ELEMENT = "SubmodelElement"

    SUBMODEL_ELEMENT_LIST = "SubmodelElementList"

    SUBMODEL_ELEMENT_COLLECTION = "SubmodelElementCollection"


class SubmodelElementList(SubmodelElement):
    """
    A submodel element list is an ordered list of submodel elements.

    The numbering starts with zero (0).

    :constraint AASd-107:
        .. _constraint_AASd-107:

        If a first level child element in a :py:class:`SubmodelElementList` has
        a :py:attr:`HasSemantics.semantic_id` it
        shall be identical to :py:attr:`semantic_id_list_element`.

    :constraint AASd-114:
        .. _constraint_AASd-114:

        If two first level child elements in a :py:class:`SubmodelElementList` have
        a :py:attr:`HasSemantics.semantic_id` then they shall be identical.

    :constraint AASd-115:
        .. _constraint_AASd-115:

        If a first level child element in a :py:class:`SubmodelElementList` does not
        specify a :py:attr:`HasSemantics.semantic_id` then the value is assumed to be
        identical to :py:attr:`semantic_id_list_element`.

    :constraint AASd-120:
        .. _constraint_AASd-120:

        The :py:attr:`id_short` of a :py:class:`SubmodelElement` being a direct child of a
        :py:class:`SubmodelElementList` shall not be specified.

    :constraint AASd-108:
        .. _constraint_AASd-108:

        All first level child elements in a :py:class:`SubmodelElementList` shall have
        the same submodel element type as specified in :py:attr:`type_value_list_element`.

    :constraint AASd-109:
        .. _constraint_AASd-109:

        If :py:attr:`type_value_list_element` is equal to
        :py:attr:`AASSubmodelElements.PROPERTY` or
        :py:attr:`AASSubmodelElements.RANGE`
        :py:attr:`value_type_list_element` shall be set and all first
        level child elements in the :py:class:`SubmodelElementList` shall have
        the value type as specified in :py:attr:`value_type_list_element`.
    """

    #: Defines whether order in list is relevant. If :py:attr:`order_relevant` = ``False``
    #: then the list is representing a set or a bag.
    #:
    #: Default: ``True``
    order_relevant: Optional[bool]

    #: Semantic ID the submodel elements contained in the list match to.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    semantic_id_list_element: Optional["Reference"]

    #: The submodel element type of the submodel elements contained in the list.
    type_value_list_element: "AASSubmodelElements"

    #: The value type of the submodel element contained in the list.
    value_type_list_element: Optional["DataTypeDefXSD"]

    #: Submodel element contained in the list.
    #:
    #: The list is ordered.
    value: Optional[List["SubmodelElement"]]

    def over_value_or_empty(self) -> Iterator["SubmodelElement"]:
        """Yield from :py:attr:`.value` if set."""
        if self.value is not None:
            yield from self.value

    def order_relevant_or_default(self) -> bool:
        """Return :py:attr:`order_relevant` if set, and the default otherwise."""
        return self.order_relevant if self.order_relevant is not None else True

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.semantic_id_list_element is not None:
            yield self.semantic_id_list_element

        if self.value is not None:
            yield from self.value

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.semantic_id_list_element is not None:
            yield self.semantic_id_list_element

            yield from self.semantic_id_list_element.descend()

        if self.value is not None:
            for yet_yet_yet_yet_yet_another_item in self.value:
                yield yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_submodel_element_list(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_submodel_element_list_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_submodel_element_list(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_submodel_element_list_with_context(self, context)

    def __init__(
        self,
        type_value_list_element: "AASSubmodelElements",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        order_relevant: Optional[bool] = None,
        semantic_id_list_element: Optional["Reference"] = None,
        value_type_list_element: Optional["DataTypeDefXSD"] = None,
        value: Optional[List["SubmodelElement"]] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.type_value_list_element = type_value_list_element
        self.order_relevant = order_relevant
        self.semantic_id_list_element = semantic_id_list_element
        self.value_type_list_element = value_type_list_element
        self.value = value


class SubmodelElementCollection(SubmodelElement):
    """
    A submodel element collection is a kind of struct, i.e. a a logical encapsulation
    of multiple named values. It has a fixed number of submodel elements.
    """

    #: Submodel element contained in the collection.
    value: Optional[List["SubmodelElement"]]

    def over_value_or_empty(self) -> Iterator["SubmodelElement"]:
        """Yield from :py:attr:`.value` if set."""
        if self.value is not None:
            yield from self.value

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.value is not None:
            yield from self.value

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.value is not None:
            for yet_yet_yet_yet_yet_another_item in self.value:
                yield yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_submodel_element_collection(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_submodel_element_collection_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_submodel_element_collection(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_submodel_element_collection_with_context(
            self, context
        )

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        value: Optional[List["SubmodelElement"]] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.value = value


class DataElement(SubmodelElement):
    """
    A data element is a submodel element that is not further composed out of
    other submodel elements.

    A data element is a submodel element that has a value. The type of value differs
    for different subtypes of data elements.

    :constraint AASd-090:
        .. _constraint_AASd-090:

        For data elements :py:attr:`category` shall be one of the following
        values: ``CONSTANT``, ``PARAMETER`` or ``VARIABLE``.

        Default: ``VARIABLE``
    """

    def category_or_default(self) -> str:
        """Return the :py:attr:`category` if set or the default value otherwise."""
        return self.category if self.category else "VARIABLE"

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )


class Property(DataElement):
    """
    A property is a data element that has a single value.

    :constraint AASd-007:
        .. _constraint_AASd-007:

        If both, the :py:attr:`value` and the :py:attr:`value_id` are
        present then the value of :py:attr:`value` needs to be identical to
        the value of the referenced coded value in :py:attr:`value_id`.
    """

    #: Data type of the value
    value_type: "DataTypeDefXSD"

    #: The value of the property instance.
    value: Optional[str]

    #: Reference to the global unique ID of a coded value.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    value_id: Optional["Reference"]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.value_id is not None:
            yield self.value_id

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.value_id is not None:
            yield self.value_id

            yield from self.value_id.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_property(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_property_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_property(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_property_with_context(self, context)

    def __init__(
        self,
        value_type: "DataTypeDefXSD",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        value: Optional[str] = None,
        value_id: Optional["Reference"] = None,
    ) -> None:
        """Initialize with the given values."""
        DataElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.value_type = value_type
        self.value = value
        self.value_id = value_id


class MultiLanguageProperty(DataElement):
    """
    A property is a data element that has a multi-language value.

    :constraint AASd-012:
        .. _constraint_AASd-012:

        If both the :py:attr:`value` and the :py:attr:`value_id` are present then for each
        string in a specific language the meaning must be the same as specified in
        :py:attr:`value_id`.
    """

    #: The value of the property instance.
    value: Optional[List["LangStringTextType"]]

    #: Reference to the global unique ID of a coded value.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    value_id: Optional["Reference"]

    def over_value_or_empty(self) -> Iterator["LangStringTextType"]:
        """Yield from :py:attr:`.value` if set."""
        if self.value is not None:
            yield from self.value

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.value is not None:
            yield from self.value

        if self.value_id is not None:
            yield self.value_id

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.value is not None:
            for yet_yet_yet_yet_yet_another_item in self.value:
                yield yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_another_item.descend()

        if self.value_id is not None:
            yield self.value_id

            yield from self.value_id.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_multi_language_property(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_multi_language_property_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_multi_language_property(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_multi_language_property_with_context(self, context)

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        value: Optional[List["LangStringTextType"]] = None,
        value_id: Optional["Reference"] = None,
    ) -> None:
        """Initialize with the given values."""
        DataElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.value = value
        self.value_id = value_id


class Range(DataElement):
    """
    A range data element is a data element that defines a range with min and max.
    """

    #: Data type of the min und max
    value_type: "DataTypeDefXSD"

    #: The minimum value of the range.
    #:
    #: If the min value is missing, then the value is assumed to be negative infinite.
    min: Optional[str]

    #: The maximum value of the range.
    #:
    #: If the max value is missing, then the value is assumed to be positive infinite.
    max: Optional[str]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_range(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_range_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_range(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_range_with_context(self, context)

    def __init__(
        self,
        value_type: "DataTypeDefXSD",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        min: Optional[str] = None,
        max: Optional[str] = None,
    ) -> None:
        """Initialize with the given values."""
        DataElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.value_type = value_type
        self.min = min
        self.max = max


class ReferenceElement(DataElement):
    """
    A reference element is a data element that defines a logical reference to another
    element within the same or another AAS or a reference to an external object or
    entity.
    """

    #: Global reference to an external object or entity or a logical reference to
    #: another element within the same or another AAS (i.e. a model reference to
    #: a Referable).
    value: Optional["Reference"]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.value is not None:
            yield self.value

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.value is not None:
            yield self.value

            yield from self.value.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_reference_element(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_reference_element_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_reference_element(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_reference_element_with_context(self, context)

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        value: Optional["Reference"] = None,
    ) -> None:
        """Initialize with the given values."""
        DataElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.value = value


class Blob(DataElement):
    """
    A :py:class:`Blob` is a data element that represents a file that is contained with its
    source code in the value attribute.
    """

    #: The value of the :py:class:`Blob` instance of a blob data element.
    #:
    #: .. note::
    #:
    #:     In contrast to the file property the file content is stored directly as value
    #:     in the :py:class:`Blob` data element.
    value: Optional[bytes]

    #: Content type of the content of the :py:class:`Blob`.
    #:
    #: The content type (MIME type) states which file extensions the file can have.
    #:
    #: Valid values are content types like e.g. ``application/json``, ``application/xls``,
    #: ``image/jpg``.
    #:
    #: The allowed values are defined as in RFC2046.
    content_type: str

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_blob(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_blob_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_blob(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_blob_with_context(self, context)

    def __init__(
        self,
        content_type: str,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        value: Optional[bytes] = None,
    ) -> None:
        """Initialize with the given values."""
        DataElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.content_type = content_type
        self.value = value


class File(DataElement):
    """
    A File is a data element that represents an address to a file (a locator).

    The value is an URI that can represent an absolute or relative path.
    """

    #: Path and name of the referenced file (with file extension).
    #:
    #: The path can be absolute or relative.
    value: Optional[str]

    #: Content type of the content of the file.
    #:
    #: The content type states which file extensions the file can have.
    content_type: str

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_file(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_file_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_file(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_file_with_context(self, context)

    def __init__(
        self,
        content_type: str,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        value: Optional[str] = None,
    ) -> None:
        """Initialize with the given values."""
        DataElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.content_type = content_type
        self.value = value


class AnnotatedRelationshipElement(RelationshipElement):
    """
    An annotated relationship element is a relationship element that can be annotated
    with additional data elements.
    """

    #: A data element that represents an annotation that holds for the relationship
    #: between the two elements
    annotations: Optional[List["DataElement"]]

    def over_annotations_or_empty(self) -> Iterator["DataElement"]:
        """Yield from :py:attr:`.annotations` if set."""
        if self.annotations is not None:
            yield from self.annotations

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        yield self.first

        yield self.second

        if self.annotations is not None:
            yield from self.annotations

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        yield self.first

        yield from self.first.descend()

        yield self.second

        yield from self.second.descend()

        if self.annotations is not None:
            for yet_yet_yet_yet_yet_another_item in self.annotations:
                yield yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_annotated_relationship_element(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_annotated_relationship_element_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_annotated_relationship_element(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_annotated_relationship_element_with_context(
            self, context
        )

    def __init__(
        self,
        first: "Reference",
        second: "Reference",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        annotations: Optional[List["DataElement"]] = None,
    ) -> None:
        """Initialize with the given values."""
        RelationshipElement.__init__(
            self,
            first,
            second,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.annotations = annotations


class Entity(SubmodelElement):
    """
    An entity is a submodel element that is used to model entities.

    :constraint AASd-014:
        .. _constraint_AASd-014:

        Either the attribute :py:attr:`global_asset_id` or :py:attr:`specific_asset_ids`
        of an :py:class:`Entity` must be set if :py:attr:`entity_type` is set to
        :py:attr:`EntityType.SELF_MANAGED_ENTITY`. They are not existing otherwise.
    """

    #: Describes statements applicable to the entity by a set of submodel elements,
    #: typically with a qualified value.
    statements: Optional[List["SubmodelElement"]]

    #: Describes whether the entity is a co-managed entity or a self-managed entity.
    entity_type: "EntityType"

    #: Global identifier of the asset the entity is representing.
    #:
    #: .. note::
    #:
    #:     This is a global reference.
    global_asset_id: Optional[str]

    #: Reference to a specific asset ID representing a supplementary identifier
    #: of the asset represented by the Asset Administration Shell.
    specific_asset_ids: Optional[List["SpecificAssetID"]]

    def over_statements_or_empty(self) -> Iterator["SubmodelElement"]:
        """Yield from :py:attr:`.statements` if set."""
        if self.statements is not None:
            yield from self.statements

    def over_specific_asset_ids_or_empty(self) -> Iterator["SpecificAssetID"]:
        """Yield from :py:attr:`.specific_asset_ids` if set."""
        if self.specific_asset_ids is not None:
            yield from self.specific_asset_ids

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.statements is not None:
            yield from self.statements

        if self.specific_asset_ids is not None:
            yield from self.specific_asset_ids

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.statements is not None:
            for yet_yet_yet_yet_yet_another_item in self.statements:
                yield yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_another_item.descend()

        if self.specific_asset_ids is not None:
            for yet_yet_yet_yet_yet_yet_another_item in self.specific_asset_ids:
                yield yet_yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_entity(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_entity_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_entity(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_entity_with_context(self, context)

    def __init__(
        self,
        entity_type: "EntityType",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        statements: Optional[List["SubmodelElement"]] = None,
        global_asset_id: Optional[str] = None,
        specific_asset_ids: Optional[List["SpecificAssetID"]] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.statements = statements
        self.entity_type = entity_type
        self.global_asset_id = global_asset_id
        self.specific_asset_ids = specific_asset_ids


class EntityType(enum.Enum):
    """
    Enumeration for denoting whether an entity is a self-managed entity or a co-managed
    entity.
    """

    #: For co-managed entities there is no separate AAS. Co-managed entities need to be
    #: part of a self-managed entity.
    CO_MANAGED_ENTITY = "CoManagedEntity"

    #: Self-Managed Entities have their own AAS but can be part of the bill of material of
    #: a composite self-managed entity.
    #:
    #: The asset of an I4.0 Component is a self-managed entity per definition.
    SELF_MANAGED_ENTITY = "SelfManagedEntity"


class Direction(enum.Enum):
    """
    Direction

    .. note::

        This element is experimental and therefore may be subject to change or may be
        removed completely in future versions of the meta-model.
    """

    #: Input direction.
    INPUT = "input"

    #: Output direction
    OUTPUT = "output"


class StateOfEvent(enum.Enum):
    """
    State of an event

    .. note::

        This element is experimental and therefore may be subject to change or may be
        removed completely in future versions of the meta-model.
    """

    #: Event is on
    ON = "on"

    #: Event is off.
    OFF = "off"


class EventPayload(Class):
    """
    Defines the necessary information of an event instance sent out or received.

    .. note::

        This element is experimental and therefore may be subject to change or may be
        removed completely in future versions of the meta-model.
    """

    #: Reference to the source event element, including identification of
    #: :py:class:`AssetAdministrationShell`, :py:class:`Submodel`,
    #: :py:class:`SubmodelElement`'s.
    source: "Reference"

    #: :py:attr:`HasSemantics.semantic_id` of the source event element, if available
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    source_semantic_id: Optional["Reference"]

    #: Reference to the referable, which defines the scope of the event.
    #:
    #: Can be :py:class:`AssetAdministrationShell`, :py:class:`Submodel` or
    #: :py:class:`SubmodelElement`.
    observable_reference: "Reference"

    #: :py:attr:`HasSemantics.semantic_id` of the referable which defines the scope of
    #: the event, if available.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    observable_semantic_id: Optional["Reference"]

    #: Information for the outer message infrastructure for scheduling the event to
    #: the respective communication channel.
    topic: Optional[str]

    #: Subject, who/which initiated the creation.
    #:
    #: .. note::
    #:
    #:     This is an external reference.
    subject_id: Optional["Reference"]

    #: Timestamp in UTC, when this event was triggered.
    time_stamp: str

    #: Event specific payload.
    payload: Optional[bytes]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        yield self.source

        if self.source_semantic_id is not None:
            yield self.source_semantic_id

        yield self.observable_reference

        if self.observable_semantic_id is not None:
            yield self.observable_semantic_id

        if self.subject_id is not None:
            yield self.subject_id

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        yield self.source

        yield from self.source.descend()

        if self.source_semantic_id is not None:
            yield self.source_semantic_id

            yield from self.source_semantic_id.descend()

        yield self.observable_reference

        yield from self.observable_reference.descend()

        if self.observable_semantic_id is not None:
            yield self.observable_semantic_id

            yield from self.observable_semantic_id.descend()

        if self.subject_id is not None:
            yield self.subject_id

            yield from self.subject_id.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_event_payload(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_event_payload_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_event_payload(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_event_payload_with_context(self, context)

    def __init__(
        self,
        source: "Reference",
        observable_reference: "Reference",
        time_stamp: str,
        source_semantic_id: Optional["Reference"] = None,
        observable_semantic_id: Optional["Reference"] = None,
        topic: Optional[str] = None,
        subject_id: Optional["Reference"] = None,
        payload: Optional[bytes] = None,
    ) -> None:
        """Initialize with the given values."""
        self.source = source
        self.observable_reference = observable_reference
        self.time_stamp = time_stamp
        self.source_semantic_id = source_semantic_id
        self.observable_semantic_id = observable_semantic_id
        self.topic = topic
        self.subject_id = subject_id
        self.payload = payload


class EventElement(SubmodelElement):
    """
    An event element.

    .. note::

        This element is experimental and therefore may be subject to change or may be
        removed completely in future versions of the meta-model.
    """

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )


class BasicEventElement(EventElement):
    """
    A basic event element.

    .. note::

        This element is experimental and therefore may be subject to change or may be
        removed completely in future versions of the meta-model.
    """

    #: Reference to the :py:class:`Referable`, which defines the scope of the event.
    #: Can be :py:class:`AssetAdministrationShell`, :py:class:`Submodel`, or
    #: :py:class:`SubmodelElement`.
    #:
    #: Reference to a referable, e.g., a data element or
    #: a submodel, that is being observed.
    observed: "Reference"

    #: Direction of event.
    #:
    #: Can be ``{ Input, Output }``.
    direction: "Direction"

    #: State of event.
    #:
    #: Can be ``{ On, Off }``.
    state: "StateOfEvent"

    #: Information for the outer message infrastructure for scheduling the event to the
    #: respective communication channel.
    message_topic: Optional[str]

    #: Information, which outer message infrastructure shall handle messages for
    #: the :py:class:`EventElement`. Refers to a :py:class:`Submodel`,
    #: :py:class:`SubmodelElementList`, :py:class:`SubmodelElementCollection` or
    #: :py:class:`Entity`, which contains :py:class:`DataElement`'s describing
    #: the proprietary specification for the message broker.
    #:
    #: .. note::
    #:
    #:     For different message infrastructure, e.g., OPC UA or MQTT or AMQP, this
    #:     proprietary specification could be standardized by having respective Submodels.
    message_broker: Optional["Reference"]

    #: Timestamp in UTC, when the last event was received (input direction) or sent
    #: (output direction).
    last_update: Optional[str]

    #: For input direction, reports on the maximum frequency, the software entity behind
    #: the respective Referable can handle input events.
    #:
    #: For output events, specifies the maximum frequency of outputting this event to
    #: an outer infrastructure.
    #:
    #: Might be not specified, that is, there is no minimum interval.
    min_interval: Optional[str]

    #: For input direction: not applicable.
    #:
    #: For output direction: maximum interval in time, the respective Referable shall send
    #: an update of the status of the event, even if no other trigger condition for
    #: the event was not met.
    #:
    #: Might be not specified, that is, there is no maximum interval
    max_interval: Optional[str]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        yield self.observed

        if self.message_broker is not None:
            yield self.message_broker

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        yield self.observed

        yield from self.observed.descend()

        if self.message_broker is not None:
            yield self.message_broker

            yield from self.message_broker.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_basic_event_element(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_basic_event_element_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_basic_event_element(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_basic_event_element_with_context(self, context)

    def __init__(
        self,
        observed: "Reference",
        direction: "Direction",
        state: "StateOfEvent",
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        message_topic: Optional[str] = None,
        message_broker: Optional["Reference"] = None,
        last_update: Optional[str] = None,
        min_interval: Optional[str] = None,
        max_interval: Optional[str] = None,
    ) -> None:
        """Initialize with the given values."""
        EventElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.observed = observed
        self.direction = direction
        self.state = state
        self.message_topic = message_topic
        self.message_broker = message_broker
        self.last_update = last_update
        self.min_interval = min_interval
        self.max_interval = max_interval


class Operation(SubmodelElement):
    """
    An operation is a submodel element with input and output variables.

    :constraint AASd-134:
        .. _constraint_AASd-134:

        For an :py:class:`Operation` the :py:attr:`Referable.id_short` of all
        :py:attr:`OperationVariable.value`'s in
        :py:attr:`input_variables`, :py:attr:`output_variables`
        and :py:attr:`inoutput_variables` shall be unique.
    """

    #: Input parameter of the operation.
    input_variables: Optional[List["OperationVariable"]]

    #: Output parameter of the operation.
    output_variables: Optional[List["OperationVariable"]]

    #: Parameter that is input and output of the operation.
    inoutput_variables: Optional[List["OperationVariable"]]

    def over_input_variables_or_empty(self) -> Iterator["OperationVariable"]:
        """Yield from :py:attr:`.input_variables` if set."""
        if self.input_variables is not None:
            yield from self.input_variables

    def over_output_variables_or_empty(self) -> Iterator["OperationVariable"]:
        """Yield from :py:attr:`.output_variables` if set."""
        if self.output_variables is not None:
            yield from self.output_variables

    def over_inoutput_variables_or_empty(self) -> Iterator["OperationVariable"]:
        """Yield from :py:attr:`.inoutput_variables` if set."""
        if self.inoutput_variables is not None:
            yield from self.inoutput_variables

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.input_variables is not None:
            yield from self.input_variables

        if self.output_variables is not None:
            yield from self.output_variables

        if self.inoutput_variables is not None:
            yield from self.inoutput_variables

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

        if self.input_variables is not None:
            for yet_yet_yet_yet_yet_another_item in self.input_variables:
                yield yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_another_item.descend()

        if self.output_variables is not None:
            for yet_yet_yet_yet_yet_yet_another_item in self.output_variables:
                yield yet_yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_yet_another_item.descend()

        if self.inoutput_variables is not None:
            for yet_yet_yet_yet_yet_yet_yet_another_item in self.inoutput_variables:
                yield yet_yet_yet_yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_operation(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_operation_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_operation(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_operation_with_context(self, context)

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        input_variables: Optional[List["OperationVariable"]] = None,
        output_variables: Optional[List["OperationVariable"]] = None,
        inoutput_variables: Optional[List["OperationVariable"]] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )
        self.input_variables = input_variables
        self.output_variables = output_variables
        self.inoutput_variables = inoutput_variables


class OperationVariable(Class):
    """
    The value of an operation variable is a submodel element that is used as input
    and/or output variable of an operation.
    """

    #: Describes an argument or result of an operation via a submodel element
    value: "SubmodelElement"

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        yield self.value

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        yield self.value

        yield from self.value.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_operation_variable(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_operation_variable_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_operation_variable(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_operation_variable_with_context(self, context)

    def __init__(self, value: "SubmodelElement") -> None:
        """Initialize with the given values."""
        self.value = value


class Capability(SubmodelElement):
    """
    A capability is the implementation-independent description of the potential of an
    asset to achieve a certain effect in the physical or virtual world.

    .. note::

        The :py:attr:`semantic_id` of a capability is typically an ontology.
        Thus, reasoning on capabilities is enabled.
    """

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.semantic_id is not None:
            yield self.semantic_id

        if self.supplemental_semantic_ids is not None:
            yield from self.supplemental_semantic_ids

        if self.qualifiers is not None:
            yield from self.qualifiers

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.semantic_id is not None:
            yield self.semantic_id

            yield from self.semantic_id.descend()

        if self.supplemental_semantic_ids is not None:
            for yet_yet_another_item in self.supplemental_semantic_ids:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.qualifiers is not None:
            for yet_yet_yet_another_item in self.qualifiers:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_yet_yet_another_item

                yield from yet_yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_capability(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_capability_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_capability(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_capability_with_context(self, context)

    def __init__(
        self,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        semantic_id: Optional["Reference"] = None,
        supplemental_semantic_ids: Optional[List["Reference"]] = None,
        qualifiers: Optional[List["Qualifier"]] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
    ) -> None:
        """Initialize with the given values."""
        SubmodelElement.__init__(
            self,
            extensions,
            category,
            id_short,
            display_name,
            description,
            semantic_id,
            supplemental_semantic_ids,
            qualifiers,
            embedded_data_specifications,
        )


class ConceptDescription(Identifiable, HasDataSpecification):
    """
    The semantics of a property or other elements that may have a semantic description
    is defined by a concept description.

    The description of the concept should follow a standardized schema (realized as
    data specification template).

    :constraint AASc-3a-004:
        .. _constraint_AASc-3a-004:

        For a :py:class:`ConceptDescription` with :py:attr:`category` ``PROPERTY`` or
        ``VALUE`` using data specification IEC61360,
        the :py:attr:`DataSpecificationIEC61360.data_type` 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``.

        .. note::

            Note: categories are deprecated since V3.0 of Part 1a of the document series
            "Details of the Asset Administration Shell".

    :constraint AASc-3a-005:
        .. _constraint_AASc-3a-005:

        For a :py:class:`ConceptDescription` with :py:attr:`category` ``REFERENCE``
        using data specification template IEC61360,
        the :py:attr:`DataSpecificationIEC61360.data_type` shall be
        one of: ``STRING``, ``IRI``, ``IRDI``.

        .. note::

            Note: categories are deprecated since V3.0 of Part 1a of the document series
            "Details of the Asset Administration Shell".

    :constraint AASc-3a-006:
        .. _constraint_AASc-3a-006:

        For a :py:class:`ConceptDescription` with :py:attr:`category` ``DOCUMENT``
        using data specification IEC61360,
        the :py:attr:`DataSpecificationIEC61360.data_type` shall be one of ``FILE``,
        ``BLOB``, ``HTML``

        .. note::

            Categories are deprecated since V3.0 of Part 1a of the document series
            "Details of the Asset Administration Shell".

    :constraint AASc-3a-007:
        .. _constraint_AASc-3a-007:

        For a :py:class:`ConceptDescription` with :py:attr:`category` ``QUALIFIER_TYPE``
        using data specification IEC61360,
        the :py:attr:`DataSpecificationIEC61360.data_type` is mandatory and shall be
        defined.

        .. note::

            Categories are deprecated since V3.0 of Part 1a of the document series
            "Details of the Asset Administration Shell".

    :constraint AASc-3a-008:
        .. _constraint_AASc-3a-008:

        For a :py:class:`ConceptDescription` using data specification template IEC61360,
        :py:attr:`DataSpecificationIEC61360.definition` is mandatory and shall be
        defined at least in English.

        Exception: The concept description describes a value, i.e.
        :py:attr:`DataSpecificationIEC61360.value` is defined.

    :constraint AASc-3a-003:
        .. _constraint_AASc-3a-003:

        For a :py:class:`ConceptDescription` using data specification template IEC61360,
        referenced via :py:attr:`DataSpecificationIEC61360.value_list`
        :py:attr:`ValueReferencePair.value_id`
        the :py:attr:`DataSpecificationIEC61360.value` shall be set.
    """

    #: Reference to an external definition the concept is compatible to or was derived
    #: from.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    #:
    #: .. note::
    #:
    #:     Compare to is-case-of relationship in ISO 13584-32 & IEC EN 61360
    is_case_of: Optional[List["Reference"]]

    def over_is_case_of_or_empty(self) -> Iterator["Reference"]:
        """Yield from :py:attr:`.is_case_of` if set."""
        if self.is_case_of is not None:
            yield from self.is_case_of

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.extensions is not None:
            yield from self.extensions

        if self.display_name is not None:
            yield from self.display_name

        if self.description is not None:
            yield from self.description

        if self.administration is not None:
            yield self.administration

        if self.embedded_data_specifications is not None:
            yield from self.embedded_data_specifications

        if self.is_case_of is not None:
            yield from self.is_case_of

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.extensions is not None:
            for an_item in self.extensions:
                yield an_item

                yield from an_item.descend()

        if self.display_name is not None:
            for another_item in self.display_name:
                yield another_item

                yield from another_item.descend()

        if self.description is not None:
            for yet_another_item in self.description:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.administration is not None:
            yield self.administration

            yield from self.administration.descend()

        if self.embedded_data_specifications is not None:
            for yet_yet_another_item in self.embedded_data_specifications:
                yield yet_yet_another_item

                yield from yet_yet_another_item.descend()

        if self.is_case_of is not None:
            for yet_yet_yet_another_item in self.is_case_of:
                yield yet_yet_yet_another_item

                yield from yet_yet_yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_concept_description(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_concept_description_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_concept_description(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_concept_description_with_context(self, context)

    def __init__(
        self,
        id: str,
        extensions: Optional[List["Extension"]] = None,
        category: Optional[str] = None,
        id_short: Optional[str] = None,
        display_name: Optional[List["LangStringNameType"]] = None,
        description: Optional[List["LangStringTextType"]] = None,
        administration: Optional["AdministrativeInformation"] = None,
        embedded_data_specifications: Optional[
            List["EmbeddedDataSpecification"]
        ] = None,
        is_case_of: Optional[List["Reference"]] = None,
    ) -> None:
        """Initialize with the given values."""
        Identifiable.__init__(
            self,
            id,
            extensions,
            category,
            id_short,
            display_name,
            description,
            administration,
        )
        HasDataSpecification.__init__(self, embedded_data_specifications)
        self.is_case_of = is_case_of


class ReferenceTypes(enum.Enum):
    """Reference types"""

    #: External reference.
    EXTERNAL_REFERENCE = "ExternalReference"

    #: Model reference.
    MODEL_REFERENCE = "ModelReference"


class Reference(Class):
    """
    Reference to either a model element of the same or another AAS or to an external
    entity.

    A reference is an ordered list of keys.

    A model reference is an ordered list of keys, each key referencing an element. The
    complete list of keys may for example be concatenated to a path that then gives
    unique access to an element.

    An external reference is a reference to an external entity.

    :constraint AASd-121:
        .. _constraint_AASd-121:

        For :py:class:`Reference`'s the value of :py:attr:`Key.type` of the first key of "
        :py:attr:`keys` shall be one of :py:attr:`.constants.GLOBALLY_IDENTIFIABLES`.

    :constraint AASd-122:
        .. _constraint_AASd-122:

        For external references, i.e. :py:class:`Reference`'s with
        :py:attr:`type` = :py:attr:`ReferenceTypes.EXTERNAL_REFERENCE`, the value
        of :py:attr:`Key.type` of the first key of :py:attr:`keys` shall be one of
        :py:attr:`.constants.GENERIC_GLOBALLY_IDENTIFIABLES`.

    :constraint AASd-123:
        .. _constraint_AASd-123:

        For model references, i.e. :py:class:`Reference`'s with
        :py:attr:`type` = :py:attr:`ReferenceTypes.MODEL_REFERENCE`, the value
        of :py:attr:`Key.type` of the first key of :py:attr:`keys` shall be one of
        :py:attr:`.constants.AAS_IDENTIFIABLES`.

    :constraint AASd-124:
        .. _constraint_AASd-124:

        For external references, i.e. :py:class:`Reference`'s with
        :py:attr:`type` = :py:attr:`ReferenceTypes.EXTERNAL_REFERENCE`, the last
        key of :py:attr:`keys` shall be either one of
        :py:attr:`.constants.GENERIC_GLOBALLY_IDENTIFIABLES` or one of
        :py:attr:`.constants.GENERIC_FRAGMENT_KEYS`.

    :constraint AASd-125:
        .. _constraint_AASd-125:

        For model references, i.e. :py:class:`Reference`'s with
        :py:attr:`type` = :py:attr:`ReferenceTypes.MODEL_REFERENCE`, with more
        than one key in :py:attr:`keys` the value of :py:attr:`Key.type`
        of each of the keys following the first
        key of :py:attr:`keys` shall be one of :py:attr:`.constants.FRAGMENT_KEYS`.

        .. note::

            :ref:`Constraint AASd-125 <constraint_AASd-125>` ensures that the shortest path is used.

    :constraint AASd-126:
        .. _constraint_AASd-126:

        For model references, i.e. :py:class:`Reference`'s with
        :py:attr:`type` = :py:attr:`ReferenceTypes.MODEL_REFERENCE`, with more
        than one key in :py:attr:`keys` the value of :py:attr:`Key.type`
        of the last key in the reference key chain may be
        one of :py:attr:`.constants.GENERIC_FRAGMENT_KEYS` or no key at all
        shall have a value out of :py:attr:`.constants.GENERIC_FRAGMENT_KEYS`.

    :constraint AASd-127:
        .. _constraint_AASd-127:

        For model references, i.e. :py:class:`Reference`'s with
        :py:attr:`type` = :py:attr:`ReferenceTypes.MODEL_REFERENCE`, with more
        than one key in :py:attr:`keys` a key with :py:attr:`Key.type`
        :py:attr:`KeyTypes.FRAGMENT_REFERENCE` shall be preceded by a key with
        :py:attr:`Key.type` :py:attr:`KeyTypes.FILE` or :py:attr:`KeyTypes.BLOB`. All other
        AAS fragments, i.e. :py:attr:`Key.type` values
        out of :py:attr:`.constants.AAS_SUBMODEL_ELEMENTS_AS_KEYS`, do not support fragments.

        .. note::

            Which kind of fragments are supported depends on the content type and the
            specification of allowed fragment identifiers for the corresponding resource
            being referenced via the reference.

    :constraint AASd-128:
        .. _constraint_AASd-128:

        For model references, i.e. :py:class:`Reference`'s with
        :py:attr:`type` = :py:attr:`ReferenceTypes.MODEL_REFERENCE`, the
        :py:attr:`Key.value` of a :py:class:`Key` preceded by a :py:class:`Key` with
        :py:attr:`Key.type` = :py:attr:`KeyTypes.SUBMODEL_ELEMENT_LIST` is an integer
        number denoting the position in the array of the submodel element list.
    """

    #: Type of the reference.
    #:
    #: Denotes, whether reference is an external reference or a model reference.
    type: "ReferenceTypes"

    #: :py:attr:`HasSemantics.semantic_id` of the referenced model element
    #: (:py:attr:`type` = :py:attr:`ReferenceTypes.MODEL_REFERENCE`).
    #:
    #: For external references there typically is no semantic ID.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a external reference.
    referred_semantic_id: Optional["Reference"]

    #: Unique references in their name space.
    keys: List["Key"]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.referred_semantic_id is not None:
            yield self.referred_semantic_id

        yield from self.keys

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.referred_semantic_id is not None:
            yield self.referred_semantic_id

            yield from self.referred_semantic_id.descend()

        for an_item in self.keys:
            yield an_item

            yield from an_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_reference(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_reference_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_reference(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_reference_with_context(self, context)

    def __init__(
        self,
        type: "ReferenceTypes",
        keys: List["Key"],
        referred_semantic_id: Optional["Reference"] = None,
    ) -> None:
        """Initialize with the given values."""
        self.type = type
        self.keys = keys
        self.referred_semantic_id = referred_semantic_id


class Key(Class):
    """A key is a reference to an element by its ID."""

    #: Denotes which kind of entity is referenced.
    #:
    #: In case :py:attr:`type` = :py:attr:`KeyTypes.GLOBAL_REFERENCE`,
    #: the key represents a reference to a source that can be globally identified.
    #:
    #: In case :py:attr:`type` = :py:attr:`KeyTypes.FRAGMENT_REFERENCE` the key represents
    #: a bookmark or a similar local identifier within its parent element as specified
    #: by the key that precedes this key.
    #:
    #: In all other cases the key references a model element of the same or of another AAS.
    #: The name of the model element is explicitly listed.
    type: "KeyTypes"

    #: The key value, for example an IRDI or an URI
    value: str

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_key(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_key_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_key(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_key_with_context(self, context)

    def __init__(self, type: "KeyTypes", value: str) -> None:
        """Initialize with the given values."""
        self.type = type
        self.value = value


class KeyTypes(enum.Enum):
    """Enumeration of different key value types within a key."""

    ANNOTATED_RELATIONSHIP_ELEMENT = "AnnotatedRelationshipElement"

    ASSET_ADMINISTRATION_SHELL = "AssetAdministrationShell"

    BASIC_EVENT_ELEMENT = "BasicEventElement"

    BLOB = "Blob"

    CAPABILITY = "Capability"

    CONCEPT_DESCRIPTION = "ConceptDescription"

    #: Data element.
    #:
    #: .. note::
    #:
    #:     Data Element is abstract, *i.e.* if a key uses :py:attr:`DATA_ELEMENT`
    #:     the reference may be a Property, a File etc.
    DATA_ELEMENT = "DataElement"

    ENTITY = "Entity"

    #: Event.
    #:
    #: .. note::
    #:
    #:     :py:class:`EventElement` is abstract.
    EVENT_ELEMENT = "EventElement"

    FILE = "File"

    #: Bookmark or a similar local identifier of a subordinate part of
    #: a primary resource
    FRAGMENT_REFERENCE = "FragmentReference"

    GLOBAL_REFERENCE = "GlobalReference"

    #: Identifiable.
    #:
    #: .. note::
    #:
    #:     Identifiable is abstract, i.e. if a key uses “Identifiable” the reference
    #:     may be an Asset Administration Shell, a Submodel or a Concept Description.
    IDENTIFIABLE = "Identifiable"

    #: Property with a value that can be provided in multiple languages
    MULTI_LANGUAGE_PROPERTY = "MultiLanguageProperty"

    OPERATION = "Operation"

    PROPERTY = "Property"

    #: Range with min and max
    RANGE = "Range"

    REFERABLE = "Referable"

    #: Reference
    REFERENCE_ELEMENT = "ReferenceElement"

    #: Relationship
    RELATIONSHIP_ELEMENT = "RelationshipElement"

    SUBMODEL = "Submodel"

    #: Submodel Element
    #:
    #: .. note::
    #:
    #:     Submodel Element is abstract, *i.e.* if a key uses :py:attr:`SUBMODEL_ELEMENT`
    #:     the reference may be a :py:class:`Property`, an :py:class:`Operation` etc.
    SUBMODEL_ELEMENT = "SubmodelElement"

    #: Struct of Submodel Elements
    SUBMODEL_ELEMENT_COLLECTION = "SubmodelElementCollection"

    #: List of Submodel Elements
    SUBMODEL_ELEMENT_LIST = "SubmodelElementList"


class DataTypeDefXSD(enum.Enum):
    """Enumeration listing all XSD anySimpleTypes"""

    ANY_URI = "xs:anyURI"

    BASE_64_BINARY = "xs:base64Binary"

    BOOLEAN = "xs:boolean"

    BYTE = "xs:byte"

    DATE = "xs:date"

    DATE_TIME = "xs:dateTime"

    DECIMAL = "xs:decimal"

    DOUBLE = "xs:double"

    DURATION = "xs:duration"

    FLOAT = "xs:float"

    G_DAY = "xs:gDay"

    G_MONTH = "xs:gMonth"

    G_MONTH_DAY = "xs:gMonthDay"

    G_YEAR = "xs:gYear"

    G_YEAR_MONTH = "xs:gYearMonth"

    HEX_BINARY = "xs:hexBinary"

    INT = "xs:int"

    INTEGER = "xs:integer"

    LONG = "xs:long"

    NEGATIVE_INTEGER = "xs:negativeInteger"

    NON_NEGATIVE_INTEGER = "xs:nonNegativeInteger"

    NON_POSITIVE_INTEGER = "xs:nonPositiveInteger"

    POSITIVE_INTEGER = "xs:positiveInteger"

    SHORT = "xs:short"

    STRING = "xs:string"

    TIME = "xs:time"

    UNSIGNED_BYTE = "xs:unsignedByte"

    UNSIGNED_INT = "xs:unsignedInt"

    UNSIGNED_LONG = "xs:unsignedLong"

    UNSIGNED_SHORT = "xs:unsignedShort"


class AbstractLangString(Class):
    """Strings with language tags"""

    #: Language tag conforming to BCP 47
    language: str

    #: Text in the :py:attr:`language`
    text: str

    def __init__(self, language: str, text: str) -> None:
        """Initialize with the given values."""
        self.language = language
        self.text = text


class LangStringNameType(AbstractLangString):
    """
    String with length 128 maximum and minimum 1 characters and with language tags
    """

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_lang_string_name_type(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_lang_string_name_type_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_lang_string_name_type(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_lang_string_name_type_with_context(self, context)

    def __init__(self, language: str, text: str) -> None:
        """Initialize with the given values."""
        AbstractLangString.__init__(self, language, text)


class LangStringTextType(AbstractLangString):
    """
    String with length 1023 maximum and minimum 1 characters and with language tags
    """

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_lang_string_text_type(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_lang_string_text_type_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_lang_string_text_type(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_lang_string_text_type_with_context(self, context)

    def __init__(self, language: str, text: str) -> None:
        """Initialize with the given values."""
        AbstractLangString.__init__(self, language, text)


class Environment(Class):
    """
    Container for the sets of different identifiables.

    .. note::

        w.r.t. file exchange: There is exactly one environment independent on how many
        files the contained elements are split. If the file is split then there
        shall be no element with the same identifier in two different files.
    """

    #: Asset administration shell
    asset_administration_shells: Optional[List["AssetAdministrationShell"]]

    #: Submodel
    submodels: Optional[List["Submodel"]]

    #: Concept description
    concept_descriptions: Optional[List["ConceptDescription"]]

    def over_asset_administration_shells_or_empty(
        self,
    ) -> Iterator["AssetAdministrationShell"]:
        """Yield from :py:attr:`.asset_administration_shells` if set."""
        if self.asset_administration_shells is not None:
            yield from self.asset_administration_shells

    def over_submodels_or_empty(self) -> Iterator["Submodel"]:
        """Yield from :py:attr:`.submodels` if set."""
        if self.submodels is not None:
            yield from self.submodels

    def over_concept_descriptions_or_empty(self) -> Iterator["ConceptDescription"]:
        """Yield from :py:attr:`.concept_descriptions` if set."""
        if self.concept_descriptions is not None:
            yield from self.concept_descriptions

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        if self.asset_administration_shells is not None:
            yield from self.asset_administration_shells

        if self.submodels is not None:
            yield from self.submodels

        if self.concept_descriptions is not None:
            yield from self.concept_descriptions

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        if self.asset_administration_shells is not None:
            for an_item in self.asset_administration_shells:
                yield an_item

                yield from an_item.descend()

        if self.submodels is not None:
            for another_item in self.submodels:
                yield another_item

                yield from another_item.descend()

        if self.concept_descriptions is not None:
            for yet_another_item in self.concept_descriptions:
                yield yet_another_item

                yield from yet_another_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_environment(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_environment_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_environment(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_environment_with_context(self, context)

    def __init__(
        self,
        asset_administration_shells: Optional[List["AssetAdministrationShell"]] = None,
        submodels: Optional[List["Submodel"]] = None,
        concept_descriptions: Optional[List["ConceptDescription"]] = None,
    ) -> None:
        """Initialize with the given values."""
        self.asset_administration_shells = asset_administration_shells
        self.submodels = submodels
        self.concept_descriptions = concept_descriptions


class DataSpecificationContent(Class):
    """
    Data specification content is part of a data specification template and defines
    which additional attributes shall be added to the element instance that references
    the data specification template and meta information about the template itself.

    :constraint AASc-3a-050:
        .. _constraint_AASc-3a-050:

        If the :py:class:`DataSpecificationIEC61360` is used
        for an element, the value of
        :py:attr:`HasDataSpecification.embedded_data_specifications`
        shall contain the global reference to the IRI of the corresponding
        data specification template
        https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
    """


class EmbeddedDataSpecification(Class):
    """Embed the content of a data specification."""

    #: Reference to the data specification
    data_specification: "Reference"

    #: Actual content of the data specification
    data_specification_content: "DataSpecificationContent"

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        yield self.data_specification

        yield self.data_specification_content

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        yield self.data_specification

        yield from self.data_specification.descend()

        yield self.data_specification_content

        yield from self.data_specification_content.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_embedded_data_specification(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_embedded_data_specification_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_embedded_data_specification(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_embedded_data_specification_with_context(
            self, context
        )

    def __init__(
        self,
        data_specification: "Reference",
        data_specification_content: "DataSpecificationContent",
    ) -> None:
        """Initialize with the given values."""
        self.data_specification = data_specification
        self.data_specification_content = data_specification_content


class DataTypeIEC61360(enum.Enum):
    # pylint: disable=missing-class-docstring

    #: values containing a calendar date, conformant to ISO 8601:2004 Format yyyy-mm-dd
    #: Example from IEC 61360-1:2017: "1999-05-31" is the [DATE] representation of:
    #: "31 May 1999".
    DATE = "DATE"

    #: values consisting of sequence of characters but cannot be translated into other
    #: languages
    STRING = "STRING"

    #: values containing string but shall be represented as different string in different
    #: languages
    STRING_TRANSLATABLE = "STRING_TRANSLATABLE"

    #: values containing values that are measure of type INTEGER. In addition such a value
    #: comes with a physical unit.
    INTEGER_MEASURE = "INTEGER_MEASURE"

    #: values containing values of type INTEGER but are no currencies or measures
    INTEGER_COUNT = "INTEGER_COUNT"

    #: values containing values of type INTEGER that are currencies
    INTEGER_CURRENCY = "INTEGER_CURRENCY"

    #: values containing values that are measures of type REAL. In addition such a value
    #: comes with a physical unit.
    REAL_MEASURE = "REAL_MEASURE"

    #: values containing numbers that can be written as a terminating or non-terminating
    #: decimal; a rational or irrational number but are no currencies or measures
    REAL_COUNT = "REAL_COUNT"

    #: values containing values of type REAL that are currencies
    REAL_CURRENCY = "REAL_CURRENCY"

    #: values representing truth of logic or Boolean algebra (TRUE, FALSE)
    BOOLEAN = "BOOLEAN"

    #: values containing values of type STRING conformant to Rfc 3987
    #:
    #: .. note::
    #:
    #:     In IEC61360-1 (2017) only URI is supported.
    #:     An IRI type allows in particular to express an URL or an URI.
    IRI = "IRI"

    #: values conforming to ISO/IEC 11179 series global identifier sequences
    #:
    #: IRDI can be used instead of the more specific data types ICID or ISO29002_IRDI.
    #:
    #: ICID values are value conformant to an IRDI, where the delimiter between RAI and ID
    #: is “#” while the delimiter between DI and VI is confined to “##”
    #:
    #: ISO29002_IRDI values are values containing a global identifier that identifies an
    #: administrated item in a registry. The structure of this identifier complies with
    #: identifier syntax defined in ISO/TS 29002-5. The identifier shall fulfil the
    #: requirements specified in ISO/TS 29002-5 for an "international registration data
    #: identifier" (IRDI).
    IRDI = "IRDI"

    #: values containing values of type rational
    RATIONAL = "RATIONAL"

    #: values containing values of type rational. In addition such a value comes with a
    #: physical unit.
    RATIONAL_MEASURE = "RATIONAL_MEASURE"

    #: values containing a time, conformant to ISO 8601:2004 but restricted to what is
    #: allowed in the corresponding type in xml.
    #:
    #: Format hh:mm (ECLASS)
    #:
    #: Example from IEC 61360-1:2017: "13:20:00-05:00" is the [TIME] representation of:
    #: 1.20 p.m. for Eastern Standard Time, which is 5 hours behind Coordinated
    #: Universal Time (UTC).
    TIME = "TIME"

    #: values containing a time, conformant to ISO 8601:2004 but restricted to what is
    #: allowed in the corresponding type in xml.
    #:
    #: Format yyyy-mm-dd hh:mm (ECLASS)
    TIMESTAMP = "TIMESTAMP"

    #: values containing an address to a file. The values are of type URI and can represent
    #: an absolute or relative path.
    #:
    #: .. note::
    #:
    #:     IEC61360 does not support the file type.
    FILE = "FILE"

    #: Values containing string with any sequence of characters, using the syntax of HTML5
    #: (see W3C Recommendation 28:2014)
    HTML = "HTML"

    #: values containing the content of a file. Values may be binaries.
    #:
    #: HTML conformant to HTML5 is a special blob.
    #:
    #: In IEC61360 binary is for a sequence of bits, each bit being represented by “0” and
    #: “1” only. A binary is a blob but a blob may also contain other source code.
    BLOB = "BLOB"


class LevelType(Class):
    """
    Value represented by up to four variants of a numeric value in a specific role:
    ``MIN``, ``NOM``, ``TYP`` and ``MAX``. True means that the value is available,
    false means the value is not available.

    EXAMPLE from [IEC61360-1]: In the case of having a property which is
    of the LEVEL_TYPE min/max − expressing a range − only those two values
    need to be provided.

    .. note::

        This is how AAS deals with the following combinations of level types:

        * Either all attributes are false. In this case the concept is mapped
          to a :py:class:`Property` and level type is ignored.
        * At most one of the attributes is set to true. In this case
          the concept is mapped to a :py:class:`Property`.
        * Min and max are set to true. In this case the concept is mapped
          to a :py:class:`Range`.
        * More than one attribute is set to true but not min and max only
          (see second case). In this case the concept is mapped
          to a :py:class:`SubmodelElementCollection` with the corresponding
          number of Properties.
          Example: If attribute :py:attr:`min` and :py:attr:`nom` are set to true
          then the concept is mapped to a :py:class:`SubmodelElementCollection`
          with two Properties within: min and nom.
          The data type of both Properties is the same.

    .. note::

        In the cases 2. and 4. the :py:attr:`Property.semantic_id` of the Property
        or Properties within the :py:class:`SubmodelElementCollection` needs to include
        information about the level type. Otherwise, the semantics is not described
        in a unique way. Please refer to the specification.
    """

    #: Minimum of the value
    min: bool

    #: Nominal value (value as designated)
    nom: bool

    #: Value as typically present
    typ: bool

    #: Maximum of the value
    max: bool

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_level_type(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_level_type_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_level_type(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_level_type_with_context(self, context)

    def __init__(self, min: bool, nom: bool, typ: bool, max: bool) -> None:
        """Initialize with the given values."""
        self.min = min
        self.nom = nom
        self.typ = typ
        self.max = max


class ValueReferencePair(Class):
    """
    A value reference pair within a value list. Each value has a global unique id
    defining its semantic.
    """

    #: The value of the referenced concept definition of the value in :py:attr:`value_id`.
    value: str

    #: Global unique id of the value.
    #:
    #: .. note::
    #:
    #:     It is recommended to use a global reference.
    value_id: "Reference"

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        yield self.value_id

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        yield self.value_id

        yield from self.value_id.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_value_reference_pair(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_value_reference_pair_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_value_reference_pair(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_value_reference_pair_with_context(self, context)

    def __init__(self, value: str, value_id: "Reference") -> None:
        """Initialize with the given values."""
        self.value = value
        self.value_id = value_id


class ValueList(Class):
    """A set of value reference pairs."""

    #: A pair of a value together with its global unique id.
    value_reference_pairs: List["ValueReferencePair"]

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        yield from self.value_reference_pairs

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        for an_item in self.value_reference_pairs:
            yield an_item

            yield from an_item.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_value_list(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_value_list_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_value_list(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_value_list_with_context(self, context)

    def __init__(self, value_reference_pairs: List["ValueReferencePair"]) -> None:
        """Initialize with the given values."""
        self.value_reference_pairs = value_reference_pairs


class LangStringPreferredNameTypeIEC61360(AbstractLangString):
    """
    String with length 255 maximum and minimum 1 characters and with language tags

    .. note::

        It is advised to keep the length of the name limited to 35 characters.
    """

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_lang_string_preferred_name_type_iec_61360(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_lang_string_preferred_name_type_iec_61360_with_context(
            self, context
        )

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_lang_string_preferred_name_type_iec_61360(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_lang_string_preferred_name_type_iec_61360_with_context(
            self, context
        )

    def __init__(self, language: str, text: str) -> None:
        """Initialize with the given values."""
        AbstractLangString.__init__(self, language, text)


class LangStringShortNameTypeIEC61360(AbstractLangString):
    """
    String with length 18 maximum and minimum 1 characters and with language tags
    """

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_lang_string_short_name_type_iec_61360(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_lang_string_short_name_type_iec_61360_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_lang_string_short_name_type_iec_61360(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_lang_string_short_name_type_iec_61360_with_context(
            self, context
        )

    def __init__(self, language: str, text: str) -> None:
        """Initialize with the given values."""
        AbstractLangString.__init__(self, language, text)


class LangStringDefinitionTypeIEC61360(AbstractLangString):
    """
    String with length 1023 maximum and minimum 1 characters and with language tags
    """

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        # No descendable properties
        return
        # For this uncommon return-yield construction, see:
        # https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
        # noinspection PyUnreachableCode
        yield

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_lang_string_definition_type_iec_61360(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_lang_string_definition_type_iec_61360_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_lang_string_definition_type_iec_61360(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_lang_string_definition_type_iec_61360_with_context(
            self, context
        )

    def __init__(self, language: str, text: str) -> None:
        """Initialize with the given values."""
        AbstractLangString.__init__(self, language, text)


class DataSpecificationIEC61360(DataSpecificationContent):
    """
    Content of data specification template for concept descriptions for properties,
    values and value lists conformant to IEC 61360.

    .. note::

        IEC61360 requires also a globally unique identifier for a concept
        description. This ID is not part of the data specification template.
        Instead the :py:attr:`ConceptDescription.id` as inherited via
        :py:class:`Identifiable` is used. Same holds for administrative
        information like the version and revision.

    .. note::

        :py:attr:`ConceptDescription.id_short` and :py:attr:`short_name` are very
        similar. However, in this case the decision was to add
        :py:attr:`short_name` explicitly to the data specification. Same holds for
        :py:attr:`ConceptDescription.display_name` and
        :py:attr:`preferred_name`. Same holds for
        :py:attr:`ConceptDescription.description` and :py:attr:`definition`.

    :constraint AASc-3a-010:
        .. _constraint_AASc-3a-010:

        If :py:attr:`value` is not empty then :py:attr:`value_list` shall be empty
        and vice versa.

        .. note::

            It is also possible that both :py:attr:`value` and :py:attr:`value_list` are
            empty. This is the case for concept descriptions that define the semantics
            of a property but do not have an enumeration (:py:attr:`value_list`) as
            data type.

        .. note::

            Although it is possible to define a :py:class:`ConceptDescription` for a
            :attr:´value_list`,
            it is not possible to reuse this :py:attr:`value_list`.
            It is only possible to directly add a :py:attr:`value_list` as data type
            to a specific semantic definition of a property.

    :constraint AASc-3a-009:
        .. _constraint_AASc-3a-009:

        If :py:attr:`data_type` one of:
        :py:attr:`DataTypeIEC61360.INTEGER_MEASURE`,
        :py:attr:`DataTypeIEC61360.REAL_MEASURE`,
        :py:attr:`DataTypeIEC61360.RATIONAL_MEASURE`,
        :py:attr:`DataTypeIEC61360.INTEGER_CURRENCY`,
        :py:attr:`DataTypeIEC61360.REAL_CURRENCY`, then :py:attr:`unit` or
        :py:attr:`unit_id` shall be defined.
    """

    #: Preferred name
    #:
    #: .. note::
    #:
    #:     It is advised to keep the length of the name limited to 35 characters.
    #:
    #: :constraint AASc-3a-002:
    #:     .. _constraint_AASc-3a-002:
    #:
    #:     :py:attr:`preferred_name` shall be provided at least in English.
    preferred_name: List["LangStringPreferredNameTypeIEC61360"]

    #: Short name
    short_name: Optional[List["LangStringShortNameTypeIEC61360"]]

    #: Unit
    unit: Optional[str]

    #: Unique unit id
    #:
    #: :py:attr:`unit` and :py:attr:`unit_id` need to be consistent if both attributes
    #: are set
    #:
    #: .. note::
    #:
    #:     It is recommended to use an external reference ID.
    unit_id: Optional["Reference"]

    #: Source of definition
    source_of_definition: Optional[str]

    #: Symbol
    symbol: Optional[str]

    #: Data Type
    data_type: Optional["DataTypeIEC61360"]

    #: Definition in different languages
    definition: Optional[List["LangStringDefinitionTypeIEC61360"]]

    #: Value Format
    #:
    #: .. note::
    #:
    #:     The value format is based on ISO 13584-42 and IEC 61360-2.
    value_format: Optional[str]

    #: List of allowed values
    value_list: Optional["ValueList"]

    #: Value
    value: Optional[str]

    #: Set of levels.
    level_type: Optional["LevelType"]

    def over_short_name_or_empty(self) -> Iterator["LangStringShortNameTypeIEC61360"]:
        """Yield from :py:attr:`.short_name` if set."""
        if self.short_name is not None:
            yield from self.short_name

    def over_definition_or_empty(self) -> Iterator["LangStringDefinitionTypeIEC61360"]:
        """Yield from :py:attr:`.definition` if set."""
        if self.definition is not None:
            yield from self.definition

    def descend_once(self) -> Iterator[Class]:
        """
        Iterate over the instances referenced from this instance.

        We do not recurse into the referenced instance.

        :yield: instances directly referenced from this instance
        """
        yield from self.preferred_name

        if self.short_name is not None:
            yield from self.short_name

        if self.unit_id is not None:
            yield self.unit_id

        if self.definition is not None:
            yield from self.definition

        if self.value_list is not None:
            yield self.value_list

        if self.level_type is not None:
            yield self.level_type

    def descend(self) -> Iterator[Class]:
        """
        Iterate recursively over the instances referenced from this one.

        :yield: instances recursively referenced from this instance
        """
        for an_item in self.preferred_name:
            yield an_item

            yield from an_item.descend()

        if self.short_name is not None:
            for another_item in self.short_name:
                yield another_item

                yield from another_item.descend()

        if self.unit_id is not None:
            yield self.unit_id

            yield from self.unit_id.descend()

        if self.definition is not None:
            for yet_another_item in self.definition:
                yield yet_another_item

                yield from yet_another_item.descend()

        if self.value_list is not None:
            yield self.value_list

            yield from self.value_list.descend()

        if self.level_type is not None:
            yield self.level_type

            yield from self.level_type.descend()

    def accept(self, visitor: "AbstractVisitor") -> None:
        """Dispatch the :paramref:`visitor` on this instance."""
        visitor.visit_data_specification_iec_61360(self)

    def accept_with_context(
        self, visitor: "AbstractVisitorWithContext[ContextT]", context: ContextT
    ) -> None:
        """Dispatch the :paramref:`visitor` on this instance in :paramref:`context`."""
        visitor.visit_data_specification_iec_61360_with_context(self, context)

    def transform(self, transformer: "AbstractTransformer[T]") -> T:
        """Dispatch the :paramref:`transformer` on this instance."""
        return transformer.transform_data_specification_iec_61360(self)

    def transform_with_context(
        self,
        transformer: "AbstractTransformerWithContext[ContextT, T]",
        context: ContextT,
    ) -> T:
        """
        Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
        """
        return transformer.transform_data_specification_iec_61360_with_context(
            self, context
        )

    def __init__(
        self,
        preferred_name: List["LangStringPreferredNameTypeIEC61360"],
        short_name: Optional[List["LangStringShortNameTypeIEC61360"]] = None,
        unit: Optional[str] = None,
        unit_id: Optional["Reference"] = None,
        source_of_definition: Optional[str] = None,
        symbol: Optional[str] = None,
        data_type: Optional["DataTypeIEC61360"] = None,
        definition: Optional[List["LangStringDefinitionTypeIEC61360"]] = None,
        value_format: Optional[str] = None,
        value_list: Optional["ValueList"] = None,
        value: Optional[str] = None,
        level_type: Optional["LevelType"] = None,
    ) -> None:
        """Initialize with the given values."""
        self.preferred_name = preferred_name
        self.short_name = short_name
        self.unit = unit
        self.unit_id = unit_id
        self.source_of_definition = source_of_definition
        self.symbol = symbol
        self.data_type = data_type
        self.definition = definition
        self.value_format = value_format
        self.value_list = value_list
        self.value = value
        self.level_type = level_type


class AbstractVisitor:
    """Visit the instances of the model."""

    def visit(self, that: Class) -> None:
        """Double-dispatch on :paramref:`that`."""
        that.accept(self)

    @abc.abstractmethod
    def visit_extension(self, that: Extension) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_administrative_information(self, that: AdministrativeInformation) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_qualifier(self, that: Qualifier) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_asset_administration_shell(self, that: AssetAdministrationShell) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_asset_information(self, that: AssetInformation) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_resource(self, that: Resource) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_specific_asset_id(self, that: SpecificAssetID) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_submodel(self, that: Submodel) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_relationship_element(self, that: RelationshipElement) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_submodel_element_list(self, that: SubmodelElementList) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_submodel_element_collection(
        self, that: SubmodelElementCollection
    ) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_property(self, that: Property) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_multi_language_property(self, that: MultiLanguageProperty) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_range(self, that: Range) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_reference_element(self, that: ReferenceElement) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_blob(self, that: Blob) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_file(self, that: File) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_annotated_relationship_element(
        self, that: AnnotatedRelationshipElement
    ) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_entity(self, that: Entity) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_event_payload(self, that: EventPayload) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_basic_event_element(self, that: BasicEventElement) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_operation(self, that: Operation) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_operation_variable(self, that: OperationVariable) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_capability(self, that: Capability) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_concept_description(self, that: ConceptDescription) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_reference(self, that: Reference) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_key(self, that: Key) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_name_type(self, that: LangStringNameType) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_text_type(self, that: LangStringTextType) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_environment(self, that: Environment) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_embedded_data_specification(
        self, that: EmbeddedDataSpecification
    ) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_level_type(self, that: LevelType) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_value_reference_pair(self, that: ValueReferencePair) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_value_list(self, that: ValueList) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_preferred_name_type_iec_61360(
        self, that: LangStringPreferredNameTypeIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_short_name_type_iec_61360(
        self, that: LangStringShortNameTypeIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_definition_type_iec_61360(
        self, that: LangStringDefinitionTypeIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_data_specification_iec_61360(
        self, that: DataSpecificationIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        raise NotImplementedError()


class AbstractVisitorWithContext(Generic[ContextT]):
    """Visit the instances of the model with context."""

    def visit_with_context(self, that: Class, context: ContextT) -> None:
        """Double-dispatch on :paramref:`that`."""
        that.accept_with_context(self, context)

    @abc.abstractmethod
    def visit_extension_with_context(self, that: Extension, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_administrative_information_with_context(
        self, that: AdministrativeInformation, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_qualifier_with_context(self, that: Qualifier, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_asset_administration_shell_with_context(
        self, that: AssetAdministrationShell, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_asset_information_with_context(
        self, that: AssetInformation, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_resource_with_context(self, that: Resource, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_specific_asset_id_with_context(
        self, that: SpecificAssetID, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_submodel_with_context(self, that: Submodel, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_relationship_element_with_context(
        self, that: RelationshipElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_submodel_element_list_with_context(
        self, that: SubmodelElementList, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_submodel_element_collection_with_context(
        self, that: SubmodelElementCollection, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_property_with_context(self, that: Property, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_multi_language_property_with_context(
        self, that: MultiLanguageProperty, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_range_with_context(self, that: Range, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_reference_element_with_context(
        self, that: ReferenceElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_blob_with_context(self, that: Blob, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_file_with_context(self, that: File, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_annotated_relationship_element_with_context(
        self, that: AnnotatedRelationshipElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_entity_with_context(self, that: Entity, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_event_payload_with_context(
        self, that: EventPayload, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_basic_event_element_with_context(
        self, that: BasicEventElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_operation_with_context(self, that: Operation, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_operation_variable_with_context(
        self, that: OperationVariable, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_capability_with_context(
        self, that: Capability, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_concept_description_with_context(
        self, that: ConceptDescription, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_reference_with_context(self, that: Reference, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_key_with_context(self, that: Key, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_name_type_with_context(
        self, that: LangStringNameType, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_text_type_with_context(
        self, that: LangStringTextType, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_environment_with_context(
        self, that: Environment, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_embedded_data_specification_with_context(
        self, that: EmbeddedDataSpecification, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_level_type_with_context(self, that: LevelType, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_value_reference_pair_with_context(
        self, that: ValueReferencePair, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_value_list_with_context(self, that: ValueList, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_preferred_name_type_iec_61360_with_context(
        self, that: LangStringPreferredNameTypeIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_short_name_type_iec_61360_with_context(
        self, that: LangStringShortNameTypeIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_lang_string_definition_type_iec_61360_with_context(
        self, that: LangStringDefinitionTypeIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def visit_data_specification_iec_61360_with_context(
        self, that: DataSpecificationIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()


class PassThroughVisitor(AbstractVisitor):
    """
    Visit the instances of the model without action.

    This visitor is not meant to be directly used. Instead, you usually
    inherit from it, and implement only the relevant visit methods.
    """

    def visit(self, that: Class) -> None:
        """Double-dispatch on :paramref:`that`."""
        that.accept(self)

    def visit_extension(self, that: Extension) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_administrative_information(self, that: AdministrativeInformation) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_qualifier(self, that: Qualifier) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_asset_administration_shell(self, that: AssetAdministrationShell) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_asset_information(self, that: AssetInformation) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_resource(self, that: Resource) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_specific_asset_id(self, that: SpecificAssetID) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_submodel(self, that: Submodel) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_relationship_element(self, that: RelationshipElement) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_submodel_element_list(self, that: SubmodelElementList) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_submodel_element_collection(
        self, that: SubmodelElementCollection
    ) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_property(self, that: Property) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_multi_language_property(self, that: MultiLanguageProperty) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_range(self, that: Range) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_reference_element(self, that: ReferenceElement) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_blob(self, that: Blob) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_file(self, that: File) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_annotated_relationship_element(
        self, that: AnnotatedRelationshipElement
    ) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_entity(self, that: Entity) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_event_payload(self, that: EventPayload) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_basic_event_element(self, that: BasicEventElement) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_operation(self, that: Operation) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_operation_variable(self, that: OperationVariable) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_capability(self, that: Capability) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_concept_description(self, that: ConceptDescription) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_reference(self, that: Reference) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_key(self, that: Key) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_lang_string_name_type(self, that: LangStringNameType) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_lang_string_text_type(self, that: LangStringTextType) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_environment(self, that: Environment) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_embedded_data_specification(
        self, that: EmbeddedDataSpecification
    ) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_level_type(self, that: LevelType) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_value_reference_pair(self, that: ValueReferencePair) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_value_list(self, that: ValueList) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_lang_string_preferred_name_type_iec_61360(
        self, that: LangStringPreferredNameTypeIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_lang_string_short_name_type_iec_61360(
        self, that: LangStringShortNameTypeIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_lang_string_definition_type_iec_61360(
        self, that: LangStringDefinitionTypeIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)

    def visit_data_specification_iec_61360(
        self, that: DataSpecificationIEC61360
    ) -> None:
        """Visit :paramref:`that`."""
        for another in that.descend_once():
            self.visit(another)


class PassThroughVisitorWithContext(AbstractVisitorWithContext[ContextT]):
    """
    Visit the instances of the model without action and in context.

    This visitor is not meant to be directly used. Instead, you usually
    inherit from it, and implement only the relevant visit methods.
    """

    def visit_with_context(self, that: Class, context: ContextT) -> None:
        """Double-dispatch on :paramref:`that`."""
        that.accept_with_context(self, context)

    def visit_extension_with_context(self, that: Extension, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_administrative_information_with_context(
        self, that: AdministrativeInformation, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_qualifier_with_context(self, that: Qualifier, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_asset_administration_shell_with_context(
        self, that: AssetAdministrationShell, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_asset_information_with_context(
        self, that: AssetInformation, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_resource_with_context(self, that: Resource, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_specific_asset_id_with_context(
        self, that: SpecificAssetID, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_submodel_with_context(self, that: Submodel, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_relationship_element_with_context(
        self, that: RelationshipElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_submodel_element_list_with_context(
        self, that: SubmodelElementList, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_submodel_element_collection_with_context(
        self, that: SubmodelElementCollection, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_property_with_context(self, that: Property, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_multi_language_property_with_context(
        self, that: MultiLanguageProperty, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_range_with_context(self, that: Range, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_reference_element_with_context(
        self, that: ReferenceElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_blob_with_context(self, that: Blob, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_file_with_context(self, that: File, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_annotated_relationship_element_with_context(
        self, that: AnnotatedRelationshipElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_entity_with_context(self, that: Entity, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_event_payload_with_context(
        self, that: EventPayload, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_basic_event_element_with_context(
        self, that: BasicEventElement, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_operation_with_context(self, that: Operation, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_operation_variable_with_context(
        self, that: OperationVariable, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_capability_with_context(
        self, that: Capability, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_concept_description_with_context(
        self, that: ConceptDescription, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_reference_with_context(self, that: Reference, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_key_with_context(self, that: Key, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_lang_string_name_type_with_context(
        self, that: LangStringNameType, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_lang_string_text_type_with_context(
        self, that: LangStringTextType, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_environment_with_context(
        self, that: Environment, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_embedded_data_specification_with_context(
        self, that: EmbeddedDataSpecification, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_level_type_with_context(self, that: LevelType, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_value_reference_pair_with_context(
        self, that: ValueReferencePair, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_value_list_with_context(self, that: ValueList, context: ContextT) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_lang_string_preferred_name_type_iec_61360_with_context(
        self, that: LangStringPreferredNameTypeIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_lang_string_short_name_type_iec_61360_with_context(
        self, that: LangStringShortNameTypeIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_lang_string_definition_type_iec_61360_with_context(
        self, that: LangStringDefinitionTypeIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)

    def visit_data_specification_iec_61360_with_context(
        self, that: DataSpecificationIEC61360, context: ContextT
    ) -> None:
        """Visit :paramref:`that` in :paramref:`context`."""
        for another in that.descend_once():
            self.visit_with_context(another, context)


class AbstractTransformer(Generic[T]):
    """Transform the instances of the model."""

    def transform(self, that: Class) -> T:
        """Double-dispatch on :paramref:`that`."""
        return that.transform(self)

    @abc.abstractmethod
    def transform_extension(self, that: Extension) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_administrative_information(
        self, that: AdministrativeInformation
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_qualifier(self, that: Qualifier) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_asset_administration_shell(self, that: AssetAdministrationShell) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_asset_information(self, that: AssetInformation) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_resource(self, that: Resource) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_specific_asset_id(self, that: SpecificAssetID) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_submodel(self, that: Submodel) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_relationship_element(self, that: RelationshipElement) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_submodel_element_list(self, that: SubmodelElementList) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_submodel_element_collection(
        self, that: SubmodelElementCollection
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_property(self, that: Property) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_multi_language_property(self, that: MultiLanguageProperty) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_range(self, that: Range) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_reference_element(self, that: ReferenceElement) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_blob(self, that: Blob) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_file(self, that: File) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_annotated_relationship_element(
        self, that: AnnotatedRelationshipElement
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_entity(self, that: Entity) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_event_payload(self, that: EventPayload) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_basic_event_element(self, that: BasicEventElement) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_operation(self, that: Operation) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_operation_variable(self, that: OperationVariable) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_capability(self, that: Capability) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_concept_description(self, that: ConceptDescription) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_reference(self, that: Reference) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_key(self, that: Key) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_name_type(self, that: LangStringNameType) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_text_type(self, that: LangStringTextType) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_environment(self, that: Environment) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_embedded_data_specification(
        self, that: EmbeddedDataSpecification
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_level_type(self, that: LevelType) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_value_reference_pair(self, that: ValueReferencePair) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_value_list(self, that: ValueList) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_preferred_name_type_iec_61360(
        self, that: LangStringPreferredNameTypeIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_short_name_type_iec_61360(
        self, that: LangStringShortNameTypeIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_definition_type_iec_61360(
        self, that: LangStringDefinitionTypeIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_data_specification_iec_61360(
        self, that: DataSpecificationIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        raise NotImplementedError()


class AbstractTransformerWithContext(Generic[ContextT, T]):
    """Transform the instances of the model in context."""

    def transform_with_context(self, that: Class, context: ContextT) -> T:
        """Double-dispatch on :paramref:`that`."""
        return that.transform_with_context(self, context)

    @abc.abstractmethod
    def transform_extension_with_context(self, that: Extension, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_administrative_information_with_context(
        self, that: AdministrativeInformation, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_qualifier_with_context(self, that: Qualifier, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_asset_administration_shell_with_context(
        self, that: AssetAdministrationShell, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_asset_information_with_context(
        self, that: AssetInformation, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_resource_with_context(self, that: Resource, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_specific_asset_id_with_context(
        self, that: SpecificAssetID, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_submodel_with_context(self, that: Submodel, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_relationship_element_with_context(
        self, that: RelationshipElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_submodel_element_list_with_context(
        self, that: SubmodelElementList, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_submodel_element_collection_with_context(
        self, that: SubmodelElementCollection, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_property_with_context(self, that: Property, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_multi_language_property_with_context(
        self, that: MultiLanguageProperty, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_range_with_context(self, that: Range, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_reference_element_with_context(
        self, that: ReferenceElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_blob_with_context(self, that: Blob, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_file_with_context(self, that: File, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_annotated_relationship_element_with_context(
        self, that: AnnotatedRelationshipElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_entity_with_context(self, that: Entity, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_event_payload_with_context(
        self, that: EventPayload, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_basic_event_element_with_context(
        self, that: BasicEventElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_operation_with_context(self, that: Operation, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_operation_variable_with_context(
        self, that: OperationVariable, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_capability_with_context(
        self, that: Capability, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_concept_description_with_context(
        self, that: ConceptDescription, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_reference_with_context(self, that: Reference, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_key_with_context(self, that: Key, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_name_type_with_context(
        self, that: LangStringNameType, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_text_type_with_context(
        self, that: LangStringTextType, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_environment_with_context(
        self, that: Environment, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_embedded_data_specification_with_context(
        self, that: EmbeddedDataSpecification, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_level_type_with_context(
        self, that: LevelType, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_value_reference_pair_with_context(
        self, that: ValueReferencePair, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_value_list_with_context(
        self, that: ValueList, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_preferred_name_type_iec_61360_with_context(
        self, that: LangStringPreferredNameTypeIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_short_name_type_iec_61360_with_context(
        self, that: LangStringShortNameTypeIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_lang_string_definition_type_iec_61360_with_context(
        self, that: LangStringDefinitionTypeIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()

    @abc.abstractmethod
    def transform_data_specification_iec_61360_with_context(
        self, that: DataSpecificationIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        raise NotImplementedError()


class TransformerWithDefault(AbstractTransformer[T]):
    """
    Transform the instances of the model.

    If you do not override the transformation methods, they simply
    return :py:attr:`.default`.
    """

    #: Default value which is returned if no override of the transformation
    default: T

    def __init__(self, default: T) -> None:
        """Initialize with the given :paramref:`default` value."""
        self.default = default

    def transform(self, that: Class) -> T:
        """Double-dispatch on :paramref:`that`."""
        return that.transform(self)

    def transform_extension(self, that: Extension) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_administrative_information(
        self, that: AdministrativeInformation
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_qualifier(self, that: Qualifier) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_asset_administration_shell(self, that: AssetAdministrationShell) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_asset_information(self, that: AssetInformation) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_resource(self, that: Resource) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_specific_asset_id(self, that: SpecificAssetID) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_submodel(self, that: Submodel) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_relationship_element(self, that: RelationshipElement) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_submodel_element_list(self, that: SubmodelElementList) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_submodel_element_collection(
        self, that: SubmodelElementCollection
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_property(self, that: Property) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_multi_language_property(self, that: MultiLanguageProperty) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_range(self, that: Range) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_reference_element(self, that: ReferenceElement) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_blob(self, that: Blob) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_file(self, that: File) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_annotated_relationship_element(
        self, that: AnnotatedRelationshipElement
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_entity(self, that: Entity) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_event_payload(self, that: EventPayload) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_basic_event_element(self, that: BasicEventElement) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_operation(self, that: Operation) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_operation_variable(self, that: OperationVariable) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_capability(self, that: Capability) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_concept_description(self, that: ConceptDescription) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_reference(self, that: Reference) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_key(self, that: Key) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_lang_string_name_type(self, that: LangStringNameType) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_lang_string_text_type(self, that: LangStringTextType) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_environment(self, that: Environment) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_embedded_data_specification(
        self, that: EmbeddedDataSpecification
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_level_type(self, that: LevelType) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_value_reference_pair(self, that: ValueReferencePair) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_value_list(self, that: ValueList) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_lang_string_preferred_name_type_iec_61360(
        self, that: LangStringPreferredNameTypeIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_lang_string_short_name_type_iec_61360(
        self, that: LangStringShortNameTypeIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_lang_string_definition_type_iec_61360(
        self, that: LangStringDefinitionTypeIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default

    def transform_data_specification_iec_61360(
        self, that: DataSpecificationIEC61360
    ) -> T:
        """Transform :paramref:`that`."""
        return self.default


class TransformerWithDefaultAndContext(AbstractTransformerWithContext[ContextT, T]):
    """
    Transform the instances of the model in context.

    If you do not override the transformation methods, they simply
    return :py:attr:`.default`.
    """

    #: Default value which is returned if no override of the transformation
    default: T

    def __init__(self, default: T) -> None:
        """Initialize with the given :paramref:`default` value."""
        self.default = default

    def transform_with_context(self, that: Class, context: ContextT) -> T:
        """Double-dispatch on :paramref:`that`."""
        return that.transform_with_context(self, context)

    def transform_extension_with_context(self, that: Extension, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_administrative_information_with_context(
        self, that: AdministrativeInformation, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_qualifier_with_context(self, that: Qualifier, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_asset_administration_shell_with_context(
        self, that: AssetAdministrationShell, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_asset_information_with_context(
        self, that: AssetInformation, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_resource_with_context(self, that: Resource, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_specific_asset_id_with_context(
        self, that: SpecificAssetID, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_submodel_with_context(self, that: Submodel, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_relationship_element_with_context(
        self, that: RelationshipElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_submodel_element_list_with_context(
        self, that: SubmodelElementList, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_submodel_element_collection_with_context(
        self, that: SubmodelElementCollection, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_property_with_context(self, that: Property, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_multi_language_property_with_context(
        self, that: MultiLanguageProperty, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_range_with_context(self, that: Range, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_reference_element_with_context(
        self, that: ReferenceElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_blob_with_context(self, that: Blob, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_file_with_context(self, that: File, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_annotated_relationship_element_with_context(
        self, that: AnnotatedRelationshipElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_entity_with_context(self, that: Entity, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_event_payload_with_context(
        self, that: EventPayload, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_basic_event_element_with_context(
        self, that: BasicEventElement, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_operation_with_context(self, that: Operation, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_operation_variable_with_context(
        self, that: OperationVariable, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_capability_with_context(
        self, that: Capability, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_concept_description_with_context(
        self, that: ConceptDescription, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_reference_with_context(self, that: Reference, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_key_with_context(self, that: Key, context: ContextT) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_lang_string_name_type_with_context(
        self, that: LangStringNameType, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_lang_string_text_type_with_context(
        self, that: LangStringTextType, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_environment_with_context(
        self, that: Environment, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_embedded_data_specification_with_context(
        self, that: EmbeddedDataSpecification, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_level_type_with_context(
        self, that: LevelType, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_value_reference_pair_with_context(
        self, that: ValueReferencePair, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_value_list_with_context(
        self, that: ValueList, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_lang_string_preferred_name_type_iec_61360_with_context(
        self, that: LangStringPreferredNameTypeIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_lang_string_short_name_type_iec_61360_with_context(
        self, that: LangStringShortNameTypeIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_lang_string_definition_type_iec_61360_with_context(
        self, that: LangStringDefinitionTypeIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default

    def transform_data_specification_iec_61360_with_context(
        self, that: DataSpecificationIEC61360, context: ContextT
    ) -> T:
        """Transform :paramref:`that` in :paramref:`context`."""
        return self.default


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