"""
Verify that the instances of the meta-model satisfy the invariants.
Here is an example how to verify an instance of :py:class:`aas_core3.types.Extension`:
.. code-block::
import aas_core3.types as aas_types
import aas_core3.verification as aas_verification
an_instance = aas_types.Extension(
# ... some constructor arguments ...
)
for error in aas_verification.verify(an_instance):
print(f"{error.cause} at: {error.path}")
"""
# This code has been automatically generated by aas-core-codegen.
# Do NOT edit or append.
import math
import re
import struct
import sys
from typing import (
Callable,
Iterable,
Iterator,
List,
Mapping,
Optional,
Pattern,
Sequence,
Set,
Union,
)
if sys.version_info >= (3, 8):
from typing import Final
else:
from typing_extensions import Final
from aas_core3 import (
constants as aas_constants,
types as aas_types,
)
[docs]class PropertySegment:
"""Represent a property access on a path to an erroneous value."""
#: Instance containing the property
instance: Final[aas_types.Class]
#: Name of the property
name: Final[str]
[docs] def __init__(self, instance: aas_types.Class, name: str) -> None:
"""Initialize with the given values."""
self.instance = instance
self.name = name
[docs] def __str__(self) -> str:
return f".{self.name}"
[docs]class IndexSegment:
"""Represent an index access on a path to an erroneous value."""
#: Sequence containing the item at :py:attr:`~index`
sequence: Final[Sequence[aas_types.Class]]
#: Index of the item
index: Final[int]
[docs] def __init__(self, sequence: Sequence[aas_types.Class], index: int) -> None:
"""Initialize with the given values."""
self.sequence = sequence
self.index = index
[docs] def __str__(self) -> str:
return f"[{self.index}]"
Segment = Union[PropertySegment, IndexSegment]
[docs]class Path:
"""Represent the relative path to the erroneous value."""
[docs] def __init__(self) -> None:
"""Initialize as an empty path."""
self._segments = [] # type: List[Segment]
@property
def segments(self) -> Sequence[Segment]:
"""Get the segments of the path."""
return self._segments
def _prepend(self, segment: Segment) -> None:
"""Insert the :paramref:`segment` in front of other segments."""
self._segments.insert(0, segment)
[docs] def __str__(self) -> str:
return "".join(str(segment) for segment in self._segments)
[docs]class Error:
"""Represent a verification error in the data."""
#: Human-readable description of the error
cause: Final[str]
#: Path to the erroneous value
path: Final[Path]
[docs] def __init__(self, cause: str) -> None:
"""Initialize as an error with an empty path."""
self.cause = cause
self.path = Path()
[docs] def __repr__(self) -> str:
return f"Error(path={self.path}, cause={self.cause})"
# noinspection SpellCheckingInspection
def _construct_matches_id_short() -> Pattern[str]:
pattern = "^[a-zA-Z][a-zA-Z0-9_]*$"
return re.compile(pattern)
_REGEX_MATCHES_ID_SHORT = _construct_matches_id_short()
[docs]def matches_id_short(text: str) -> bool:
"""Check that :paramref:`text` is a valid short ID."""
return _REGEX_MATCHES_ID_SHORT.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_version_type() -> Pattern[str]:
pattern = "^(0|[1-9][0-9]*)$"
return re.compile(pattern)
_REGEX_MATCHES_VERSION_TYPE = _construct_matches_version_type()
[docs]def matches_version_type(text: str) -> bool:
"""Check that :paramref:`text` is a valid version string."""
return _REGEX_MATCHES_VERSION_TYPE.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_revision_type() -> Pattern[str]:
pattern = "^(0|[1-9][0-9]*)$"
return re.compile(pattern)
_REGEX_MATCHES_REVISION_TYPE = _construct_matches_revision_type()
[docs]def matches_revision_type(text: str) -> bool:
"""Check that :paramref:`text` is a valid revision string."""
return _REGEX_MATCHES_REVISION_TYPE.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_date_time_utc() -> Pattern[str]:
digit = "[0-9]"
year_frag = f"-?(([1-9]{digit}{digit}{digit}+)|(0{digit}{digit}{digit}))"
month_frag = "((0[1-9])|(1[0-2]))"
day_frag = f"((0[1-9])|([12]{digit})|(3[01]))"
hour_frag = f"(([01]{digit})|(2[0-3]))"
minute_frag = f"[0-5]{digit}"
second_frag = f"([0-5]{digit})(\\.{digit}+)?"
end_of_day_frag = "24:00:00(\\.0+)?"
timezone_frag = "(Z|\\+00:00|-00:00)"
date_time_lexical_rep = f"{year_frag}-{month_frag}-{day_frag}T(({hour_frag}:{minute_frag}:{second_frag})|{end_of_day_frag}){timezone_frag}"
pattern = f"^{date_time_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DATE_TIME_UTC = _construct_matches_xs_date_time_utc()
[docs]def matches_xs_date_time_utc(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:dateTime``.
The time zone must be fixed to UTC. We verify only that the ``text`` matches
a pre-defined pattern. We *do not* verify that the day of month is
correct nor do we check for leap seconds.
See: https://www.w3.org/TR/xmlschema-2/#dateTime
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DATE_TIME_UTC.match(text) is not None
[docs]def is_xs_date_time_utc(value: str) -> bool:
"""
Check that :paramref:`value` is a ``xs:dateTime`` with
the time zone set to UTC.
"""
if not matches_xs_date_time_utc(value):
return False
date, _ = value.split("T")
return is_xs_date(date)
# noinspection SpellCheckingInspection
def _construct_matches_mime_type() -> Pattern[str]:
tchar = "[!#$%&'*+\\-.^_`|~0-9a-zA-Z]"
token = f"({tchar})+"
type = f"{token}"
subtype = f"{token}"
ows = "[ \\t]*"
obs_text = "[\\x80-\\xff]"
qd_text = f"([\\t !#-\\[\\]-~]|{obs_text})"
quoted_pair = f"\\\\([\\t !-~]|{obs_text})"
quoted_string = f'"({qd_text}|{quoted_pair})*"'
parameter = f"{token}=({token}|{quoted_string})"
media_type = f"^{type}/{subtype}({ows};{ows}{parameter})*$"
return re.compile(media_type)
_REGEX_MATCHES_MIME_TYPE = _construct_matches_mime_type()
[docs]def matches_mime_type(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of MIME type.
The definition has been taken from:
https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1,
https://www.rfc-editor.org/rfc/rfc7230#section-3.2.3 and
https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6.
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_MIME_TYPE.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_rfc_2396() -> Pattern[str]:
alphanum = "[a-zA-Z0-9]"
mark = "[-_.!~*'()]"
unreserved = f"({alphanum}|{mark})"
hex = "([0-9]|[aA]|[bB]|[cC]|[dD]|[eE]|[fF]|[aA]|[bB]|[cC]|[dD]|[eE]|[fF])"
escaped = f"%{hex}{hex}"
pchar = f"({unreserved}|{escaped}|[:@&=+$,])"
param = f"({pchar})*"
segment = f"({pchar})*(;{param})*"
path_segments = f"{segment}(/{segment})*"
abs_path = f"/{path_segments}"
scheme = "[a-zA-Z][a-zA-Z0-9+\\-.]*"
userinfo = f"({unreserved}|{escaped}|[;:&=+$,])*"
domainlabel = f"({alphanum}|{alphanum}({alphanum}|-)*{alphanum})"
toplabel = f"([a-zA-Z]|[a-zA-Z]({alphanum}|-)*{alphanum})"
hostname = f"({domainlabel}\\.)*{toplabel}(\\.)?"
ipv4address = "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"
host = f"({hostname}|{ipv4address})"
port = "[0-9]*"
hostport = f"{host}(:{port})?"
server = f"(({userinfo}@)?{hostport})?"
reg_name = f"({unreserved}|{escaped}|[$,;:@&=+])+"
authority = f"({server}|{reg_name})"
net_path = f"//{authority}({abs_path})?"
reserved = "[;/?:@&=+$,]"
uric = f"({reserved}|{unreserved}|{escaped})"
query = f"({uric})*"
hier_part = f"({net_path}|{abs_path})(\\?{query})?"
uric_no_slash = f"({unreserved}|{escaped}|[;?:@&=+$,])"
opaque_part = f"{uric_no_slash}({uric})*"
absoluteuri = f"{scheme}:({hier_part}|{opaque_part})"
fragment = f"({uric})*"
rel_segment = f"({unreserved}|{escaped}|[;@&=+$,])+"
rel_path = f"{rel_segment}({abs_path})?"
relativeuri = f"({net_path}|{abs_path}|{rel_path})(\\?{query})?"
uri_reference = f"^({absoluteuri}|{relativeuri})?(#{fragment})?$"
return re.compile(uri_reference)
_REGEX_MATCHES_RFC_2396 = _construct_matches_rfc_2396()
[docs]def matches_rfc_2396(text: str) -> bool:
"""
Check that :paramref:`text` matches to the URI pattern defined in RFC 2396
The definition has been taken from:
https://datatracker.ietf.org/doc/html/rfc2396
Note that RFX 2396 alone is not enough for specifying ``xs:anyURI`` for
XSD version 1.0, as that specifies URI together with the amendment of
RFC 2732.
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_RFC_2396.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_bcp_47() -> Pattern[str]:
alphanum = "[a-zA-Z0-9]"
singleton = "[0-9A-WY-Za-wy-z]"
extension = f"{singleton}(-({alphanum}){{2,8}})+"
extlang = "[a-zA-Z]{3}(-[a-zA-Z]{3}){0,2}"
irregular = "(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)"
regular = "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)"
grandfathered = f"({irregular}|{regular})"
language = f"([a-zA-Z]{{2,3}}(-{extlang})?|[a-zA-Z]{{4}}|[a-zA-Z]{{5,8}})"
script = "[a-zA-Z]{4}"
region = "([a-zA-Z]{2}|[0-9]{3})"
variant = f"(({alphanum}){{5,8}}|[0-9]({alphanum}){{3}})"
privateuse = f"[xX](-({alphanum}){{1,8}})+"
langtag = f"{language}(-{script})?(-{region})?(-{variant})*(-{extension})*(-{privateuse})?"
language_tag = f"({langtag}|{privateuse}|{grandfathered})"
pattern = f"^{language_tag}$"
return re.compile(pattern)
_REGEX_MATCHES_BCP_47 = _construct_matches_bcp_47()
[docs]def matches_bcp_47(text: str) -> bool:
"""
Check that :paramref:`text` is a valid BCP 47 language tag.
See: https://en.wikipedia.org/wiki/IETF_language_tag
"""
return _REGEX_MATCHES_BCP_47.match(text) is not None
[docs]def lang_strings_have_unique_languages(
lang_strings: Iterable[aas_types.AbstractLangString],
) -> bool:
"""
Check that :paramref:`lang_strings` are specified each for a unique
language.
"""
language_set = set() # type: Set[str]
for lang_string in lang_strings:
if lang_string.language in language_set:
return False
language_set.add(lang_string.language)
return True
[docs]def qualifier_types_are_unique(qualifiers: Iterable[aas_types.Qualifier]) -> bool:
"""
Check that there are no duplicate
:py:attr:`.types.Qualifier.type`'s
in the :paramref:`qualifiers`.
"""
type_set = set() # type: Set[str]
for qualifier in qualifiers:
if qualifier.type in type_set:
return False
type_set.add(qualifier.type)
return True
# noinspection SpellCheckingInspection
def _construct_matches_xml_serializable_string() -> Pattern[str]:
pattern = "^[\\x09\\x0a\\x0d\\x20-\\ud7ff\\ue000-\\ufffd\\U00010000-\\U0010ffff]*$"
return re.compile(pattern)
_REGEX_MATCHES_XML_SERIALIZABLE_STRING = _construct_matches_xml_serializable_string()
[docs]def matches_xml_serializable_string(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of the Constraint AASd-130.
Ensures that encoding is possible and interoperability between different
serializations is possible.
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XML_SERIALIZABLE_STRING.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_any_uri() -> Pattern[str]:
scheme = "[a-zA-Z][a-zA-Z0-9+\\-.]*"
ucschar = "[\\xa0-\\ud7ff\\uf900-\\ufdcf\\ufdf0-\\uffef\\U00010000-\\U0001fffd\\U00020000-\\U0002fffd\\U00030000-\\U0003fffd\\U00040000-\\U0004fffd\\U00050000-\\U0005fffd\\U00060000-\\U0006fffd\\U00070000-\\U0007fffd\\U00080000-\\U0008fffd\\U00090000-\\U0009fffd\\U000a0000-\\U000afffd\\U000b0000-\\U000bfffd\\U000c0000-\\U000cfffd\\U000d0000-\\U000dfffd\\U000e1000-\\U000efffd]"
iunreserved = f"([a-zA-Z0-9\\-._~]|{ucschar})"
pct_encoded = "%[0-9A-Fa-f][0-9A-Fa-f]"
sub_delims = "[!$&'()*+,;=]"
iuserinfo = f"({iunreserved}|{pct_encoded}|{sub_delims}|:)*"
h16 = "[0-9A-Fa-f]{1,4}"
dec_octet = "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
ipv4address = f"{dec_octet}\\.{dec_octet}\\.{dec_octet}\\.{dec_octet}"
ls32 = f"({h16}:{h16}|{ipv4address})"
ipv6address = f"(({h16}:){{6}}{ls32}|::({h16}:){{5}}{ls32}|({h16})?::({h16}:){{4}}{ls32}|(({h16}:)?{h16})?::({h16}:){{3}}{ls32}|(({h16}:){{0,2}}{h16})?::({h16}:){{2}}{ls32}|(({h16}:){{0,3}}{h16})?::{h16}:{ls32}|(({h16}:){{0,4}}{h16})?::{ls32}|(({h16}:){{0,5}}{h16})?::{h16}|(({h16}:){{0,6}}{h16})?::)"
unreserved = "[a-zA-Z0-9\\-._~]"
ipvfuture = f"[vV][0-9A-Fa-f]+\\.({unreserved}|{sub_delims}|:)+"
ip_literal = f"\\[({ipv6address}|{ipvfuture})\\]"
ireg_name = f"({iunreserved}|{pct_encoded}|{sub_delims})*"
ihost = f"({ip_literal}|{ipv4address}|{ireg_name})"
port = "[0-9]*"
iauthority = f"({iuserinfo}@)?{ihost}(:{port})?"
ipchar = f"({iunreserved}|{pct_encoded}|{sub_delims}|[:@])"
isegment = f"({ipchar})*"
ipath_abempty = f"(/{isegment})*"
isegment_nz = f"({ipchar})+"
ipath_absolute = f"/({isegment_nz}(/{isegment})*)?"
ipath_rootless = f"{isegment_nz}(/{isegment})*"
ipath_empty = f"({ipchar}){{0}}"
ihier_part = f"(//{iauthority}{ipath_abempty}|{ipath_absolute}|{ipath_rootless}|{ipath_empty})"
iprivate = "[\\ue000-\\uf8ff\\U000f0000-\\U000ffffd\\U00100000-\\U0010fffd]"
iquery = f"({ipchar}|{iprivate}|[/?])*"
ifragment = f"({ipchar}|[/?])*"
isegment_nz_nc = f"({iunreserved}|{pct_encoded}|{sub_delims}|@)+"
ipath_noscheme = f"{isegment_nz_nc}(/{isegment})*"
irelative_part = f"(//{iauthority}{ipath_abempty}|{ipath_absolute}|{ipath_noscheme}|{ipath_empty})"
irelative_ref = f"{irelative_part}(\\?{iquery})?(#{ifragment})?"
iri = f"{scheme}:{ihier_part}(\\?{iquery})?(#{ifragment})?"
iri_reference = f"({iri}|{irelative_ref})"
pattern = f"^{iri_reference}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_ANY_URI = _construct_matches_xs_any_uri()
[docs]def matches_xs_any_uri(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:anyURI``.
See: https://www.w3.org/TR/xmlschema-2/#anyURI and
https://datatracker.ietf.org/doc/html/rfc3987
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_ANY_URI.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_base_64_binary() -> Pattern[str]:
b04_char = "[AQgw]"
b04 = f"{b04_char}\\x20?"
b16_char = "[AEIMQUYcgkosw048]"
b16 = f"{b16_char}\\x20?"
b64_char = "[A-Za-z0-9+/]"
b64 = f"{b64_char}\\x20?"
b64quad = f"({b64}{b64}{b64}{b64})"
b64_final_quad = f"({b64}{b64}{b64}{b64_char})"
padded_8 = f"{b64}{b04}= ?="
padded_16 = f"{b64}{b64}{b16}="
b64final = f"({b64_final_quad}|{padded_16}|{padded_8})"
base64_binary = f"({b64quad}*{b64final})?"
pattern = f"^{base64_binary}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_BASE_64_BINARY = _construct_matches_xs_base_64_binary()
[docs]def matches_xs_base_64_binary(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:base64Binary``.
See: https://www.w3.org/TR/xmlschema-2/#base64Binary
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_BASE_64_BINARY.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_boolean() -> Pattern[str]:
pattern = "^(true|false|1|0)$"
return re.compile(pattern)
_REGEX_MATCHES_XS_BOOLEAN = _construct_matches_xs_boolean()
[docs]def matches_xs_boolean(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:boolean``.
See: https://www.w3.org/TR/xmlschema-2/#boolean
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_BOOLEAN.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_date() -> Pattern[str]:
digit = "[0-9]"
year_frag = f"-?(([1-9]{digit}{digit}{digit}+)|(0{digit}{digit}{digit}))"
month_frag = "((0[1-9])|(1[0-2]))"
day_frag = f"((0[1-9])|([12]{digit})|(3[01]))"
minute_frag = f"[0-5]{digit}"
timezone_frag = f"(Z|(\\+|-)((0{digit}|1[0-3]):{minute_frag}|14:00))"
date_lexical_rep = f"{year_frag}-{month_frag}-{day_frag}{timezone_frag}?"
pattern = f"^{date_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DATE = _construct_matches_xs_date()
[docs]def matches_xs_date(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:date``.
See: https://www.w3.org/TR/xmlschema-2/#date
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DATE.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_date_time() -> Pattern[str]:
digit = "[0-9]"
year_frag = f"-?(([1-9]{digit}{digit}{digit}+)|(0{digit}{digit}{digit}))"
month_frag = "((0[1-9])|(1[0-2]))"
day_frag = f"((0[1-9])|([12]{digit})|(3[01]))"
hour_frag = f"(([01]{digit})|(2[0-3]))"
minute_frag = f"[0-5]{digit}"
second_frag = f"([0-5]{digit})(\\.{digit}+)?"
end_of_day_frag = "24:00:00(\\.0+)?"
timezone_frag = f"(Z|(\\+|-)((0{digit}|1[0-3]):{minute_frag}|14:00))"
date_time_lexical_rep = f"{year_frag}-{month_frag}-{day_frag}T(({hour_frag}:{minute_frag}:{second_frag})|{end_of_day_frag}){timezone_frag}?"
pattern = f"^{date_time_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DATE_TIME = _construct_matches_xs_date_time()
[docs]def matches_xs_date_time(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:dateTime``.
See: https://www.w3.org/TR/xmlschema-2/#dateTime
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DATE_TIME.match(text) is not None
[docs]def is_xs_date_time(value: str) -> bool:
"""
Check that :paramref:`value` is a ``xs:dateTime`` with
the time zone set to UTC.
"""
if not matches_xs_date_time(value):
return False
date, _ = value.split("T")
return is_xs_date(date)
# noinspection SpellCheckingInspection
def _construct_matches_xs_decimal() -> Pattern[str]:
digit = "[0-9]"
unsigned_no_decimal_pt_numeral = f"{digit}+"
no_decimal_pt_numeral = f"(\\+|-)?{unsigned_no_decimal_pt_numeral}"
frac_frag = f"{digit}+"
unsigned_decimal_pt_numeral = (
f"({unsigned_no_decimal_pt_numeral}\\.{frac_frag}|\\.{frac_frag})"
)
decimal_pt_numeral = f"(\\+|-)?{unsigned_decimal_pt_numeral}"
decimal_lexical_rep = f"({decimal_pt_numeral}|{no_decimal_pt_numeral})"
pattern = f"^{decimal_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DECIMAL = _construct_matches_xs_decimal()
[docs]def matches_xs_decimal(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:decimal``.
See: https://www.w3.org/TR/xmlschema-2/#decimal
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DECIMAL.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_double() -> Pattern[str]:
double_rep = (
"((\\+|-)?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([Ee](\\+|-)?[0-9]+)?|-?INF|NaN)"
)
pattern = f"^{double_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DOUBLE = _construct_matches_xs_double()
[docs]def matches_xs_double(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:double``.
See: https://www.w3.org/TR/xmlschema-2/#double
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DOUBLE.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_duration() -> Pattern[str]:
duration_rep = "-?P((([0-9]+Y([0-9]+M)?([0-9]+D)?|([0-9]+M)([0-9]+D)?|([0-9]+D))(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S)))?)|(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S))))"
pattern = f"^{duration_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DURATION = _construct_matches_xs_duration()
[docs]def matches_xs_duration(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:duration``.
See: https://www.w3.org/TR/xmlschema-2/#duration
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DURATION.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_float() -> Pattern[str]:
float_rep = (
"((\\+|-)?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([Ee](\\+|-)?[0-9]+)?|-?INF|NaN)"
)
pattern = f"^{float_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_FLOAT = _construct_matches_xs_float()
[docs]def matches_xs_float(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:float``.
See: https://www.w3.org/TR/xmlschema-2/#float
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_FLOAT.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_g_day() -> Pattern[str]:
g_day_lexical_rep = (
"---(0[1-9]|[12][0-9]|3[01])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
)
pattern = f"^{g_day_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_G_DAY = _construct_matches_xs_g_day()
[docs]def matches_xs_g_day(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:gDay``.
See: https://www.w3.org/TR/xmlschema-2/#gDay
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_G_DAY.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_g_month() -> Pattern[str]:
g_month_lexical_rep = (
"--(0[1-9]|1[0-2])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
)
pattern = f"^{g_month_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_G_MONTH = _construct_matches_xs_g_month()
[docs]def matches_xs_g_month(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:gMonth``.
See: https://www.w3.org/TR/xmlschema-2/#gMonth
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_G_MONTH.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_g_month_day() -> Pattern[str]:
g_month_day_rep = "--(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
pattern = f"^{g_month_day_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_G_MONTH_DAY = _construct_matches_xs_g_month_day()
[docs]def matches_xs_g_month_day(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:gMonthDay``.
See: https://www.w3.org/TR/xmlschema-2/#gMonthDay
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_G_MONTH_DAY.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_g_year() -> Pattern[str]:
g_year_rep = (
"-?([1-9][0-9]{3,}|0[0-9]{3})(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
)
pattern = f"^{g_year_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_G_YEAR = _construct_matches_xs_g_year()
[docs]def matches_xs_g_year(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:gYear``.
See: https://www.w3.org/TR/xmlschema-2/#gYear
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_G_YEAR.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_g_year_month() -> Pattern[str]:
g_year_month_rep = "-?([1-9][0-9]{3,}|0[0-9]{3})-(0[1-9]|1[0-2])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
pattern = f"^{g_year_month_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_G_YEAR_MONTH = _construct_matches_xs_g_year_month()
[docs]def matches_xs_g_year_month(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:gYearMonth``.
See: https://www.w3.org/TR/xmlschema-2/#gYearMonth
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_G_YEAR_MONTH.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_hex_binary() -> Pattern[str]:
hex_binary = "([0-9a-fA-F]{2})*"
pattern = f"^{hex_binary}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_HEX_BINARY = _construct_matches_xs_hex_binary()
[docs]def matches_xs_hex_binary(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:hexBinary``.
See: https://www.w3.org/TR/xmlschema-2/#hexBinary
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_HEX_BINARY.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_time() -> Pattern[str]:
time_rep = "(([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?|(24:00:00(\\.0+)?))(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?"
pattern = f"^{time_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_TIME = _construct_matches_xs_time()
[docs]def matches_xs_time(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:time``.
See: https://www.w3.org/TR/xmlschema-2/#time
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_TIME.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_integer() -> Pattern[str]:
integer_rep = "[-+]?[0-9]+"
pattern = f"^{integer_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_INTEGER = _construct_matches_xs_integer()
[docs]def matches_xs_integer(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:integer``.
See: https://www.w3.org/TR/xmlschema-2/#integer
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_INTEGER.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_long() -> Pattern[str]:
long_rep = "[-+]?0*[0-9]{1,20}"
pattern = f"^{long_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_LONG = _construct_matches_xs_long()
[docs]def matches_xs_long(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:long``.
See: https://www.w3.org/TR/xmlschema-2/#long
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_LONG.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_int() -> Pattern[str]:
int_rep = "[-+]?0*[0-9]{1,10}"
pattern = f"^{int_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_INT = _construct_matches_xs_int()
[docs]def matches_xs_int(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:int``.
See: https://www.w3.org/TR/xmlschema-2/#int
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_INT.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_short() -> Pattern[str]:
short_rep = "[-+]?0*[0-9]{1,5}"
pattern = f"^{short_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_SHORT = _construct_matches_xs_short()
[docs]def matches_xs_short(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:short``.
See: https://www.w3.org/TR/xmlschema-2/#short
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_SHORT.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_byte() -> Pattern[str]:
byte_rep = "[-+]?0*[0-9]{1,3}"
pattern = f"^{byte_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_BYTE = _construct_matches_xs_byte()
[docs]def matches_xs_byte(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:byte``.
See: https://www.w3.org/TR/xmlschema-2/#byte
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_BYTE.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_non_negative_integer() -> Pattern[str]:
non_negative_integer_rep = "(-0|\\+?[0-9]+)"
pattern = f"^{non_negative_integer_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_NON_NEGATIVE_INTEGER = _construct_matches_xs_non_negative_integer()
[docs]def matches_xs_non_negative_integer(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:nonNegativeInteger``.
See: https://www.w3.org/TR/xmlschema-2/#nonNegativeInteger
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_NON_NEGATIVE_INTEGER.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_positive_integer() -> Pattern[str]:
positive_integer_rep = "\\+?0*[1-9][0-9]*"
pattern = f"^{positive_integer_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_POSITIVE_INTEGER = _construct_matches_xs_positive_integer()
[docs]def matches_xs_positive_integer(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:positiveInteger``.
See: https://www.w3.org/TR/xmlschema-2/#positiveInteger
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_POSITIVE_INTEGER.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_long() -> Pattern[str]:
unsigned_long_rep = "(-0|\\+?0*[0-9]{1,20})"
pattern = f"^{unsigned_long_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_UNSIGNED_LONG = _construct_matches_xs_unsigned_long()
[docs]def matches_xs_unsigned_long(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedLong``.
See: https://www.w3.org/TR/xmlschema-2/#unsignedLong
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_UNSIGNED_LONG.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_int() -> Pattern[str]:
unsigned_int_rep = "(-0|\\+?0*[0-9]{1,10})"
pattern = f"^{unsigned_int_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_UNSIGNED_INT = _construct_matches_xs_unsigned_int()
[docs]def matches_xs_unsigned_int(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedInt``.
See: https://www.w3.org/TR/xmlschema-2/#unsignedInt
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_UNSIGNED_INT.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_short() -> Pattern[str]:
unsigned_short_rep = "(-0|\\+?0*[0-9]{1,5})"
pattern = f"^{unsigned_short_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_UNSIGNED_SHORT = _construct_matches_xs_unsigned_short()
[docs]def matches_xs_unsigned_short(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedShort``.
See: https://www.w3.org/TR/xmlschema-2/#unsignedShort
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_UNSIGNED_SHORT.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_unsigned_byte() -> Pattern[str]:
unsigned_byte_rep = "(-0|\\+?0*[0-9]{1,3})"
pattern = f"^{unsigned_byte_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_UNSIGNED_BYTE = _construct_matches_xs_unsigned_byte()
[docs]def matches_xs_unsigned_byte(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:unsignedByte``.
See: https://www.w3.org/TR/xmlschema-2/#unsignedByte
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_UNSIGNED_BYTE.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_non_positive_integer() -> Pattern[str]:
non_positive_integer_rep = "(\\+0|0|-[0-9]+)"
pattern = f"^{non_positive_integer_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_NON_POSITIVE_INTEGER = _construct_matches_xs_non_positive_integer()
[docs]def matches_xs_non_positive_integer(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:nonPositiveInteger``.
See: https://www.w3.org/TR/xmlschema-2/#nonPositiveInteger
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_NON_POSITIVE_INTEGER.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_negative_integer() -> Pattern[str]:
negative_integer_rep = "(-0*[1-9][0-9]*)"
pattern = f"^{negative_integer_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_NEGATIVE_INTEGER = _construct_matches_xs_negative_integer()
[docs]def matches_xs_negative_integer(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:negativeInteger``.
See: https://www.w3.org/TR/xmlschema-2/#negativeInteger
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_NEGATIVE_INTEGER.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_string() -> Pattern[str]:
pattern = "^[\\x09\\x0a\\x0d\\x20-\\ud7ff\\ue000-\\ufffd\\U00010000-\\U0010ffff]*$"
return re.compile(pattern)
_REGEX_MATCHES_XS_STRING = _construct_matches_xs_string()
[docs]def matches_xs_string(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:string``.
See: https://www.w3.org/TR/xmlschema-2/#string
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_STRING.match(text) is not None
def _is_leap_year(year: int) -> bool:
"""
Check if :paramref:`year` is a leap year.
>>> _is_leap_year(2016)
True
>>> _is_leap_year(1700)
False
>>> _is_leap_year(1600)
True
>>> _is_leap_year(2000)
True
"""
# We consider the years B.C. to be one-off.
#
# See the note at: https://www.w3.org/TR/xmlschema-2/#dateTime:
# "'-0001' is the lexical representation of the year 1 Before Common Era
# (1 BCE, sometimes written "1 BC")."
#
# Hence, -1 year in XML is 1 BCE, which is 0 year in astronomical years.
if year < 0:
year = abs(year) - 1
# See: https://en.wikipedia.org/wiki/Leap_year#Algorithm
if year % 4 > 0:
return False
if year % 100 > 0:
return True
if year % 400 > 0:
return False
return True
_DAYS_IN_MONTH: Mapping[int, int] = {
1: 31,
# Please use _is_leap_year if you need to check
# whether a concrete February has 28 or 29 days.
2: 29,
3: 31,
4: 30,
5: 31,
6: 30,
7: 31,
8: 31,
9: 30,
10: 31,
11: 30,
12: 31,
}
_DATE_PREFIX_RE = re.compile(r"^(-?[0-9]+)-([0-9]{2})-([0-9]{2})")
[docs]def is_xs_date(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:date``."""
if not matches_xs_date(value):
return False
# NOTE (mristin, 2022-11-23):
# We can not use :py:func:`datetime.datetime.strptime` as it does not
# handle years below 1000 correctly on Windows (*e.g.*, ``-999-01-01``).
# NOTE (mristin, 2022-10-30):
# We need to match the prefix as zone offsets are allowed in the dates. Optimally,
# we would re-use the pattern matching from :py:func`matches_xs_date`, but this
# would make the code generation and constraint inference for schemas much more
# difficult. Hence, we sacrifice the efficiency a bit for the clearer code & code
# generation.
match = _DATE_PREFIX_RE.match(value)
assert match is not None
year = int(match.group(1))
month = int(match.group(2))
day = int(match.group(3))
# We do not accept year zero,
# see the note at: https://www.w3.org/TR/xmlschema-2/#dateTime
if year == 0:
return False
if day <= 0:
return False
if month <= 0 or month >= 13:
return False
if month == 2:
max_days = 29 if _is_leap_year(year) else 28
else:
max_days = _DAYS_IN_MONTH[month]
if day > max_days:
return False
return True
[docs]def is_xs_double(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:double``."""
# We need to check explicitly for the regular expression since
# ``float(.)`` is too permissive. For example,
# it accepts "nan" although only "NaN" is valid.
# See: https://www.w3.org/TR/xmlschema-2/#double
if not matches_xs_double(value):
return False
converted = float(value)
# Check that the value is either "INF" or "-INF".
# Otherwise, the value is a decimal which is too big
# to be represented as a double-precision floating point
# number.
#
# Python simply rounds up/down to ``INF`` and ``-INF``,
# respectively, if the number is too large.
# For example: ``float("1e400") == math.inf``
if math.isinf(converted) and value != "INF" and value != "-INF":
return False
return True
[docs]def is_xs_float(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:float``."""
# We need to check explicitly for the regular expression since
# ``float(.)`` is too permissive. For example,
# it accepts "nan" although only "NaN" is valid.
# See: https://www.w3.org/TR/xmlschema-2/#double
if not matches_xs_float(value):
return False
converted = float(value)
# Check that the value is either "INF" or "-INF".
# Otherwise, the value is a decimal which is too big
# to be represented as a single-precision floating point
# number.
#
# Python simply rounds up/down to ``INF`` and ``-INF``,
# respectively, if the number is too large.
# For example: ``float("1e400") == math.inf``
if math.isinf(converted) and value != "INF" and value != "-INF":
return False
# Python uses double-precision floating point numbers. Since
# we check for a single-precision one, we have to explicitly
# see if the number is within a range of a single-precision
# floating point numbers.
try:
_ = struct.pack(">f", converted)
except OverflowError:
return False
return True
[docs]def is_xs_g_month_day(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:gMonthDay``."""
if not matches_xs_g_month_day(value):
return False
month = int(value[2:4])
day = int(value[5:7])
max_days = _DAYS_IN_MONTH[month]
return day <= max_days
[docs]def is_xs_long(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:long``."""
if not matches_xs_long(value):
return False
converted = int(value)
return -9223372036854775808 <= converted <= 9223372036854775807
[docs]def is_xs_int(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:int``."""
if not matches_xs_int(value):
return False
converted = int(value)
return -2147483648 <= converted <= 2147483647
[docs]def is_xs_short(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:short``."""
if not matches_xs_short(value):
return False
converted = int(value)
return -32768 <= converted <= 32767
[docs]def is_xs_byte(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:byte``."""
if not matches_xs_byte(value):
return False
converted = int(value)
return -128 <= converted <= 127
[docs]def is_xs_unsigned_long(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:unsignedLong``."""
if not matches_xs_unsigned_long(value):
return False
converted = int(value)
return 0 <= converted <= 18446744073709551615
[docs]def is_xs_unsigned_int(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:unsignedInt``."""
if not matches_xs_unsigned_int(value):
return False
converted = int(value)
return 0 <= converted <= 4294967295
[docs]def is_xs_unsigned_short(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:unsignedShort``."""
if not matches_xs_unsigned_short(value):
return False
converted = int(value)
return 0 <= converted <= 65535
[docs]def is_xs_unsigned_byte(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:unsignedByte``."""
if not matches_xs_unsigned_byte(value):
return False
converted = int(value)
return 0 <= converted <= 255
_DATA_TYPE_DEF_XSD_TO_VALUE_CONSISTENCY: Mapping[
aas_types.DataTypeDefXSD, Callable[[str], bool]
] = {
aas_types.DataTypeDefXSD.ANY_URI: matches_xs_any_uri,
aas_types.DataTypeDefXSD.BASE_64_BINARY: matches_xs_base_64_binary,
aas_types.DataTypeDefXSD.BOOLEAN: matches_xs_boolean,
aas_types.DataTypeDefXSD.BYTE: is_xs_byte,
aas_types.DataTypeDefXSD.DATE: is_xs_date,
aas_types.DataTypeDefXSD.DATE_TIME: is_xs_date_time,
aas_types.DataTypeDefXSD.DECIMAL: matches_xs_decimal,
aas_types.DataTypeDefXSD.DOUBLE: is_xs_double,
aas_types.DataTypeDefXSD.DURATION: matches_xs_duration,
aas_types.DataTypeDefXSD.FLOAT: is_xs_float,
aas_types.DataTypeDefXSD.G_DAY: matches_xs_g_day,
aas_types.DataTypeDefXSD.G_MONTH: matches_xs_g_month,
aas_types.DataTypeDefXSD.G_MONTH_DAY: is_xs_g_month_day,
aas_types.DataTypeDefXSD.G_YEAR: matches_xs_g_year,
aas_types.DataTypeDefXSD.G_YEAR_MONTH: matches_xs_g_year_month,
aas_types.DataTypeDefXSD.HEX_BINARY: matches_xs_hex_binary,
aas_types.DataTypeDefXSD.INT: is_xs_int,
aas_types.DataTypeDefXSD.INTEGER: matches_xs_integer,
aas_types.DataTypeDefXSD.LONG: is_xs_long,
aas_types.DataTypeDefXSD.NEGATIVE_INTEGER: matches_xs_negative_integer,
aas_types.DataTypeDefXSD.NON_NEGATIVE_INTEGER: matches_xs_non_negative_integer,
aas_types.DataTypeDefXSD.NON_POSITIVE_INTEGER: matches_xs_non_positive_integer,
aas_types.DataTypeDefXSD.POSITIVE_INTEGER: matches_xs_positive_integer,
aas_types.DataTypeDefXSD.SHORT: is_xs_short,
aas_types.DataTypeDefXSD.STRING: matches_xs_string,
aas_types.DataTypeDefXSD.TIME: matches_xs_time,
aas_types.DataTypeDefXSD.UNSIGNED_BYTE: is_xs_unsigned_byte,
aas_types.DataTypeDefXSD.UNSIGNED_INT: is_xs_unsigned_int,
aas_types.DataTypeDefXSD.UNSIGNED_LONG: is_xs_unsigned_long,
aas_types.DataTypeDefXSD.UNSIGNED_SHORT: is_xs_unsigned_short,
}
assert all(
data_type_def_xsd in _DATA_TYPE_DEF_XSD_TO_VALUE_CONSISTENCY
for data_type_def_xsd in aas_types.DataTypeDefXSD
)
[docs]def value_consistent_with_xsd_type(
value: str, value_type: aas_types.DataTypeDefXSD
) -> bool:
"""
Check that :paramref:`value` is consistent with the given
:paramref:`value_type`.
"""
return _DATA_TYPE_DEF_XSD_TO_VALUE_CONSISTENCY[value_type](value)
[docs]def is_model_reference_to(
reference: aas_types.Reference, expected_type: aas_types.KeyTypes
) -> bool:
"""
Check that the target of the model reference matches the :paramref:`expected_type`.
"""
# pylint: disable=all
return (
reference.type == aas_types.ReferenceTypes.MODEL_REFERENCE
and len(reference.keys) != 0
and reference.keys[-1].type == expected_type
)
[docs]def is_model_reference_to_referable(reference: aas_types.Reference) -> bool:
"""
Check that the target of the reference matches a :py:attr:`.constants.AAS_REFERABLES`.
"""
# pylint: disable=all
return (
reference.type == aas_types.ReferenceTypes.MODEL_REFERENCE
and len(reference.keys) != 0
and (reference.keys[-1].type in aas_constants.AAS_REFERABLES)
)
[docs]def id_shorts_are_unique(referables: Iterable[aas_types.Referable]) -> bool:
"""
Check that all :py:attr:`.types.Referable.id_short` are unique
among :paramref:`referables`.
"""
id_short_set = set() # type: Set[str]
for referable in referables:
if referable.id_short in id_short_set:
return False
if referable.id_short is not None:
id_short_set.add(referable.id_short)
return True
[docs]def id_shorts_of_variables_are_unique(
input_variables: Optional[List[aas_types.OperationVariable]],
output_variables: Optional[List[aas_types.OperationVariable]],
inoutput_variables: Optional[List[aas_types.OperationVariable]],
) -> bool:
"""
Check that the :py:attr:`.types.Referable.id_short`'s among all the
:paramref:`input_variables`, :paramref:`output_variables`
and :paramref:`inoutput_variables` are unique.
"""
id_short_set = set()
if input_variables is not None:
for variable in input_variables:
if variable.value.id_short is not None:
if variable.value.id_short in id_short_set:
return False
id_short_set.add(variable.value.id_short)
if output_variables is not None:
for variable in output_variables:
if variable.value.id_short is not None:
if variable.value.id_short in id_short_set:
return False
id_short_set.add(variable.value.id_short)
if inoutput_variables is not None:
for variable in inoutput_variables:
if variable.value.id_short is not None:
if variable.value.id_short in id_short_set:
return False
id_short_set.add(variable.value.id_short)
return True
[docs]def extension_names_are_unique(extensions: Iterable[aas_types.Extension]) -> bool:
"""
Check that all :py:attr:`.types.Extension.name` are unique
among :paramref:`extensions`.
"""
name_set = set() # type: Set[str]
for extension in extensions:
if extension.name in name_set:
return False
name_set.add(extension.name)
return True
[docs]def submodel_elements_have_identical_semantic_ids(
elements: Iterable[aas_types.SubmodelElement],
) -> bool:
"""
Check that all :paramref:`elements` have the identical
:py:attr:`.types.HasSemantics.semantic_id`.
"""
that_semantic_id = None # type: Optional[aas_types.Reference]
for element in elements:
if element.semantic_id is None:
continue
if that_semantic_id is None:
that_semantic_id = element.semantic_id
continue
this_semantic_id = element.semantic_id
if len(that_semantic_id.keys) != len(this_semantic_id.keys):
return False
for this_key, that_key in zip(this_semantic_id.keys, that_semantic_id.keys):
if this_key.value != that_key.value:
return False
return True
# fmt: off
_AAS_SUBMODEL_ELEMENTS_TO_TYPE: Mapping[
aas_types.AASSubmodelElements,
type
] = {
aas_types.AASSubmodelElements.ANNOTATED_RELATIONSHIP_ELEMENT:
aas_types.AnnotatedRelationshipElement,
aas_types.AASSubmodelElements.BASIC_EVENT_ELEMENT:
aas_types.BasicEventElement,
aas_types.AASSubmodelElements.BLOB:
aas_types.Blob,
aas_types.AASSubmodelElements.CAPABILITY:
aas_types.Capability,
aas_types.AASSubmodelElements.DATA_ELEMENT:
aas_types.DataElement,
aas_types.AASSubmodelElements.ENTITY:
aas_types.Entity,
aas_types.AASSubmodelElements.EVENT_ELEMENT:
aas_types.EventElement,
aas_types.AASSubmodelElements.FILE:
aas_types.File,
aas_types.AASSubmodelElements.MULTI_LANGUAGE_PROPERTY:
aas_types.MultiLanguageProperty,
aas_types.AASSubmodelElements.OPERATION:
aas_types.Operation,
aas_types.AASSubmodelElements.PROPERTY:
aas_types.Property,
aas_types.AASSubmodelElements.RANGE:
aas_types.Range,
aas_types.AASSubmodelElements.REFERENCE_ELEMENT:
aas_types.ReferenceElement,
aas_types.AASSubmodelElements.RELATIONSHIP_ELEMENT:
aas_types.RelationshipElement,
aas_types.AASSubmodelElements.SUBMODEL_ELEMENT:
aas_types.SubmodelElement,
aas_types.AASSubmodelElements.SUBMODEL_ELEMENT_LIST:
aas_types.SubmodelElementList,
aas_types.AASSubmodelElements.SUBMODEL_ELEMENT_COLLECTION:
aas_types.SubmodelElementCollection,
}
# fmt: on
def _assert_all_types_covered_in_aas_submodel_elements_to_type() -> None:
"""
Assert that we did not miss a type in :py:attr:`_AAS_SUBMODEL_ELEMENTS_TO_TYPE`.
"""
missing_literals = [
literal
for literal in aas_types.AASSubmodelElements
if literal not in _AAS_SUBMODEL_ELEMENTS_TO_TYPE
]
assert len(missing_literals) == 0, (
f"Some literals were missed in "
f"_AAS_SUBMODEL_ELEMENTS_TO_TYPE: {missing_literals!r}"
)
_assert_all_types_covered_in_aas_submodel_elements_to_type()
[docs]def submodel_element_is_of_type(
element: aas_types.SubmodelElement, expected_type: aas_types.AASSubmodelElements
) -> bool:
"""
Check that :paramref:`element` is an instance of class corresponding
to :paramref:`expected_type`.
"""
# noinspection PyTypeHints
return isinstance(element, _AAS_SUBMODEL_ELEMENTS_TO_TYPE[expected_type])
[docs]def properties_or_ranges_have_value_type(
elements: Iterable[aas_types.SubmodelElement], value_type: aas_types.DataTypeDefXSD
) -> bool:
"""
Check that :paramref:`elements` which are
:py:class:`.types.Property` or :py:class:`.types.Range`
have the given :paramref:`value_type`.
"""
range_or_property = (aas_types.Property, aas_types.Range)
for element in elements:
if isinstance(element, range_or_property):
if element.value_type is not value_type:
return False
return True
[docs]def reference_key_values_equal(
that: aas_types.Reference, other: aas_types.Reference
) -> bool:
"""
Check that the two references, :paramref:`that` and :paramref:`other`,
are equal by comparing their :py:attr:`.types.Reference.keys`
by :py:attr:`.types.Key.value`'s.
"""
if len(that.keys) != len(other.keys):
return False
for that_key, other_key in zip(that.keys, other.keys):
if that_key.value != other_key.value:
return False
return True
[docs]def data_specification_iec_61360s_for_property_or_value_have_appropriate_data_type(
embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
"""
Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
is defined appropriately for all data specifications whose content is given
as IEC 61360.
"""
for embedded_data_specification in embedded_data_specifications:
if isinstance(
embedded_data_specification.data_specification_content,
aas_types.DataSpecificationIEC61360,
):
iec61360 = embedded_data_specification.data_specification_content
if (
iec61360.data_type is None
or iec61360.data_type
not in aas_constants.DATA_TYPE_IEC_61360_FOR_PROPERTY_OR_VALUE
):
return False
return True
[docs]def data_specification_iec_61360s_for_reference_have_appropriate_data_type(
embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
"""
Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
is defined appropriately for all data specifications whose content is given
as IEC 61360.
"""
for embedded_data_specification in embedded_data_specifications:
if isinstance(
embedded_data_specification.data_specification_content,
aas_types.DataSpecificationIEC61360,
):
iec61360 = embedded_data_specification.data_specification_content
if (
iec61360.data_type is None
or iec61360.data_type
not in aas_constants.DATA_TYPE_IEC_61360_FOR_REFERENCE
):
return False
return True
[docs]def data_specification_iec_61360s_for_document_have_appropriate_data_type(
embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
"""
Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
is defined appropriately for all data specifications whose content is given as
IEC 61360.
"""
for embedded_data_specification in embedded_data_specifications:
if isinstance(
embedded_data_specification.data_specification_content,
aas_types.DataSpecificationIEC61360,
):
iec61360 = embedded_data_specification.data_specification_content
if (
iec61360.data_type is None
or iec61360.data_type
not in aas_constants.DATA_TYPE_IEC_61360_FOR_DOCUMENT
):
return False
return True
[docs]def data_specification_iec_61360s_have_data_type(
embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
"""
Check that :py:attr:`.types.DataSpecificationIEC61360.data_type`
is defined for all data specifications whose content is given as IEC 61360.
"""
for embedded_data_specification in embedded_data_specifications:
if isinstance(
embedded_data_specification.data_specification_content,
aas_types.DataSpecificationIEC61360,
):
iec61360 = embedded_data_specification.data_specification_content
if iec61360.data_type is None:
return False
return True
[docs]def data_specification_iec_61360s_have_value(
embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
"""
Check that :py:attr:`.types.DataSpecificationIEC61360.value`
is defined for all data specifications whose content is given as IEC 61360.
"""
for embedded_data_specification in embedded_data_specifications:
if isinstance(
embedded_data_specification.data_specification_content,
aas_types.DataSpecificationIEC61360,
):
iec61360 = embedded_data_specification.data_specification_content
if iec61360.value is None:
return False
return True
[docs]def data_specification_iec_61360s_have_definition_at_least_in_english(
embedded_data_specifications: Iterable[aas_types.EmbeddedDataSpecification],
) -> bool:
"""
Check that :py:attr:`.types.DataSpecificationIEC61360.definition`
is defined for all data specifications whose content is given as IEC 61360
at least in English.
"""
for embedded_data_specification in embedded_data_specifications:
if isinstance(
embedded_data_specification.data_specification_content,
aas_types.DataSpecificationIEC61360,
):
iec61360 = embedded_data_specification.data_specification_content
if iec61360.definition is None:
return False
no_definition_in_english = True
for lang_string in iec61360.definition:
if is_bcp_47_for_english(lang_string.language):
no_definition_in_english = False
break
if no_definition_in_english:
return False
return True
# noinspection SpellCheckingInspection
def _construct_is_bcp_47_for_english() -> Pattern[str]:
pattern = "^(en|EN)(-.*)?$"
return re.compile(pattern)
_REGEX_IS_BCP_47_FOR_ENGLISH = _construct_is_bcp_47_for_english()
[docs]def is_bcp_47_for_english(text: str) -> bool:
"""
Check that the :paramref:`text` corresponds to a BCP47 code for english.
"""
return _REGEX_IS_BCP_47_FOR_ENGLISH.match(text) is not None
class _Transformer(aas_types.AbstractTransformer[Iterator[Error]]):
# noinspection PyMethodMayBeStatic
def transform_extension(self, that: aas_types.Extension) -> Iterator[Error]:
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.refers_to is not None) or (len(that.refers_to) >= 1)):
yield Error("Refers-to must be either not set or have at least one item.")
if not (
not (that.value is not None)
or value_consistent_with_xsd_type(that.value, that.value_type_or_default())
):
yield Error("The value must match the value type.")
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, an_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
for error in verify_name_type(that.name):
error.path._prepend(PropertySegment(that, "name"))
yield error
if that.value is not None:
for error in verify_value_data_type(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
if that.refers_to is not None:
for i, another_item in enumerate(that.refers_to):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.refers_to, i))
error.path._prepend(PropertySegment(that, "refers_to"))
yield error
# noinspection PyMethodMayBeStatic
def transform_administrative_information(
self, that: aas_types.AdministrativeInformation
) -> Iterator[Error]:
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (not (that.revision is not None) or (that.version is not None)):
yield Error(
"Constraint AASd-005: If version is not specified then also "
+ "revision shall be unspecified. This means, a revision "
+ "requires a version. If there is no version there is no "
+ "revision either. Revision is optional."
)
if that.embedded_data_specifications is not None:
for i, an_item in enumerate(that.embedded_data_specifications):
for error in self.transform(an_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.version is not None:
for error in verify_version_type(that.version):
error.path._prepend(PropertySegment(that, "version"))
yield error
if that.revision is not None:
for error in verify_revision_type(that.revision):
error.path._prepend(PropertySegment(that, "revision"))
yield error
if that.creator is not None:
for error in self.transform(that.creator):
error.path._prepend(PropertySegment(that, "creator"))
yield error
if that.template_id is not None:
for error in verify_identifier(that.template_id):
error.path._prepend(PropertySegment(that, "template_id"))
yield error
# noinspection PyMethodMayBeStatic
def transform_qualifier(self, that: aas_types.Qualifier) -> Iterator[Error]:
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (
not (that.value is not None)
or value_consistent_with_xsd_type(that.value, that.value_type)
):
yield Error(
"Constraint AASd-020: The value shall be consistent to "
+ "the data type as defined in value type."
)
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, an_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
for error in verify_qualifier_type(that.type):
error.path._prepend(PropertySegment(that, "type"))
yield error
if that.value is not None:
for error in verify_value_data_type(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
if that.value_id is not None:
for error in self.transform(that.value_id):
error.path._prepend(PropertySegment(that, "value_id"))
yield error
# noinspection PyMethodMayBeStatic
def transform_asset_administration_shell(
self, that: aas_types.AssetAdministrationShell
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (not (that.submodels is not None) or (len(that.submodels) >= 1)):
yield Error("Submodels must be either not set or have at least one item.")
if not (
not (that.derived_from is not None)
or is_model_reference_to(
that.derived_from, aas_types.KeyTypes.ASSET_ADMINISTRATION_SHELL
)
):
yield Error(
"Derived-from must be a model reference to an asset "
+ "administration shell."
)
if not (
not (that.submodels is not None)
or (
all(
is_model_reference_to(reference, aas_types.KeyTypes.SUBMODEL)
for reference in that.submodels
)
)
):
yield Error("All submodels must be model references to a submodel.")
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.administration is not None:
for error in self.transform(that.administration):
error.path._prepend(PropertySegment(that, "administration"))
yield error
for error in verify_identifier(that.id):
error.path._prepend(PropertySegment(that, "id"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_another_item in enumerate(that.embedded_data_specifications):
for error in self.transform(yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.derived_from is not None:
for error in self.transform(that.derived_from):
error.path._prepend(PropertySegment(that, "derived_from"))
yield error
for error in self.transform(that.asset_information):
error.path._prepend(PropertySegment(that, "asset_information"))
yield error
if that.submodels is not None:
for i, yet_yet_yet_another_item in enumerate(that.submodels):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.submodels, i))
error.path._prepend(PropertySegment(that, "submodels"))
yield error
# noinspection PyMethodMayBeStatic
def transform_asset_information(
self, that: aas_types.AssetInformation
) -> Iterator[Error]:
if not (
not (that.specific_asset_ids is not None)
or (
all(
(
specific_asset_id.name != "globalAssetId"
or (
(
(that.global_asset_id is not None)
and specific_asset_id.name == "globalAssetId"
and specific_asset_id.value == that.global_asset_id
)
)
)
for specific_asset_id in that.specific_asset_ids
)
)
):
yield Error(
"Constraint AASd-116: ``globalAssetId`` is a reserved key. "
+ "If used as value for the name of specific asset ID then "
+ "the value of specific asset ID shall be identical to "
+ "the global asset ID."
)
if not (
(
(
(
(that.global_asset_id is not None)
or (that.specific_asset_ids is not None)
)
)
and (
not (that.specific_asset_ids is not None)
or (len(that.specific_asset_ids) >= 1)
)
)
):
yield Error(
"Constraint AASd-131: Either the global asset ID shall be "
+ "defined or at least one specific asset ID."
)
if not (
not (that.specific_asset_ids is not None)
or (len(that.specific_asset_ids) >= 1)
):
yield Error(
"Specific asset IDs must be either not set or have at least "
+ "one item."
)
if that.global_asset_id is not None:
for error in verify_identifier(that.global_asset_id):
error.path._prepend(PropertySegment(that, "global_asset_id"))
yield error
if that.specific_asset_ids is not None:
for i, an_item in enumerate(that.specific_asset_ids):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.specific_asset_ids, i))
error.path._prepend(PropertySegment(that, "specific_asset_ids"))
yield error
if that.asset_type is not None:
for error in verify_identifier(that.asset_type):
error.path._prepend(PropertySegment(that, "asset_type"))
yield error
if that.default_thumbnail is not None:
for error in self.transform(that.default_thumbnail):
error.path._prepend(PropertySegment(that, "default_thumbnail"))
yield error
# noinspection PyMethodMayBeStatic
def transform_resource(self, that: aas_types.Resource) -> Iterator[Error]:
for error in verify_path_type(that.path):
error.path._prepend(PropertySegment(that, "path"))
yield error
if that.content_type is not None:
for error in verify_content_type(that.content_type):
error.path._prepend(PropertySegment(that, "content_type"))
yield error
# noinspection PyMethodMayBeStatic
def transform_specific_asset_id(
self, that: aas_types.SpecificAssetID
) -> Iterator[Error]:
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (
not (that.external_subject_id is not None)
or (
that.external_subject_id.type
== aas_types.ReferenceTypes.EXTERNAL_REFERENCE
)
):
yield Error(
"Constraint AASd-133: External subject ID shall be "
+ "an external reference."
)
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, an_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
for error in verify_label_type(that.name):
error.path._prepend(PropertySegment(that, "name"))
yield error
for error in verify_identifier(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
if that.external_subject_id is not None:
for error in self.transform(that.external_subject_id):
error.path._prepend(PropertySegment(that, "external_subject_id"))
yield error
# noinspection PyMethodMayBeStatic
def transform_submodel(self, that: aas_types.Submodel) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.submodel_elements is not None)
or (len(that.submodel_elements) >= 1)
):
yield Error(
"Submodel elements must be either not set or have at least "
+ "one item."
)
if not (
not (that.submodel_elements is not None)
or (all(item.id_short is not None for item in that.submodel_elements))
):
yield Error(
"ID-shorts need to be defined for all the items of submodel "
+ "elements according to AASd-117 (ID-short of Referables not "
+ "being a direct child of a Submodel element list shall be "
+ "specified)."
)
if not (
not (that.submodel_elements is not None)
or id_shorts_are_unique(that.submodel_elements)
):
yield Error(
"Constraint AASd-022: ID-short of non-identifiable "
+ "referables within the same name space shall be unique "
+ "(case-sensitive)."
)
if not (
not (that.submodel_elements is not None)
or (
not (that.kind_or_default() != aas_types.ModellingKind.TEMPLATE)
or (
all(
not (submodel_element.qualifiers is not None)
or (
all(
qualifier.kind_or_default()
!= aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in submodel_element.qualifiers
)
)
for submodel_element in that.submodel_elements
)
)
)
):
yield Error(
"Constraint AASd-129: If any qualifier kind value of "
+ "a Submodel element qualifier (attribute qualifier inherited "
+ "via Qualifiable) is equal to Template Qualifier then "
+ "the submodel element shall be part of a submodel template, "
+ "i.e. a Submodel with submodel kind (attribute kind "
+ "inherited via Has-Kind) value is equal to Template."
)
if not (
not (that.qualifiers is not None)
or (
not (
any(
qualifier.kind_or_default()
== aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModellingKind.TEMPLATE)
)
):
yield Error(
"Constraint AASd-119: If any qualifier kind value of "
+ "a qualifiable qualifier is equal to template qualifier and "
+ "the qualified element has kind then the qualified element "
+ "shall be of kind template."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.administration is not None:
for error in self.transform(that.administration):
error.path._prepend(PropertySegment(that, "administration"))
yield error
for error in verify_identifier(that.id):
error.path._prepend(PropertySegment(that, "id"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.submodel_elements is not None:
for i, yet_yet_yet_yet_yet_another_item in enumerate(
that.submodel_elements
):
for error in self.transform(yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.submodel_elements, i))
error.path._prepend(PropertySegment(that, "submodel_elements"))
yield error
# noinspection PyMethodMayBeStatic
def transform_relationship_element(
self, that: aas_types.RelationshipElement
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
for error in self.transform(that.first):
error.path._prepend(PropertySegment(that, "first"))
yield error
for error in self.transform(that.second):
error.path._prepend(PropertySegment(that, "second"))
yield error
# noinspection PyMethodMayBeStatic
def transform_submodel_element_list(
self, that: aas_types.SubmodelElementList
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (not (that.value is not None) or (len(that.value) >= 1)):
yield Error("Value must be either not set or have at least one item.")
if not (
not (
(
(that.value is not None)
and (that.semantic_id_list_element is not None)
)
)
or (
all(
not (child.semantic_id is not None)
or reference_key_values_equal(
child.semantic_id, that.semantic_id_list_element
)
for child in that.value
)
)
):
yield Error(
"Constraint AASd-107: If a first level child element has "
+ "a semantic ID it shall be identical to semantic ID list "
+ "element."
)
if not (
not (that.value is not None)
or submodel_elements_have_identical_semantic_ids(that.value)
):
yield Error(
"Constraint AASd-114: If two first level child elements have "
+ "a semantic ID then they shall be identical."
)
if not (
not (that.value is not None)
or (
all(
submodel_element_is_of_type(element, that.type_value_list_element)
for element in that.value
)
)
):
yield Error(
"Constraint AASd-108: All first level child elements shall "
+ "have the same submodel element type as specified in type "
+ "value list element."
)
if not (
not (
(
that.type_value_list_element
== aas_types.AASSubmodelElements.PROPERTY
or that.type_value_list_element
== aas_types.AASSubmodelElements.RANGE
)
)
or (
(
(that.value_type_list_element is not None)
and (
(
(that.value is None)
or properties_or_ranges_have_value_type(
that.value, that.value_type_list_element
)
)
)
)
)
):
yield Error(
"Constraint AASd-109: If type value list element is equal to "
+ "Property or Range value type list element shall be set and "
+ "all first level child elements shall have the value type as "
+ "specified in value type list element."
)
if not (
not (that.value is not None)
or (all(element.id_short is None for element in that.value))
):
yield Error(
"Constraint AASd-120: ID-short of submodel elements being "
+ "a direct child of a Submodel element list shall not be "
+ "specified."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.semantic_id_list_element is not None:
for error in self.transform(that.semantic_id_list_element):
error.path._prepend(PropertySegment(that, "semantic_id_list_element"))
yield error
if that.value is not None:
for i, yet_yet_yet_yet_yet_another_item in enumerate(that.value):
for error in self.transform(yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.value, i))
error.path._prepend(PropertySegment(that, "value"))
yield error
# noinspection PyMethodMayBeStatic
def transform_submodel_element_collection(
self, that: aas_types.SubmodelElementCollection
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (not (that.value is not None) or (len(that.value) >= 1)):
yield Error("Value must be either not set or have at least one item.")
if not (
not (that.value is not None)
or (all(item.id_short is not None for item in that.value))
):
yield Error(
"ID-shorts need to be defined for all the items of value "
+ "according to AASd-117 (ID-short of Referables not being "
+ "a direct child of a Submodel element list shall be "
+ "specified)."
)
if not (not (that.value is not None) or id_shorts_are_unique(that.value)):
yield Error("ID-shorts of the value must be unique.")
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.value is not None:
for i, yet_yet_yet_yet_yet_another_item in enumerate(that.value):
for error in self.transform(yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.value, i))
error.path._prepend(PropertySegment(that, "value"))
yield error
# noinspection PyMethodMayBeStatic
def transform_property(self, that: aas_types.Property) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.category is not None)
or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
):
yield Error(
"Constraint AASd-090: For data elements category shall be "
+ "one of the following values: CONSTANT, PARAMETER or "
+ "VARIABLE."
)
if not (
not (that.value is not None)
or value_consistent_with_xsd_type(that.value, that.value_type)
):
yield Error("Value must be consistent with the value type.")
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.value is not None:
for error in verify_value_data_type(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
if that.value_id is not None:
for error in self.transform(that.value_id):
error.path._prepend(PropertySegment(that, "value_id"))
yield error
# noinspection PyMethodMayBeStatic
def transform_multi_language_property(
self, that: aas_types.MultiLanguageProperty
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.category is not None)
or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
):
yield Error(
"Constraint AASd-090: For data elements category shall be "
+ "one of the following values: CONSTANT, PARAMETER or "
+ "VARIABLE."
)
if not (
not (that.value is not None)
or lang_strings_have_unique_languages(that.value)
):
yield Error("Value must specify unique languages.")
if not (not (that.value is not None) or (len(that.value) >= 1)):
yield Error("Value must be either not set or have at least one item.")
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.value is not None:
for i, yet_yet_yet_yet_yet_another_item in enumerate(that.value):
for error in self.transform(yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.value, i))
error.path._prepend(PropertySegment(that, "value"))
yield error
if that.value_id is not None:
for error in self.transform(that.value_id):
error.path._prepend(PropertySegment(that, "value_id"))
yield error
# noinspection PyMethodMayBeStatic
def transform_range(self, that: aas_types.Range) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.category is not None)
or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
):
yield Error(
"Constraint AASd-090: For data elements category shall be "
+ "one of the following values: CONSTANT, PARAMETER or "
+ "VARIABLE."
)
if not (
not (that.max is not None)
or value_consistent_with_xsd_type(that.max, that.value_type)
):
yield Error("Max must be consistent with the value type.")
if not (
not (that.min is not None)
or value_consistent_with_xsd_type(that.min, that.value_type)
):
yield Error("Min must be consistent with the value type.")
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.min is not None:
for error in verify_value_data_type(that.min):
error.path._prepend(PropertySegment(that, "min"))
yield error
if that.max is not None:
for error in verify_value_data_type(that.max):
error.path._prepend(PropertySegment(that, "max"))
yield error
# noinspection PyMethodMayBeStatic
def transform_reference_element(
self, that: aas_types.ReferenceElement
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.category is not None)
or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
):
yield Error(
"Constraint AASd-090: For data elements category shall be "
+ "one of the following values: CONSTANT, PARAMETER or "
+ "VARIABLE."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.value is not None:
for error in self.transform(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
# noinspection PyMethodMayBeStatic
def transform_blob(self, that: aas_types.Blob) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.category is not None)
or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
):
yield Error(
"Constraint AASd-090: For data elements category shall be "
+ "one of the following values: CONSTANT, PARAMETER or "
+ "VARIABLE."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.value is not None:
for error in verify_blob_type(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
for error in verify_content_type(that.content_type):
error.path._prepend(PropertySegment(that, "content_type"))
yield error
# noinspection PyMethodMayBeStatic
def transform_file(self, that: aas_types.File) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.category is not None)
or (that.category in aas_constants.VALID_CATEGORIES_FOR_DATA_ELEMENT)
):
yield Error(
"Constraint AASd-090: For data elements category shall be "
+ "one of the following values: CONSTANT, PARAMETER or "
+ "VARIABLE."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.value is not None:
for error in verify_path_type(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
for error in verify_content_type(that.content_type):
error.path._prepend(PropertySegment(that, "content_type"))
yield error
# noinspection PyMethodMayBeStatic
def transform_annotated_relationship_element(
self, that: aas_types.AnnotatedRelationshipElement
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (not (that.annotations is not None) or (len(that.annotations) >= 1)):
yield Error(
"Annotations must be either not set or have at least one " + "item."
)
if not (
not (that.annotations is not None)
or (all(item.id_short is not None for item in that.annotations))
):
yield Error(
"ID-shorts need to be defined for all the items of "
+ "annotations according to AASd-117 (ID-short of Referables "
+ "not being a direct child of a Submodel element list shall "
+ "be specified)."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
for error in self.transform(that.first):
error.path._prepend(PropertySegment(that, "first"))
yield error
for error in self.transform(that.second):
error.path._prepend(PropertySegment(that, "second"))
yield error
if that.annotations is not None:
for i, yet_yet_yet_yet_yet_another_item in enumerate(that.annotations):
for error in self.transform(yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.annotations, i))
error.path._prepend(PropertySegment(that, "annotations"))
yield error
# noinspection PyMethodMayBeStatic
def transform_entity(self, that: aas_types.Entity) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (not (that.statements is not None) or (len(that.statements) >= 1)):
yield Error("Statements must be either not set or have at least one item.")
if not (
not (that.statements is not None)
or (all(item.id_short is not None for item in that.statements))
):
yield Error(
"ID-shorts need to be defined for all the items of "
+ "statements according to AASd-117 (ID-short of Referables "
+ "not being a direct child of a Submodel element list shall "
+ "be specified)."
)
if not (
(
(
(
that.entity_type == aas_types.EntityType.SELF_MANAGED_ENTITY
and (
(
(
(
(that.global_asset_id is not None)
and (that.specific_asset_ids is None)
)
)
or (
(
(that.global_asset_id is None)
and (that.specific_asset_ids is not None)
and len(that.specific_asset_ids) >= 1
)
)
)
)
)
)
or (
(
that.entity_type != aas_types.EntityType.SELF_MANAGED_ENTITY
and (that.global_asset_id is None)
and (that.specific_asset_ids is None)
)
)
)
):
yield Error(
"Constraint AASd-014: Either the attribute global asset ID "
+ "or specific asset ID must be set if entity type is set to "
+ "self-managed entity. They are not existing otherwise."
)
if not (
not (that.specific_asset_ids is not None)
or (len(that.specific_asset_ids) >= 1)
):
yield Error(
"Specific asset IDs must be either not set or have at least "
+ "one item."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.statements is not None:
for i, yet_yet_yet_yet_yet_another_item in enumerate(that.statements):
for error in self.transform(yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.statements, i))
error.path._prepend(PropertySegment(that, "statements"))
yield error
if that.global_asset_id is not None:
for error in verify_identifier(that.global_asset_id):
error.path._prepend(PropertySegment(that, "global_asset_id"))
yield error
if that.specific_asset_ids is not None:
for i, yet_yet_yet_yet_yet_yet_another_item in enumerate(
that.specific_asset_ids
):
for error in self.transform(yet_yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.specific_asset_ids, i))
error.path._prepend(PropertySegment(that, "specific_asset_ids"))
yield error
# noinspection PyMethodMayBeStatic
def transform_event_payload(self, that: aas_types.EventPayload) -> Iterator[Error]:
if not (
(
is_model_reference_to(that.source, aas_types.KeyTypes.EVENT_ELEMENT)
or is_model_reference_to(
that.source, aas_types.KeyTypes.BASIC_EVENT_ELEMENT
)
)
):
yield Error("Source must be a model reference to an Event element.")
if not (is_model_reference_to_referable(that.observable_reference)):
yield Error(
"Observable reference must be a model reference to " + "a referable."
)
for error in self.transform(that.source):
error.path._prepend(PropertySegment(that, "source"))
yield error
if that.source_semantic_id is not None:
for error in self.transform(that.source_semantic_id):
error.path._prepend(PropertySegment(that, "source_semantic_id"))
yield error
for error in self.transform(that.observable_reference):
error.path._prepend(PropertySegment(that, "observable_reference"))
yield error
if that.observable_semantic_id is not None:
for error in self.transform(that.observable_semantic_id):
error.path._prepend(PropertySegment(that, "observable_semantic_id"))
yield error
if that.topic is not None:
for error in verify_message_topic_type(that.topic):
error.path._prepend(PropertySegment(that, "topic"))
yield error
if that.subject_id is not None:
for error in self.transform(that.subject_id):
error.path._prepend(PropertySegment(that, "subject_id"))
yield error
for error in verify_date_time_utc(that.time_stamp):
error.path._prepend(PropertySegment(that, "time_stamp"))
yield error
if that.payload is not None:
for error in verify_blob_type(that.payload):
error.path._prepend(PropertySegment(that, "payload"))
yield error
# noinspection PyMethodMayBeStatic
def transform_basic_event_element(
self, that: aas_types.BasicEventElement
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
not (that.direction == aas_types.Direction.INPUT)
or (that.max_interval is None)
):
yield Error("Max. interval is not applicable for input direction.")
if not is_model_reference_to_referable(that.observed):
yield Error("Observed must be a model reference to a referable.")
if not (
not (that.message_broker is not None)
or is_model_reference_to_referable(that.message_broker)
):
yield Error("Message broker must be a model reference to a referable.")
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
for error in self.transform(that.observed):
error.path._prepend(PropertySegment(that, "observed"))
yield error
if that.message_topic is not None:
for error in verify_message_topic_type(that.message_topic):
error.path._prepend(PropertySegment(that, "message_topic"))
yield error
if that.message_broker is not None:
for error in self.transform(that.message_broker):
error.path._prepend(PropertySegment(that, "message_broker"))
yield error
if that.last_update is not None:
for error in verify_date_time_utc(that.last_update):
error.path._prepend(PropertySegment(that, "last_update"))
yield error
if that.min_interval is not None:
for error in verify_duration(that.min_interval):
error.path._prepend(PropertySegment(that, "min_interval"))
yield error
if that.max_interval is not None:
for error in verify_duration(that.max_interval):
error.path._prepend(PropertySegment(that, "max_interval"))
yield error
# noinspection PyMethodMayBeStatic
def transform_operation(self, that: aas_types.Operation) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (
id_shorts_of_variables_are_unique(
that.input_variables, that.output_variables, that.inoutput_variables
)
):
yield Error(
"Constraint AASd-134: For an Operation the ID-short of all "
+ "values of input, output and in/output variables shall be "
+ "unique."
)
if not (
not (that.input_variables is not None) or (len(that.input_variables) >= 1)
):
yield Error(
"Input variables must be either not set or have at least one " + "item."
)
if not (
not (that.output_variables is not None) or (len(that.output_variables) >= 1)
):
yield Error(
"Output variables must be either not set or have at least "
+ "one item."
)
if not (
not (that.inoutput_variables is not None)
or (len(that.inoutput_variables) >= 1)
):
yield Error(
"Inoutput variables must be either not set or have at least "
+ "one item."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.input_variables is not None:
for i, yet_yet_yet_yet_yet_another_item in enumerate(that.input_variables):
for error in self.transform(yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.input_variables, i))
error.path._prepend(PropertySegment(that, "input_variables"))
yield error
if that.output_variables is not None:
for i, yet_yet_yet_yet_yet_yet_another_item in enumerate(
that.output_variables
):
for error in self.transform(yet_yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.output_variables, i))
error.path._prepend(PropertySegment(that, "output_variables"))
yield error
if that.inoutput_variables is not None:
for i, yet_yet_yet_yet_yet_yet_yet_another_item in enumerate(
that.inoutput_variables
):
for error in self.transform(yet_yet_yet_yet_yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.inoutput_variables, i))
error.path._prepend(PropertySegment(that, "inoutput_variables"))
yield error
# noinspection PyMethodMayBeStatic
def transform_operation_variable(
self, that: aas_types.OperationVariable
) -> Iterator[Error]:
if not (that.value.id_short is not None):
yield Error(
"Value must have the ID-short specified according to "
+ "Constraint AASd-117 (ID-short of Referables not being "
+ "a direct child of a Submodel element list shall be "
+ "specified)."
)
for error in self.transform(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
# noinspection PyMethodMayBeStatic
def transform_capability(self, that: aas_types.Capability) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.supplemental_semantic_ids is not None)
or (len(that.supplemental_semantic_ids) >= 1)
):
yield Error(
"Supplemental semantic IDs must be either not set or have at "
+ "least one item."
)
if not (
not (that.supplemental_semantic_ids is not None)
or (that.semantic_id is not None)
):
yield Error(
"Constraint AASd-118: If there are supplemental semantic IDs "
+ "defined then there shall be also a main semantic ID."
)
if not (not (that.qualifiers is not None) or (len(that.qualifiers) >= 1)):
yield Error("Qualifiers must be either not set or have at least one item.")
if not (
not (that.qualifiers is not None)
or qualifier_types_are_unique(that.qualifiers)
):
yield Error(
"Constraint AASd-021: Every qualifiable can only have one "
+ "qualifier with the same type."
)
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.semantic_id is not None:
for error in self.transform(that.semantic_id):
error.path._prepend(PropertySegment(that, "semantic_id"))
yield error
if that.supplemental_semantic_ids is not None:
for i, yet_yet_another_item in enumerate(that.supplemental_semantic_ids):
for error in self.transform(yet_yet_another_item):
error.path._prepend(IndexSegment(that.supplemental_semantic_ids, i))
error.path._prepend(
PropertySegment(that, "supplemental_semantic_ids")
)
yield error
if that.qualifiers is not None:
for i, yet_yet_yet_another_item in enumerate(that.qualifiers):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.qualifiers, i))
error.path._prepend(PropertySegment(that, "qualifiers"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_yet_yet_another_item in enumerate(
that.embedded_data_specifications
):
for error in self.transform(yet_yet_yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
# noinspection PyMethodMayBeStatic
def transform_concept_description(
self, that: aas_types.ConceptDescription
) -> Iterator[Error]:
if not (not (that.extensions is not None) or (len(that.extensions) >= 1)):
yield Error("Extensions must be either not set or have at least one item.")
if not (
not (that.extensions is not None)
or extension_names_are_unique(that.extensions)
):
yield Error(
"Constraint AASd-077: The name of an extension within "
+ "Has-Extensions needs to be unique."
)
if not (not (that.description is not None) or (len(that.description) >= 1)):
yield Error(
"Description must be either not set or have at least one " + "item."
)
if not (
not (that.description is not None)
or lang_strings_have_unique_languages(that.description)
):
yield Error("Description must specify unique languages.")
if not (not (that.display_name is not None) or (len(that.display_name) >= 1)):
yield Error(
"Display name must be either not set or have at least one " + "item."
)
if not (
not (that.display_name is not None)
or lang_strings_have_unique_languages(that.display_name)
):
yield Error("Display name must specify unique languages.")
if not (
not (that.embedded_data_specifications is not None)
or (len(that.embedded_data_specifications) >= 1)
):
yield Error(
"Embedded data specifications must be either not set or have "
+ "at least one item."
)
if not (not (that.is_case_of is not None) or (len(that.is_case_of) >= 1)):
yield Error("Is-case-of must be either not set or have at least one item.")
if not (
not (that.embedded_data_specifications is not None)
or (
(
data_specification_iec_61360s_have_definition_at_least_in_english(
that.embedded_data_specifications
)
or data_specification_iec_61360s_have_value(
that.embedded_data_specifications
)
)
)
):
yield Error(
"Constraint AASc-3a-008: For a concept description using "
+ "data specification template IEC 61360, the definition is "
+ "mandatory and shall be defined at least in English. "
+ "Exception: The concept description describes a value."
)
if not (
not (
(
(that.category is not None)
and that.category == "QUALIFIER_TYPE"
and (that.embedded_data_specifications is not None)
)
)
or data_specification_iec_61360s_have_data_type(
that.embedded_data_specifications
)
):
yield Error(
"Constraint AASc-3a-007: For a concept description with "
+ "category QUALIFIER_TYPE using data specification IEC 61360, "
+ "the data type of the data specification is mandatory and "
+ "shall be defined."
)
if not (
not (
(
(that.category is not None)
and that.category == "DOCUMENT"
and (that.embedded_data_specifications is not None)
)
)
or data_specification_iec_61360s_for_document_have_appropriate_data_type(
that.embedded_data_specifications
)
):
yield Error(
"Constraint AASc-3a-006: For a concept description with "
+ "category DOCUMENT using data specification IEC 61360, "
+ "the data type of the data specification shall be one of: "
+ "FILE, BLOB, HTML."
)
if not (
not (
(
(that.category is not None)
and that.category == "REFERENCE"
and (that.embedded_data_specifications is not None)
)
)
or data_specification_iec_61360s_for_reference_have_appropriate_data_type(
that.embedded_data_specifications
)
):
yield Error(
"Constraint AASc-3a-005: For a concept description with "
+ "category REFERENCE using data specification IEC 61360, "
+ "the data type of the data specification shall be one of: "
+ "STRING, IRI, IRDI."
)
if not (
not (
(
(that.category is not None)
and ((that.category == "PROPERTY" or that.category == "VALUE"))
and (that.embedded_data_specifications is not None)
)
)
or data_specification_iec_61360s_for_property_or_value_have_appropriate_data_type(
that.embedded_data_specifications
)
):
yield Error(
"Constraint AASc-3a-004: For a concept description with "
+ "category PROPERTY or VALUE using data specification IEC "
+ "61360, the data type of the data specification is mandatory "
+ "and shall be one of: DATE, STRING, STRING_TRANSLATABLE, "
+ "INTEGER_MEASURE, INTEGER_COUNT, INTEGER_CURRENCY, "
+ "REAL_MEASURE, REAL_COUNT, REAL_CURRENCY, BOOLEAN, RATIONAL, "
+ "RATIONAL_MEASURE, TIME, TIMESTAMP."
)
if that.extensions is not None:
for i, an_item in enumerate(that.extensions):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.extensions, i))
error.path._prepend(PropertySegment(that, "extensions"))
yield error
if that.category is not None:
for error in verify_name_type(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short_type(that.id_short):
error.path._prepend(PropertySegment(that, "id_short"))
yield error
if that.display_name is not None:
for i, another_item in enumerate(that.display_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.display_name, i))
error.path._prepend(PropertySegment(that, "display_name"))
yield error
if that.description is not None:
for i, yet_another_item in enumerate(that.description):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.description, i))
error.path._prepend(PropertySegment(that, "description"))
yield error
if that.administration is not None:
for error in self.transform(that.administration):
error.path._prepend(PropertySegment(that, "administration"))
yield error
for error in verify_identifier(that.id):
error.path._prepend(PropertySegment(that, "id"))
yield error
if that.embedded_data_specifications is not None:
for i, yet_yet_another_item in enumerate(that.embedded_data_specifications):
for error in self.transform(yet_yet_another_item):
error.path._prepend(
IndexSegment(that.embedded_data_specifications, i)
)
error.path._prepend(
PropertySegment(that, "embedded_data_specifications")
)
yield error
if that.is_case_of is not None:
for i, yet_yet_yet_another_item in enumerate(that.is_case_of):
for error in self.transform(yet_yet_yet_another_item):
error.path._prepend(IndexSegment(that.is_case_of, i))
error.path._prepend(PropertySegment(that, "is_case_of"))
yield error
# noinspection PyMethodMayBeStatic
def transform_reference(self, that: aas_types.Reference) -> Iterator[Error]:
if not (len(that.keys) >= 1):
yield Error("Keys must contain at least one item.")
if not (
not (len(that.keys) >= 1)
or (that.keys[0].type in aas_constants.GLOBALLY_IDENTIFIABLES)
):
yield Error(
"Constraint AASd-121: For References the value of type of "
+ "the first key of keys shall be one of Globally "
+ "Identifiables."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.EXTERNAL_REFERENCE
and len(that.keys) >= 1
)
)
or (that.keys[0].type in aas_constants.GENERIC_GLOBALLY_IDENTIFIABLES)
):
yield Error(
"Constraint AASd-122: For external references the value of "
+ "type of the first key of keys shall be one of Generic "
+ "Globally Identifiables."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
and len(that.keys) >= 1
)
)
or (that.keys[0].type in aas_constants.AAS_IDENTIFIABLES)
):
yield Error(
"Constraint AASd-123: For model references the value of type "
+ "of the first key of keys shall be one of AAS identifiables."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.EXTERNAL_REFERENCE
and len(that.keys) >= 1
)
)
or (
(
(that.keys[-1].type in aas_constants.GENERIC_GLOBALLY_IDENTIFIABLES)
or (that.keys[-1].type in aas_constants.GENERIC_FRAGMENT_KEYS)
)
)
):
yield Error(
"Constraint AASd-124: For external references the last key "
+ "of keys shall be either one of Generic Globally "
+ "Identifiables or one of Generic Fragment Keys."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
and len(that.keys) > 1
)
)
or (
all(
that.keys[i].type in aas_constants.FRAGMENT_KEYS
for i in range(1, len(that.keys))
)
)
):
yield Error(
"Constraint AASd-125: For model references with more than "
+ "one key in keys the value of type of each of the keys "
+ "following the first key of keys shall be one of Fragment "
+ "Keys."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
and len(that.keys) > 1
)
)
or (
all(
not (that.keys[i].type in aas_constants.GENERIC_FRAGMENT_KEYS)
for i in range(0, len(that.keys) - 1)
)
)
):
yield Error(
"Constraint AASd-126: For model references with more than "
+ "one key in keys the value of type of the last key in "
+ "the reference key chain may be one of Generic Fragment Keys "
+ "or no key at all shall have a value out of Generic Fragment "
+ "Keys."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
and len(that.keys) > 1
and that.keys[-1].type == aas_types.KeyTypes.FRAGMENT_REFERENCE
)
)
or (
(
that.keys[-2].type == aas_types.KeyTypes.FILE
or that.keys[-2].type == aas_types.KeyTypes.BLOB
)
)
):
yield Error(
"Constraint AASd-127: For model references, with more than "
+ "one key in keys a key with type Fragment Reference shall be "
+ "preceded by a key with type File or Blob."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.MODEL_REFERENCE
and len(that.keys) > 2
)
)
or (
all(
not (that.keys[i].type == aas_types.KeyTypes.SUBMODEL_ELEMENT_LIST)
or matches_xs_non_negative_integer(that.keys[i + 1].value)
for i in range(0, len(that.keys) - 1)
)
)
):
yield Error(
"Constraint AASd-128: For model references, the value of "
+ "a key preceded by a key with type Submodel element list is "
+ "an integer number denoting the position in the array of "
+ "the submodel element list."
)
if that.referred_semantic_id is not None:
for error in self.transform(that.referred_semantic_id):
error.path._prepend(PropertySegment(that, "referred_semantic_id"))
yield error
for i, an_item in enumerate(that.keys):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.keys, i))
error.path._prepend(PropertySegment(that, "keys"))
yield error
# noinspection PyMethodMayBeStatic
def transform_key(self, that: aas_types.Key) -> Iterator[Error]:
for error in verify_identifier(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
# noinspection PyMethodMayBeStatic
def transform_lang_string_name_type(
self, that: aas_types.LangStringNameType
) -> Iterator[Error]:
if not (len(that.text) <= 128):
yield Error("String shall have a maximum length of 128 characters.")
for error in verify_bcp_47_language_tag(that.language):
error.path._prepend(PropertySegment(that, "language"))
yield error
for error in verify_non_empty_xml_serializable_string(that.text):
error.path._prepend(PropertySegment(that, "text"))
yield error
# noinspection PyMethodMayBeStatic
def transform_lang_string_text_type(
self, that: aas_types.LangStringTextType
) -> Iterator[Error]:
if not (len(that.text) <= 1023):
yield Error("String shall have a maximum length of 1023 characters.")
for error in verify_bcp_47_language_tag(that.language):
error.path._prepend(PropertySegment(that, "language"))
yield error
for error in verify_non_empty_xml_serializable_string(that.text):
error.path._prepend(PropertySegment(that, "text"))
yield error
# noinspection PyMethodMayBeStatic
def transform_environment(self, that: aas_types.Environment) -> Iterator[Error]:
if not (
not (that.concept_descriptions is not None)
or (len(that.concept_descriptions) >= 1)
):
yield Error(
"Concept descriptions must be either not set or have at "
+ "least one item."
)
if not (not (that.submodels is not None) or (len(that.submodels) >= 1)):
yield Error("Submodels must be either not set or have at least one item.")
if not (
not (that.asset_administration_shells is not None)
or (len(that.asset_administration_shells) >= 1)
):
yield Error(
"Asset administration shells must be either not set or have "
+ "at least one item."
)
if that.asset_administration_shells is not None:
for i, an_item in enumerate(that.asset_administration_shells):
for error in self.transform(an_item):
error.path._prepend(
IndexSegment(that.asset_administration_shells, i)
)
error.path._prepend(
PropertySegment(that, "asset_administration_shells")
)
yield error
if that.submodels is not None:
for i, another_item in enumerate(that.submodels):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.submodels, i))
error.path._prepend(PropertySegment(that, "submodels"))
yield error
if that.concept_descriptions is not None:
for i, yet_another_item in enumerate(that.concept_descriptions):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.concept_descriptions, i))
error.path._prepend(PropertySegment(that, "concept_descriptions"))
yield error
# noinspection PyMethodMayBeStatic
def transform_embedded_data_specification(
self, that: aas_types.EmbeddedDataSpecification
) -> Iterator[Error]:
for error in self.transform(that.data_specification):
error.path._prepend(PropertySegment(that, "data_specification"))
yield error
for error in self.transform(that.data_specification_content):
error.path._prepend(PropertySegment(that, "data_specification_content"))
yield error
# noinspection PyMethodMayBeStatic
def transform_level_type(self, that: aas_types.LevelType) -> Iterator[Error]:
# No verification has been defined for LevelType.
return
# For this uncommon return-yield construction, see:
# https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
# noinspection PyUnreachableCode
yield
# noinspection PyMethodMayBeStatic
def transform_value_reference_pair(
self, that: aas_types.ValueReferencePair
) -> Iterator[Error]:
for error in verify_value_type_iec_61360(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
for error in self.transform(that.value_id):
error.path._prepend(PropertySegment(that, "value_id"))
yield error
# noinspection PyMethodMayBeStatic
def transform_value_list(self, that: aas_types.ValueList) -> Iterator[Error]:
if not (len(that.value_reference_pairs) >= 1):
yield Error("Value reference pair types must contain at least one item.")
for i, an_item in enumerate(that.value_reference_pairs):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.value_reference_pairs, i))
error.path._prepend(PropertySegment(that, "value_reference_pairs"))
yield error
# noinspection PyMethodMayBeStatic
def transform_lang_string_preferred_name_type_iec_61360(
self, that: aas_types.LangStringPreferredNameTypeIEC61360
) -> Iterator[Error]:
if not (len(that.text) <= 255):
yield Error("String shall have a maximum length of 255 characters.")
for error in verify_bcp_47_language_tag(that.language):
error.path._prepend(PropertySegment(that, "language"))
yield error
for error in verify_non_empty_xml_serializable_string(that.text):
error.path._prepend(PropertySegment(that, "text"))
yield error
# noinspection PyMethodMayBeStatic
def transform_lang_string_short_name_type_iec_61360(
self, that: aas_types.LangStringShortNameTypeIEC61360
) -> Iterator[Error]:
if not (len(that.text) <= 18):
yield Error("String shall have a maximum length of 18 characters.")
for error in verify_bcp_47_language_tag(that.language):
error.path._prepend(PropertySegment(that, "language"))
yield error
for error in verify_non_empty_xml_serializable_string(that.text):
error.path._prepend(PropertySegment(that, "text"))
yield error
# noinspection PyMethodMayBeStatic
def transform_lang_string_definition_type_iec_61360(
self, that: aas_types.LangStringDefinitionTypeIEC61360
) -> Iterator[Error]:
if not (len(that.text) <= 1023):
yield Error("String shall have a maximum length of 1023 characters.")
for error in verify_bcp_47_language_tag(that.language):
error.path._prepend(PropertySegment(that, "language"))
yield error
for error in verify_non_empty_xml_serializable_string(that.text):
error.path._prepend(PropertySegment(that, "text"))
yield error
# noinspection PyMethodMayBeStatic
def transform_data_specification_iec_61360(
self, that: aas_types.DataSpecificationIEC61360
) -> Iterator[Error]:
if not (not (((that.value is not None) and (that.value_list is not None)))):
yield Error(
"Constraint AASc-3a-010: If value is not empty then value "
+ "list shall be empty and vice versa."
)
if not (
not (
(
(that.data_type is not None)
and (that.data_type in aas_constants.IEC_61360_DATA_TYPES_WITH_UNIT)
)
)
or (((that.unit is not None) or (that.unit_id is not None)))
):
yield Error(
"Constraint AASc-3a-009: If data type is a an integer, real "
+ "or rational with a measure or currency, unit or unit ID "
+ "shall be defined."
)
if not (not (that.definition is not None) or (len(that.definition) >= 1)):
yield Error("Definition must be either not set or have at least one item.")
if not (
not (that.definition is not None)
or lang_strings_have_unique_languages(that.definition)
):
yield Error("Definition must specify unique languages.")
if not (not (that.short_name is not None) or (len(that.short_name) >= 1)):
yield Error("Short name must be either not set or have at least one item.")
if not (
not (that.short_name is not None)
or lang_strings_have_unique_languages(that.short_name)
):
yield Error("Short name must specify unique languages.")
if not (len(that.preferred_name) >= 1):
yield Error("Preferred name must have at least one item.")
if not (lang_strings_have_unique_languages(that.preferred_name)):
yield Error("Preferred name must specify unique languages.")
if not (
any(
is_bcp_47_for_english(lang_string.language)
for lang_string in that.preferred_name
)
):
yield Error(
"Constraint AASc-3a-002: preferred name shall be provided at "
+ "least in English."
)
for i, an_item in enumerate(that.preferred_name):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.preferred_name, i))
error.path._prepend(PropertySegment(that, "preferred_name"))
yield error
if that.short_name is not None:
for i, another_item in enumerate(that.short_name):
for error in self.transform(another_item):
error.path._prepend(IndexSegment(that.short_name, i))
error.path._prepend(PropertySegment(that, "short_name"))
yield error
if that.unit is not None:
for error in verify_non_empty_xml_serializable_string(that.unit):
error.path._prepend(PropertySegment(that, "unit"))
yield error
if that.unit_id is not None:
for error in self.transform(that.unit_id):
error.path._prepend(PropertySegment(that, "unit_id"))
yield error
if that.source_of_definition is not None:
for error in verify_non_empty_xml_serializable_string(
that.source_of_definition
):
error.path._prepend(PropertySegment(that, "source_of_definition"))
yield error
if that.symbol is not None:
for error in verify_non_empty_xml_serializable_string(that.symbol):
error.path._prepend(PropertySegment(that, "symbol"))
yield error
if that.definition is not None:
for i, yet_another_item in enumerate(that.definition):
for error in self.transform(yet_another_item):
error.path._prepend(IndexSegment(that.definition, i))
error.path._prepend(PropertySegment(that, "definition"))
yield error
if that.value_format is not None:
for error in verify_non_empty_xml_serializable_string(that.value_format):
error.path._prepend(PropertySegment(that, "value_format"))
yield error
if that.value_list is not None:
for error in self.transform(that.value_list):
error.path._prepend(PropertySegment(that, "value_list"))
yield error
if that.value is not None:
for error in verify_value_type_iec_61360(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
if that.level_type is not None:
for error in self.transform(that.level_type):
error.path._prepend(PropertySegment(that, "level_type"))
yield error
_TRANSFORMER = _Transformer()
[docs]def verify(that: aas_types.Class) -> Iterator[Error]:
"""
Verify the constraints of :paramref:`that` recursively.
:param that: instance whose constraints we want to verify
:yield: constraint violations
"""
yield from _TRANSFORMER.transform(that)
[docs]def verify_xml_serializable_string(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
[docs]def verify_non_empty_xml_serializable_string(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
[docs]def verify_date_time_utc(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xs_date_time_utc(that):
yield Error(
"The value must match the pattern of xs:dateTime with "
+ "the time zone fixed to UTC."
)
if not is_xs_date_time_utc(that):
yield Error(
"The value must represent a valid xs:dateTime with the time "
+ "zone fixed to UTC."
)
[docs]def verify_duration(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xs_duration(that):
yield Error("The value must match the pattern of xs:duration.")
# noinspection PyUnusedLocal
[docs]def verify_blob_type(that: bytes) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
# There is no verification specified.
return
# Empty generator according to:
# https://stackoverflow.com/a/13243870/1600678
# noinspection PyUnreachableCode
yield
[docs]def verify_identifier(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 2000):
yield Error("Identifier shall have a maximum length of 2000 characters.")
[docs]def verify_value_type_iec_61360(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 2000):
yield Error(
"Value type IEC 61360 shall have a maximum length of 2000 " + "characters."
)
[docs]def verify_name_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 128):
yield Error("Name type shall have a maximum length of 128 characters.")
[docs]def verify_version_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not matches_version_type(that):
yield Error("Version type shall match the version pattern.")
if not (len(that) <= 4):
yield Error("Version type shall have a maximum length of 4 characters.")
[docs]def verify_revision_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not matches_revision_type(that):
yield Error("Revision type shall match the revision pattern.")
if not (len(that) <= 4):
yield Error("Revision type shall have a maximum length of 4 characters.")
[docs]def verify_label_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 64):
yield Error("Label type shall have a maximum length of 64 characters.")
[docs]def verify_message_topic_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 255):
yield Error(
"Message topic type shall have a maximum length of 255 " + "characters."
)
[docs]def verify_bcp_47_language_tag(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_bcp_47(that):
yield Error(
"The value must represent a value language tag conformant to " + "BCP 47."
)
[docs]def verify_content_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 100):
yield Error("Content type shall have a maximum length of 100 characters.")
if not matches_mime_type(that):
yield Error(
"The value must represent a valid content MIME type "
+ "according to RFC 2046."
)
[docs]def verify_path_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 2000):
yield Error("Identifier shall have a maximum length of 2000 characters.")
if not matches_rfc_2396(that):
yield Error(
"String with max 2048 and min 1 characters conformant to "
+ "a URI as per RFC 2396."
)
[docs]def verify_qualifier_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 128):
yield Error("Name type shall have a maximum length of 128 characters.")
[docs]def verify_value_data_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
[docs]def verify_id_short_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xml_serializable_string(that):
yield Error(
"Constraint AASd-130: An attribute with data type 'string' "
+ "shall consist of these characters only: "
+ "^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010FFFF]*$."
)
if not (len(that) >= 1):
yield Error("The value must not be empty.")
if not (len(that) <= 128):
yield Error("Name type shall have a maximum length of 128 characters.")
if not matches_id_short(that):
yield Error(
"ID-short of Referables shall only feature letters, digits, "
+ "underscore (``_``); starting mandatory with a letter. "
+ "*I.e.* ``[a-zA-Z][a-zA-Z0-9_]*``."
)
# This code has been automatically generated by aas-core-codegen.
# Do NOT edit or append.