"""
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_rc02.types.Extension`:
.. code-block::
import aas_core3_rc02.types as aas_types
import aas_core3_rc02.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_rc02 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()
# 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_xs_date_time_stamp_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"
date_time_stamp_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_stamp_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DATE_TIME_STAMP_UTC = _construct_matches_xs_date_time_stamp_utc()
[docs]def matches_xs_date_time_stamp_utc(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:dateTimeStamp``.
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/xmlschema11-2/#dateTimeStamp
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DATE_TIME_STAMP_UTC.match(text) is not None
[docs]def is_xs_date_time_stamp_utc(value: str) -> bool:
"""
Check that :paramref:`value` is a ``xs:dateTimeStamp`` with
the time zone set to UTC.
"""
if not matches_xs_date_time_stamp_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_8089_path() -> Pattern[str]:
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}:){{2}}{h16})?::({h16}:){{2}}{ls32}|(({h16}:){{3}}{h16})?::{h16}:{ls32}|(({h16}:){{4}}{h16})?::{ls32}|(({h16}:){{5}}{h16})?::{h16}|(({h16}:){{6}}{h16})?::)"
unreserved = "[a-zA-Z0-9\\-._~]"
sub_delims = "[!$&'()*+,;=]"
ipvfuture = f"[vV][0-9A-Fa-f]+\\.({unreserved}|{sub_delims}|:)+"
ip_literal = f"\\[({ipv6address}|{ipvfuture})\\]"
pct_encoded = "%[0-9A-Fa-f][0-9A-Fa-f]"
reg_name = f"({unreserved}|{pct_encoded}|{sub_delims})*"
host = f"({ip_literal}|{ipv4address}|{reg_name})"
file_auth = f"(localhost|{host})"
pchar = f"({unreserved}|{pct_encoded}|{sub_delims}|[:@])"
segment_nz = f"({pchar})+"
segment = f"({pchar})*"
path_absolute = f"/({segment_nz}(/{segment})*)?"
auth_path = f"({file_auth})?{path_absolute}"
local_path = f"{path_absolute}"
file_hier_part = f"(//{auth_path}|{local_path})"
file_scheme = "file"
file_uri = f"{file_scheme}:{file_hier_part}"
pattern = f"^{file_uri}$"
return re.compile(pattern)
_REGEX_MATCHES_RFC_8089_PATH = _construct_matches_rfc_8089_path()
[docs]def matches_rfc_8089_path(text: str) -> bool:
"""
Check that :paramref:`text` is a path conforming to the pattern of RFC 8089.
The definition has been taken from:
https://datatracker.ietf.org/doc/html/rfc8089
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_RFC_8089_PATH.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}){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.LangString],
) -> 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_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}:){{2}}{h16})?::({h16}:){{2}}{ls32}|(({h16}:){{3}}{h16})?::{h16}:{ls32}|(({h16}:){{4}}{h16})?::{ls32}|(({h16}:){{5}}{h16})?::{h16}|(({h16}:){{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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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
# noinspection SpellCheckingInspection
def _construct_matches_xs_date_time_stamp() -> 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_stamp_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_stamp_lexical_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DATE_TIME_STAMP = _construct_matches_xs_date_time_stamp()
[docs]def matches_xs_date_time_stamp(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:dateTimeStamp``.
See: https://www.w3.org/TR/xmlschema11-2/#dateTimeStamp
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DATE_TIME_STAMP.match(text) is not None
# 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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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_day_time_duration() -> Pattern[str]:
day_time_duration_rep = "-?P((([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"^{day_time_duration_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_DAY_TIME_DURATION = _construct_matches_xs_day_time_duration()
[docs]def matches_xs_day_time_duration(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:dayTimeDuration``.
See: https://www.w3.org/TR/xmlschema11-2/#dayTimeDuration
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_DAY_TIME_DURATION.match(text) is not None
# noinspection SpellCheckingInspection
def _construct_matches_xs_year_month_duration() -> Pattern[str]:
year_month_duration_rep = "-?P((([0-9]+Y)([0-9]+M)?)|([0-9]+M))"
pattern = f"^{year_month_duration_rep}$"
return re.compile(pattern)
_REGEX_MATCHES_XS_YEAR_MONTH_DURATION = _construct_matches_xs_year_month_duration()
[docs]def matches_xs_year_month_duration(text: str) -> bool:
"""
Check that :paramref:`text` conforms to the pattern of an ``xs:yearMonthDuration``.
See: https://www.w3.org/TR/xmlschema11-2/#yearMonthDuration
:param text: Text to be checked
:return:
True if the :paramref:`text` conforms to the pattern
"""
return _REGEX_MATCHES_XS_YEAR_MONTH_DURATION.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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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/xmlschema11-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 = "^[\\x01-\\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/xmlschema11-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_date_time(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:dateTime``."""
# 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``).
if not matches_xs_date_time(value):
return False
date, _ = value.split("T")
return is_xs_date(date)
[docs]def is_xs_date_time_stamp(value: str) -> bool:
"""Check that :paramref:`value` is a valid ``xs:dateTimeStamp``."""
if not matches_xs_date_time_stamp(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``).
date, _ = value.split("T")
return is_xs_date(date)
[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.DATE: is_xs_date,
aas_types.DataTypeDefXsd.DATE_TIME: is_xs_date_time,
aas_types.DataTypeDefXsd.DATE_TIME_STAMP: is_xs_date_time_stamp,
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.STRING: matches_xs_string,
aas_types.DataTypeDefXsd.TIME: matches_xs_time,
aas_types.DataTypeDefXsd.DAY_TIME_DURATION: matches_xs_day_time_duration,
aas_types.DataTypeDefXsd.YEAR_MONTH_DURATION: matches_xs_year_month_duration,
aas_types.DataTypeDefXsd.INTEGER: matches_xs_integer,
aas_types.DataTypeDefXsd.LONG: is_xs_long,
aas_types.DataTypeDefXsd.INT: is_xs_int,
aas_types.DataTypeDefXsd.SHORT: is_xs_short,
aas_types.DataTypeDefXsd.BYTE: is_xs_byte,
aas_types.DataTypeDefXsd.NON_NEGATIVE_INTEGER: matches_xs_non_negative_integer,
aas_types.DataTypeDefXsd.POSITIVE_INTEGER: matches_xs_positive_integer,
aas_types.DataTypeDefXsd.UNSIGNED_LONG: is_xs_unsigned_long,
aas_types.DataTypeDefXsd.UNSIGNED_INT: is_xs_unsigned_int,
aas_types.DataTypeDefXsd.UNSIGNED_SHORT: is_xs_unsigned_short,
aas_types.DataTypeDefXsd.UNSIGNED_BYTE: is_xs_unsigned_byte,
aas_types.DataTypeDefXsd.NON_POSITIVE_INTEGER: matches_xs_non_positive_integer,
aas_types.DataTypeDefXsd.NEGATIVE_INTEGER: matches_xs_negative_integer,
}
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)
# noinspection SpellCheckingInspection
def _construct_matches_global_asset_id_literally() -> Pattern[str]:
pattern = "^[gG][lL][oO][bB][aA][lL][aA][sS][sS][eE][tT][iI][dD]$"
return re.compile(pattern)
_REGEX_MATCHES_GLOBAL_ASSET_ID_LITERALLY = (
_construct_matches_global_asset_id_literally()
)
[docs]def matches_global_asset_id_literally(text: str) -> bool:
"""
Check that the :paramref:`text` matches ``globalAssetId`` case-insensitive.
The case-insensitivity depends on the culture. For example in Turkish, uppercase
"i" is "İ", not "I". We assume the culture to be English, and explicitly check
for English case-folding.
:param text:
which needs to match ``globalAssetId`` literally
:return:
True if the :paramref:`text` matches case-insensitive
"""
return _REGEX_MATCHES_GLOBAL_ASSET_ID_LITERALLY.match(text) is not None
[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 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.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_non_empty_string(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 error in self.transform(that.refers_to):
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_non_empty_string(that.version):
error.path._prepend(PropertySegment(that, "version"))
yield error
if that.revision is not None:
for error in verify_non_empty_string(that.revision):
error.path._prepend(PropertySegment(that, "revision"))
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 specifies no duplicate 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 specifies no duplicate 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 (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 self.transform(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.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 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_non_empty_string(that.name):
error.path._prepend(PropertySegment(that, "name"))
yield error
for error in verify_non_empty_string(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
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 specifies no duplicate 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 specifies no duplicate 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(element.id_short is not None for element in that.submodel_elements))
):
yield Error("ID-shorts need to be defined for all the submodel elements.")
if not (
not (that.submodel_elements is not None)
or id_shorts_are_unique(that.submodel_elements)
):
yield Error(
"Constraint AASd-120: ID-short of non-identifiable "
+ "referables shall be unique in its namespace."
)
if not (
not (that.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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.value is not None)
and (
(
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 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-shorts of submodel elements within "
+ "a SubmodelElementList 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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.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
# 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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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(element.id_short is not None for element in that.value))
):
yield Error("ID-shorts need to be defined for all the elements.")
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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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 specifies no duplicate 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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 (
(
(
(
that.entity_type == aas_types.EntityType.SELF_MANAGED_ENTITY
and (
(
(
(
(that.global_asset_id is not None)
and (that.specific_asset_id is None)
)
)
or (
(
(that.global_asset_id is None)
and (that.specific_asset_id is not None)
)
)
)
)
)
)
or (
(
(that.global_asset_id is None)
and (that.specific_asset_id 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 "
+ "'SelfManagedEntity'. They are not existing otherwise."
)
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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 self.transform(that.global_asset_id):
error.path._prepend(PropertySegment(that, "global_asset_id"))
yield error
if that.specific_asset_id is not None:
for error in self.transform(that.specific_asset_id):
error.path._prepend(PropertySegment(that, "specific_asset_id"))
yield error
# noinspection PyMethodMayBeStatic
def transform_event_payload(self, that: aas_types.EventPayload) -> Iterator[Error]:
if not is_model_reference_to_referable(that.source):
yield Error("Source must be a model reference to a referable.")
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_non_empty_string(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_stamp_utc(that.time_stamp):
error.path._prepend(PropertySegment(that, "time_stamp"))
yield error
if that.payload is not None:
for error in verify_non_empty_string(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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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_non_empty_string(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_stamp_utc(that.last_update):
error.path._prepend(PropertySegment(that, "last_update"))
yield error
if that.min_interval is not None:
for error in verify_date_time_stamp_utc(that.min_interval):
error.path._prepend(PropertySegment(that, "min_interval"))
yield error
if that.max_interval is not None:
for error in verify_date_time_stamp_utc(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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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 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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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]:
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 specifies no duplicate 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 specifies no duplicate 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.qualifiers is not None)
or (
not (
any(
qualifier.kind == aas_types.QualifierKind.TEMPLATE_QUALIFIER
for qualifier in that.qualifiers
)
)
or (that.kind_or_default() == aas_types.ModelingKind.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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 specifies no duplicate 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 specifies no duplicate 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.category is not None)
or (that.category in aas_constants.VALID_CATEGORIES_FOR_CONCEPT_DESCRIPTION)
):
yield Error(
"Constraint AASd-051: A concept description shall have one "
+ "of the following categories: 'VALUE', 'PROPERTY', "
+ "'REFERENCE', 'DOCUMENT', 'CAPABILITY',; 'RELATIONSHIP', "
+ "'COLLECTION', 'FUNCTION', 'EVENT', 'ENTITY', "
+ "'APPLICATION_CLASS', 'QUALIFIER', 'VIEW'."
)
if not (
not (
(
(that.category is not None)
and that.category != "VALUE"
and (that.embedded_data_specifications is not None)
)
)
or data_specification_iec_61360s_have_definition_at_least_in_english(
that.embedded_data_specifications
)
):
yield Error(
"Constraint AASc-003: For all concept descriptions with "
+ "a category except VALUE using data specification IEC 61360, "
+ "the definition of the data specification is mandatory and "
+ "shall be defined at least in English."
)
if not (
not (
(
(that.category is not None)
and that.category == "VALUE"
and (that.embedded_data_specifications is not None)
)
)
or data_specification_iec_61360s_have_value(
that.embedded_data_specifications
)
):
yield Error(
"Constraint AASc-008: For a concept description with "
+ "category VALUE using data specification IEC 61360, "
+ "the value of the data specification shall be set."
)
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-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-006: For a concept description with "
+ "category DOCUMENT using data specification IEC 61360, "
+ "the data type of the data specification is mandatory and "
+ "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-005: For a concept description with "
+ "category REFERENCE using data specification IEC 61360, "
+ "the data type of the data specification is mandatory and "
+ "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-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_non_empty_string(that.category):
error.path._prepend(PropertySegment(that, "category"))
yield error
if that.id_short is not None:
for error in verify_id_short(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.checksum is not None:
for error in verify_non_empty_string(that.checksum):
error.path._prepend(PropertySegment(that, "checksum"))
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 type of the first "
+ "key shall be one of Globally identifiables."
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.GLOBAL_REFERENCE
and len(that.keys) >= 1
)
)
or (that.keys[0].type in aas_constants.GENERIC_GLOBALLY_IDENTIFIABLES)
):
yield Error(
"Constraint AASd-122: For global references the type of "
+ "the first key 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 type of "
+ "the first key shall be one of AAS identifiables"
)
if not (
not (
(
that.type == aas_types.ReferenceTypes.GLOBAL_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 global references the last key "
+ "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, the type of the keys following the first key 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, the 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, 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_positive_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_non_empty_string(that.value):
error.path._prepend(PropertySegment(that, "value"))
yield error
# noinspection PyMethodMayBeStatic
def transform_lang_string(self, that: aas_types.LangString) -> Iterator[Error]:
for error in verify_bcp_47_language_tag(that.language):
error.path._prepend(PropertySegment(that, "language"))
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_value_reference_pair(
self, that: aas_types.ValueReferencePair
) -> Iterator[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_data_specification_iec_61360(
self, that: aas_types.DataSpecificationIEC61360
) -> Iterator[Error]:
if not (
(
(((that.value is not None) and (that.value_list is None)))
or (
(
(that.value is None)
and (that.value_list is not None)
and len(that.value_list.value_reference_pairs) >= 1
)
)
)
):
yield Error(
"Constraint AASc-010: If value is not empty then value list "
+ "shall be empty and vice versa."
)
if not (
not (
(
(that.data_type is 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-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 specifies no duplicate 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 specifies no duplicate 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 specifies no duplicate languages")
if not (
any(
is_bcp_47_for_english(lang_string.language)
for lang_string in that.preferred_name
)
):
yield Error(
"Constraint AASc-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_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_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_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_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
# noinspection PyMethodMayBeStatic
def transform_data_specification_physical_unit(
self, that: aas_types.DataSpecificationPhysicalUnit
) -> Iterator[Error]:
if not (len(that.definition) >= 1):
yield Error("Definition must have at least one item")
if not (lang_strings_have_unique_languages(that.definition)):
yield Error("Definition specifies no duplicate languages")
for error in verify_non_empty_string(that.unit_name):
error.path._prepend(PropertySegment(that, "unit_name"))
yield error
for error in verify_non_empty_string(that.unit_symbol):
error.path._prepend(PropertySegment(that, "unit_symbol"))
yield error
for i, an_item in enumerate(that.definition):
for error in self.transform(an_item):
error.path._prepend(IndexSegment(that.definition, i))
error.path._prepend(PropertySegment(that, "definition"))
yield error
if that.si_notation is not None:
for error in verify_non_empty_string(that.si_notation):
error.path._prepend(PropertySegment(that, "si_notation"))
yield error
if that.si_name is not None:
for error in verify_non_empty_string(that.si_name):
error.path._prepend(PropertySegment(that, "si_name"))
yield error
if that.din_notation is not None:
for error in verify_non_empty_string(that.din_notation):
error.path._prepend(PropertySegment(that, "din_notation"))
yield error
if that.ece_name is not None:
for error in verify_non_empty_string(that.ece_name):
error.path._prepend(PropertySegment(that, "ece_name"))
yield error
if that.ece_code is not None:
for error in verify_non_empty_string(that.ece_code):
error.path._prepend(PropertySegment(that, "ece_code"))
yield error
if that.nist_name is not None:
for error in verify_non_empty_string(that.nist_name):
error.path._prepend(PropertySegment(that, "nist_name"))
yield error
if that.source_of_definition is not None:
for error in verify_non_empty_string(that.source_of_definition):
error.path._prepend(PropertySegment(that, "source_of_definition"))
yield error
if that.conversion_factor is not None:
for error in verify_non_empty_string(that.conversion_factor):
error.path._prepend(PropertySegment(that, "conversion_factor"))
yield error
if that.registration_authority_id is not None:
for error in verify_non_empty_string(that.registration_authority_id):
error.path._prepend(PropertySegment(that, "registration_authority_id"))
yield error
if that.supplier is not None:
for error in verify_non_empty_string(that.supplier):
error.path._prepend(PropertySegment(that, "supplier"))
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_non_empty_string(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not (len(that) >= 1):
yield Error(
"Constraint AASd-100: An attribute with data type ``string`` "
+ "is not allowed to be empty."
)
[docs]def verify_date_time_stamp_utc(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not matches_xs_date_time_stamp_utc(that):
yield Error(
"The value must match the pattern of xs:dateTimeStamp with "
+ "the time zone fixed to UTC."
)
if not is_xs_date_time_stamp_utc(that):
yield Error(
"The value must represent a valid xs:dateTimeStamp with "
+ "the time zone fixed to UTC."
)
# 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 (len(that) >= 1):
yield Error(
"Constraint AASd-100: An attribute with data type ``string`` "
+ "is not allowed to be empty."
)
[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 (len(that) >= 1):
yield Error(
"Constraint AASd-100: An attribute with data type ``string`` "
+ "is not allowed to be empty."
)
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 (len(that) >= 1):
yield Error(
"Constraint AASd-100: An attribute with data type ``string`` "
+ "is not allowed to be empty."
)
if not matches_rfc_8089_path(that):
yield Error(
"The value must represent a valid file URI scheme according "
+ "to RFC 8089."
)
[docs]def verify_qualifier_type(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not (len(that) >= 1):
yield Error(
"Constraint AASd-100: An attribute with data type ``string`` "
+ "is not allowed to be empty."
)
# noinspection PyUnusedLocal
[docs]def verify_value_data_type(that: str) -> 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_id_short(that: str) -> Iterator[Error]:
"""Verify the constraints of :paramref:`that`."""
if not (len(that) <= 128):
yield Error(
"Constraint AASd-027: ID-short 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.