diff --git a/src/bsdd/bsdd_json.py b/src/bsdd/bsdd_json.py new file mode 100644 index 0000000000..61c18982e6 --- /dev/null +++ b/src/bsdd/bsdd_json.py @@ -0,0 +1,281 @@ +from __future__ import annotations + +from pydantic import BaseModel +from .type_hints import * +from typing import List, Optional, Literal +from datetime import datetime +from pydantic import BaseModel, Field, PrivateAttr, model_validator, ConfigDict +import json +import weakref +import logging + + +def _lower_first(s: str) -> str: + return s[:1].lower() + s[1:] if s else s + + +class CaseInsensitiveModel(BaseModel): + model_config = ConfigDict(populate_by_name=True, alias_generator=_lower_first) + + +class BsddDictionary(CaseInsensitiveModel): + OrganizationCode: str + DictionaryCode: str + DictionaryVersion: str + LanguageIsoCode: LANGUAGE_ISO_CODE + LanguageOnly: bool + UseOwnUri: bool + DictionaryName: Optional[str] = None + DictionaryUri: Optional[str] = None + License: Optional[str] = "MIT" + LicenseUrl: Optional[str] = None + ChangeRequestEmailAddress: Optional[str] = None + ModelVersion: Optional[str] = "2.0" + MoreInfoUrl: Optional[str] = None + QualityAssuranceProcedure: Optional[str] = None + QualityAssuranceProcedureUrl: Optional[str] = None + ReleaseDate: Optional[datetime] = None + Status: Optional[STATUS] = None + Classes: List[BsddClass] = Field(default_factory=list) + Properties: List[BsddProperty] = Field(default_factory=list) + + @classmethod + def load(cls, path) -> BsddDictionary: + """Load from a JSON file and validate via the normalizer above.""" + with open(path, "r", encoding="utf-8") as f: + raw = json.load(f) + # The model_validator(before) handles list/dict/nested shapes + return cls.model_validate(raw) + + def save(self, path): + with open(path, "w") as file: + json.dump(self.model_dump(mode="json", exclude_none=True), file) + + # add Parent to children after loading + def model_post_init(self, context): + for c in self.Classes: + c._set_parent(self) + for p in self.Properties: + p._set_parent(self) + + +class BsddClass(CaseInsensitiveModel): + Code: str + Name: str + ClassType: CLASS_TYPE = "Class" + Definition: Optional[str] = None + Description: Optional[str] = None + ParentClassCode: Optional[str | None] = None + RelatedIfcEntityNamesList: Optional[List[str]] = None + Synonyms: Optional[List[str]] = None + ActivationDateUtc: Optional[datetime] = None + ReferenceCode: Optional[str] = None + CountriesOfUse: Optional[List[COUNTRY_CODE]] = None + CountryOfOrigin: Optional[COUNTRY_CODE] = None + CreatorLanguageIsoCode: Optional[LANGUAGE_ISO_CODE] = None + DeActivationDateUtc: Optional[datetime] = None + DeprecationExplanation: Optional[str] = None + DocumentReference: Optional[str] = None + OwnedUri: Optional[str] = None + ReplacedObjectCodes: Optional[List[str]] = None + ReplacingObjectCodes: Optional[List[str]] = None + RevisionDateUtc: Optional[datetime] = None + RevisionNumber: Optional[int] = None + Status: Optional[CLASS_STATUS] = None + SubdivisionsOfUse: Optional[List[str]] = None + Uid: Optional[str] = None + VersionDateUtc: Optional[datetime] = None + VersionNumber: Optional[int] = None + VisualRepresentationUri: Optional[str] = None + ClassProperties: List[BsddClassProperty] = Field(default_factory=list) + ClassRelations: List[BsddClassRelation] = Field(default_factory=list) + + _parent_ref: Optional[weakref.ReferenceType["BsddDictionary"]] = PrivateAttr( + default=None + ) + + def _set_parent(self, parent: "BsddDictionary") -> None: + self._parent_ref = weakref.ref(parent) + + def parent(self) -> Optional[BsddDictionary]: + return self._parent_ref() if self._parent_ref is not None else None + + def model_post_init(self, context): + for c in self.ClassProperties: + c._set_parent(self) + for cr in self.ClassRelations: + cr._set_parent(self) + + def _apply_code_side_effects(self, code: str) -> None: + from bsdd_json.utils import class_utils as cl_utils + + if not code.strip(): + logging.info("Empty Code is not allowed") + raise ValueError("Empty Code is not allowed") + + parent = self._parent_ref() if self._parent_ref else None + if parent is not None and code in cl_utils.get_all_class_codes(parent): + logging.info(f"Code '{code}' exists already") + raise ValueError(f"Code '{code}' exists already") + + # propagate to children + for child in cl_utils.get_children(self): + child.ParentClassCode = code + + +class BsddClassRelation(CaseInsensitiveModel): + RelationType: CLASS_RELATION_TYPE + RelatedClassUri: str + RelatedClassName: Optional[str] = None + Fraction: Optional[float] = None + OwnedUri: Optional[str] = None + + def _set_parent(self, parent: BsddClass) -> None: + self._parent_ref = weakref.ref(parent) + + def parent(self) -> Optional[BsddClass]: + return self._parent_ref() if self._parent_ref is not None else None + + +class BsddAllowedValue(CaseInsensitiveModel): + Code: str + Value: str + Description: Optional[str] = None + Uri: Optional[str] = None + SortNumber: Optional[int] = None + OwnedUri: Optional[str] = None + + +class BsddClassProperty(CaseInsensitiveModel): + Code: str + PropertyCode: Optional[str] = None + PropertyUri: Optional[str] = None + Description: Optional[str] = None + PropertySet: Optional[str] = None + Unit: Optional[str] = None + PredefinedValue: Optional[str] = None + IsRequired: Optional[bool] = None + IsWritable: Optional[bool] = None + MaxExclusive: Optional[float] = None + MaxInclusive: Optional[float] = None + MinExclusive: Optional[float] = None + MinInclusive: Optional[float] = None + Pattern: Optional[str] = None + OwnedUri: Optional[str] = None + PropertyType: Optional[Literal["Property", "Dependency"]] = None + SortNumber: Optional[int] = None + Symbol: Optional[str] = None + AllowedValues: List[BsddAllowedValue] = Field(default_factory=list) + _parent_ref: Optional[weakref.ReferenceType["BsddClass"]] = PrivateAttr( + default=None + ) + + def _set_parent(self, parent: "BsddClass") -> None: + self._parent_ref = weakref.ref(parent) + + def parent(self) -> Optional[BsddClass]: + return self._parent_ref() if self._parent_ref is not None else None + + @model_validator(mode="after") + def _validate_property_code_or_uri(self): + """ + only one of PropertyCode or PropertyUri must be set (XOR) + """ + # normalize whitespace + code = ( + self.PropertyCode.strip() + if self.PropertyCode and isinstance(self.PropertyCode, str) + else None + ) + uri = ( + self.PropertyUri.strip() + if self.PropertyUri and isinstance(self.PropertyUri, str) + else None + ) + + # XOR: exactly one must be provided + if bool(code) == bool(uri): + raise ValueError( + "Exactly one of PropertyCode or PropertyUri must be provided (not both, not neither)" + ) + + # assign normalized values back + object.__setattr__(self, "PropertyCode", code) + object.__setattr__(self, "PropertyUri", uri) + return self + + +class BsddProperty(CaseInsensitiveModel): + Code: str + Name: str + Definition: Optional[str] = None + Description: Optional[str] = None + DataType: Optional[DATATYPE_TYPE] = None + Units: Optional[List[UNITS_TYPE]] = None + Example: Optional[str] = None + ActivationDateUtc: Optional[datetime] = None + ConnectedPropertyCodes: Optional[List[str]] = None + CountriesOfUse: Optional[List[COUNTRY_CODE]] = None + CountryOfOrigin: Optional[COUNTRY_CODE] = None + CreatorLanguageIsoCode: Optional[LANGUAGE_ISO_CODE] = None + DeActivationDateUtc: Optional[datetime] = None + DeprecationExplanation: Optional[str] = None + Dimension: Optional[str] = None + DimensionLength: Optional[int] = None + DimensionMass: Optional[int] = None + DimensionTime: Optional[int] = None + DimensionElectricCurrent: Optional[int] = None + DimensionThermodynamicTemperature: Optional[int] = None + DimensionAmountOfSubstance: Optional[int] = None + DimensionLuminousIntensity: Optional[int] = None + DocumentReference: Optional[DOCUMENT_TYPE] = None + DynamicParameterPropertyCodes: Optional[List[str]] = None + IsDynamic: Optional[bool] = None + MaxExclusive: Optional[float] = None + MaxInclusive: Optional[float] = None + MinExclusive: Optional[float] = None + MinInclusive: Optional[float] = None + MethodOfMeasurement: Optional[str] = None + OwnedUri: Optional[str] = None + Pattern: Optional[str] = None + PhysicalQuantity: Optional[str] = None + PropertyValueKind: Optional[PROPERTY_VALUE_KIND_TYPE] = None + ReplacedObjectCodes: Optional[List[str]] = None + ReplacingObjectCodes: Optional[List[str]] = None + RevisionDateUtc: Optional[datetime] = None + RevisionNumber: Optional[int] = None + Status: Optional[PROPERTY_STATUS] = None + SubdivisionsOfUse: Optional[List[str]] = None + TextFormat: Optional[str] = None + Uid: Optional[str] = None + VersionDateUtc: Optional[datetime] = None + VersionNumber: Optional[int] = None + VisualRepresentationUri: Optional[str] = None + PropertyRelations: List[BsddPropertyRelation] = Field(default_factory=list) + AllowedValues: List[BsddAllowedValue] = Field(default_factory=list) + _parent_ref: Optional[weakref.ReferenceType["BsddDictionary"]] = PrivateAttr( + default=None + ) + + def _set_parent(self, parent: "BsddDictionary") -> None: + self._parent_ref = weakref.ref(parent) + + def parent(self) -> Optional[BsddDictionary]: + return self._parent_ref() if self._parent_ref is not None else None + + def model_post_init(self, context): + for pr in self.PropertyRelations: + pr._set_parent(self) + + +class BsddPropertyRelation(CaseInsensitiveModel): + RelatedPropertyName: Optional[str] = None + RelatedPropertyUri: str + RelationType: PROPERTY_RELATION_TYPE + OwnedUri: Optional[str] = None + + def _set_parent(self, parent: BsddProperty) -> None: + self._parent_ref = weakref.ref(parent) + + def parent(self) -> Optional[BsddProperty]: + return self._parent_ref() if self._parent_ref is not None else None diff --git a/src/bsdd/pyproject.toml b/src/bsdd/pyproject.toml index 0a9df5cb79..2704dc673e 100644 --- a/src/bsdd/pyproject.toml +++ b/src/bsdd/pyproject.toml @@ -40,4 +40,4 @@ Documentation = "https://docs.ifcopenshell.org" Issues = "https://github.com/IfcOpenShell/IfcOpenShell/issues" [tool.setuptools] -py-modules = ["bsdd"] +py-modules = ["bsdd","bsdd_json","type_hints"] diff --git a/src/bsdd/type_hints.py b/src/bsdd/type_hints.py new file mode 100644 index 0000000000..ac9aa29923 --- /dev/null +++ b/src/bsdd/type_hints.py @@ -0,0 +1,1525 @@ +from typing import Literal, Annotated +from datetime import datetime +from pydantic import BeforeValidator + + +COUNTRY_CODE = Literal[ + "AF", + "AX", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "KH", + "CM", + "CA", + "CV", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CG", + "CD", + "CK", + "CR", + "CI", + "HR", + "CU", + "CY", + "CZ", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MK", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "AN", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "RE", + "RO", + "RU", + "RW", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SZ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "US", + "UM", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "EU", +] + +CLASS_TYPE = Literal[ + "Class", + "Material", + "GroupOfProperties", + "AlternativeUse", + # deprecated but may appear in API results + "ReferenceDocument", + "ComposedProperty", + "Dictionary", +] + +STATUS = Literal["Preview", "Active", "Inactive"] +CLASS_STATUS = Literal["Active", "Inactive"] +PROPERTY_STATUS = Literal["Active", "Inactive"] + +# Pydantic-validated DateTime adhering to bSDD import rules +LANGUAGE_ISO_CODE = Literal[ + "EN", + "en-GB", + "nl-NL", + "nb-NO", + "nl-BE", + "fr-BE", + "de-DE", + "it-IT", + "sv-SE", + "fr-FR", + "es-ES", + "en-AU", + "fa-IR", + "pl-PL", + "lv-LV", + "en-NZ", + "sr-SP", + "zh-CN", + "ru-RU", + "vi-VN", + "bg-BG", + "kr-KR", + "ar-SA", + "el-GR", + "de-AT", + "mn-MN", + "en-CA", + "lt-LT", + "da-DK", + "de-CH", + "et-EE", + "cs-CZ", + "nn-NO", + "en-US", + "pt-BR", + "fi-FI", + "ja-JP", + "no-NO", + "pt-PT", +] + +CLASS_RELATION_TYPE = Literal[ + "HasMaterial", + "HasReference", + "IsEqualTo", + "IsSimilarTo", + "IsParentOf", + "IsChildOf", + "HasPart", + "IsPartOf", +] + +PROPERTY_RELATION_TYPE = Literal["HasReference", "IsEqualTo", "IsSimilarTo"] + +DATATYPE_TYPE = Literal["Boolean", "Character", "Integer", "Real", "String", "Time"] +UNITS_TYPE = Literal[ + "N", + "mm", + "dB", + "K", + "°C", + "N/m", + "J", + "H", + "px", + "pf", + "pH", + "%RH", + "gH₂O/kgAir", + "V/K", + "°daysC", + "°daysF", + "%obsc/ft", + "%obsc/m", + "psi/°F", + "m²/N", + "dBmV", + "dBµV", + "ppu", + "ppm", + "ppb", + "g/kg", + "rad", + "deg", + "degPh", + "sr", + "ntu", + "fnu", + "PUE", + "DCIE", + "AFN", + "DZD", + "ARS", + "AMD", + "AWG", + "AUD", + "AZN", + "BSD", + "BHD", + "THB", + "PAB", + "BBD", + "BYR", + "BZD", + "BMD", + "VEF", + "BOB", + "BRL", + "BND", + "BGN", + "BIF", + "CAD", + "CVE", + "KYD", + "GHS", + "XAF", + "XPF", + "CLP", + "CNY", + "CDF", + "NIO", + "CRC", + "HRK", + "CUP", + "CZK", + "GMD", + "DKK", + "MKD", + "DJF", + "STD", + "DOP", + "VND", + "XCD", + "EGP", + "ETB", + "EUR", + "FKP", + "FJD", + "HUF", + "GIP", + "HTG", + "PYG", + "GNF", + "GYD", + "HKD", + "UAH", + "ISK", + "INR", + "IRR", + "IQD", + "JMD", + "JOD", + "KES", + "PGK", + "LAK", + "BAM", + "KWD", + "MWK", + "AOA", + "MMK", + "GEL", + "LBP", + "ALL", + "HNL", + "SLL", + "RON", + "LRD", + "LYD", + "SZL", + "LSL", + "MGA", + "MYR", + "TMT", + "MUR", + "MZN", + "MXN", + "MDL", + "MAD", + "NGN", + "ERN", + "NAD", + "NPR", + "ILS", + "NZD", + "BTN", + "KPW", + "NOK", + "PEN", + "MRO", + "PKR", + "MOP", + "UYU", + "PHP", + "GBP", + "BWP", + "PLN", + "QAR", + "GTQ", + "ZAR", + "OMR", + "KHR", + "MVR", + "IDR", + "RUB", + "RWF", + "SHP", + "SAR", + "RSD", + "SCR", + "SGD", + "SBD", + "KGS", + "SOS", + "TJS", + "KRW", + "LKR", + "SDG", + "SRD", + "SEK", + "CHF", + "SYP", + "TWD", + "BDT", + "WST", + "TZS", + "KZT", + "TTD", + "MNT", + "TND", + "TRY", + "AED", + "UGX", + "USD", + "UZS", + "VUV", + "YER", + "JPY", + "ZMW", + "ZWL", + "m/s²", + "rad/s²", + "Js", + "rad/s", + "rpm", + "m²", + "mm²", + "cm²", + "km²", + "in²", + "ft²", + "yd²", + "mile²", + "acre", + "F", + "COP", + "kg/m³", + "µg/m³", + "C", + "Ah", + "S", + "A", + "mA", + "A/m²", + "V/m", + "Volt", + "mV", + "kV", + "MV", + "MΩ", + "mΩ", + "S/m", + "kJ", + "Wh", + "kWh", + "MWh", + "BTU", + "kBTU", + "MBTU", + "hph", + "cal", + "therm", + "tonrefh", + "MJ", + "GJ", + "Nm", + "N/m²", + "m³ gas", + "ft³ gas", + "hundred cubic feet natural gas", + "thousand cubic feet natural gas", + "million cubic feet natural gas", + "VAh", + "kVAh", + "MVAh", + "VARh", + "kVARh", + "MVARh", + "J/m²", + "Wh/m²", + "Wh/ft²", + "kWh/m²", + "kWh/ft²", + "MWh/m²", + "MWh/ft²", + "MJ/m²", + "MJ/ft²", + "kBTU/ft²", + "MBTU/ft²", + "J/g", + "J/kg", + "J/kg dry", + "BTU/lb", + "kJ/kg", + "kJ/kg dry", + "MJ/kg dry", + "cal/g", + "lbf", + "Hz", + "kHz", + "cph", + "cpm", + "MHz", + "%/s", + "ACH", + "kg/m²", + "g/m²", + "K/s", + "°C/h", + "°C/min", + "°F/h", + "°F/min", + "K/h", + "K/min", + "lx", + "fc", + "phot", + "W/m² irr", + "W/ft² irr", + "m", + "µm", + "cm", + "km", + "in", + "ft", + "yd", + "mile", + "cd/m²", + "cd/ft²", + "lm", + "cd", + "A/m", + "Wb", + "T", + "kg", + "mg", + "g", + "oz", + "lb", + "klb", + "t", + "kg/s", + "kg/min", + "kg/h", + "lb/min", + "lb/h", + "lb/s", + "klb/h", + "g/s", + "g/min", + "Ns", + "W", + "mW", + "kW", + "MW", + "GW", + "BTU/h", + "therm/h", + "hp", + "tonref", + "kBTU/h", + "MBTU/h", + "J/h", + "kJ/h", + "MJ/h", + "GJ/h", + "W/m²", + "W/ft²", + "kW/m²", + "kW/ft²", + "kBTU/h/ft²", + "W/m³/s", + "W/cfm", + "kW/kcfm", + "kW/gal/min", + "VA", + "kVA", + "VAR", + "kVAR", + "MVAR", + "Pa", + "kPa", + "bar", + "atm", + "psi", + "cmH₂O", + "in/wc", + "mmHg", + "cmHg", + "inHg", + "hPa", + "mbar", + "°F", + "ns", + "µs", + "ms", + "cs", + "ds", + "min", + "hr", + "day", + "wk", + "mo", + "yr", + "m/s", + "km/s", + "km/h", + "mph", + "ft/s", + "ft/min", + "mm/s", + "mm/min", + "m/min", + "m/h", + "knot", + "m³", + "mm³", + "cm³", + "hL", + "kL", + "in³", + "ft³", + "yd³", + "gal", + "kgal", + "qt", + "pt", + "fl oz", + "galUK", + "hft³", + "m³/s", + "mL/s", + "hL/s", + "cfs", + "cfm", + "cfh", + "kcfm", + "galUK/min", + "gal/min", + "gal/hr", + "m³/min", + "m³/h", + "byte", + "kB", + "MB", + "GB", + "TB", + "PB", + "dBi", + "Mbit/s", + "Bft", + "kW/(m³/s)", + "kg/24h", + "mH", + "dB(A)", + "W/K", + "kN", + "l/s", + "h", + "GJ/jaar", + "l", + "%/100%", + "AirWatt", + "kWp", + "m rad", + "kJ/m²", + "kcmil", + "Jaar", + "dB(A) re 1 pW", + "N/mm", + "kJ/Ohm", + "Megapixel", + "%/K", + "mm/m", + "cSt", + "c/min", + "c/h", + "1/min", + "l/min", + "kBit/s", + "Mbyte", + "kByte", + "kOhm", + "l/h", + "mAh", + "opm", + "W/m", + "Bd", + "DPI", + "lm/W", + "µH", + "µF", + "AX", + "nm", + "°", + "%", + "ml", + "kg/m", + "GHz", + "MOhm", + "mOhm", + "kA", + "Ohm", + "s", + "V", + "Wp", + "Imp/kWh (kvarh)", + "dB(C)", + "% m/md", + "°dH", + "µS/cm", + "cal/cm²", + "dm", + "g/cm³", + "g/h", + "g/l", + "g/m³", + "Gbit/s", + "HRC", + "kg/cm/m²", + "kg/km", + "kN/m²", + "m²/h", + "m²/l", + "m²/m", + "m³/m²h50Pa", + "mg/l", + "mH2O", + "Month", + "MP", + "N/mm²", + "nmi", + "Ohm/km", + "PSU", + "Rpm", + "kg·m²", + "mm²/m", + "Gbit/sec", + "MPa", + "cm⁴", + "kg/100m", + "kg/dm³", + "m⁴", + "mm⁴", + "TPI", + "'", + "µA", + "A/°C", + "A/cm", + "A/cm²", + "A/J", + "A/mm", + "A/mm²", + "A/(m²·K²)", + "A/rad", + "Ao", + "ar", + "As", + "At", + "bbl", + "bit", + "bit/s", + "Bq", + "BTU/lb dry", + "BTU/Wh", + "C·m", + "cL", + "CYP", + "J/K", + "J/kg·K", + "kJ/K", + "MJ/K", + "MVA", + "u", + "kN/m", + "1/K", + "1/m", + "1/m²", + "cm²/m", + "kPa·s/m³", + "?", + "kN/m³", + "MN/m²", + "MN/m³", + "mol", + "mol/l", + "mS/cm", + "μT", + "1/h", + "1/s", + "mg/dm²", + "CTUe", + "CTUh", + "kg CFC11 eq", + "kg N eq", + "kg NMVOC eq", + "kg SO2 eq", + "m³/(h·m²) @ 50Pa", + "mg/kg", + "mg/m²/h", + "mg/m³", + "mol H+ eq", + "mol N eq", + "PTV", + "unitless", + "kBq U235 eq", + "kg ethene eq", + "kg Sb eq", + "kg/m/s/Pa", + "m³/m²sPa", + "mol/m²", + "mol/m²/d", + "mol/m²/s", + "mol/m³", + "kW/tonne", + "tonne", + "tonne/h", + "dBm", + "kg C", + "kg O₃ eq", + "kg CO₂ eq", + "kg PO₄³⁻ eq", + "m²/s", + "m³/m", + "mm/(m·K)", + "mol/(m·s·Pa)", + "mol/(m³·Pa)", + "N·m²/rad", + "Ohm·m", + "Pa·s", + "A·m²", + "A·m²/(J·s)", + "ft·lbs/sec", + "GJ/yr", + "kJ/(kg·K)", + "m/(N·m²)", + "m²·K/W", + "Pa·√m", + "ppmv", + "W/(m²·K)", + "W/(m²·K²)", + "W/(m·K)", + "Fps", + "kWh/(m²·a)", + "l/m", + "Wh/°C", +] +DOCUMENT_TYPE = Literal[ + "CR 12793:1997", + "CR 13933:2000", + "CEN/TR 15697:2008", + "CEN/TR 15678:2008", + "CEN/TR 16142:2011", + "EN 13639:2017", + "CEN/TR 16632:2014", + "CEN/TR 16912:2016", + "EN 413-2:2016", + "EN 196-3:2016", + "EN 197-2:2020", + "EN 196-10:2016", + "EN 13282-3:2015", + "EN 459-3:2015", + "EN 13282-2:2015", + "EN 459-1:2015", + "EN 196-1:2016", + "EN 197-1:2011", + "CEN/TS 12390-9:2016", + "EN 196-9:2010", + "CEN/TR 15177:2006", + "EN 15368:2008+A1:2010", + "EN 196-6:2018", + "EN 196-8:2010", + "CEN/TR 17365:2019", + "CEN/TR 14245:2020", + "EN 13282-1:2013", + "CEN/TR 196-4:2007", + "EN 196-5:2011", + "EN 14216:2015", + "EN 16908:2017", + "EN 14647:2005/AC:2006", + "EN 196-11:2018", + "EN 459-2:2010", + "EN 15743:2010+A1:2015", + "EN 196-7:2007", + "EN 14647:2005", + "EN 413-1:2011", + "EN 196-2:2013", + "EN ISO 18233:2006", + "EN ISO 10140-2:2010", + "EN ISO 3382-2:2008", + "EN ISO 10140-3:2010", + "EN ISO 10140-5:2010", + "EN ISO 3822-1:1999/A1:2008", + "EN ISO 3822-2:1995", + "EN 29052-1:1992", + "EN ISO 10534-1:2001", + "EN ISO 10534-2:2001", + "EN ISO 3822-1:1999", + "EN ISO 11654:1997", + "EN ISO 12354-1:2017", + "EN ISO 12354-2:2017", + "EN ISO 12354-3:2017", + "EN ISO 12354-4:2017", + "EN ISO 3382-1:2009", + "EN ISO 16032:2004", + "EN ISO 3382-3:2012", + "EN ISO 717-1:2013", + "EN ISO 717-2:2013", + "EN ISO 15186-2:2010", + "EN ISO 15186-3:2010", + "EN ISO 3382-2:2008/AC:2009", + "EN ISO 10052:2004/A1:2010", + "EN ISO 12999-1:2014", + "EN ISO 10140-5:2010/A1:2014", + "EN 12354-5:2009/AC:2010", + "EN ISO 16283-3:2016", + "EN 16703:2015", + "EN ISO 10140-3:2010/A1:2015", + "EN ISO 10848-4:2017", + "EN ISO 3822-3:2018", + "EN ISO 16283-1:2014/A1:2017", + "EN 16205:2013+A1:2018", + "EN ISO 10848-3:2017", + "CEN/TR 16961:2018", + "EN ISO 10848-2:2017", + "EN ISO 16283-2:2020", + "EN 15657:2017", + "EN ISO 10140-1:2016", + "CEN/TR 15226:2006", + "EN 14366:2004+A1:2019", + "EN ISO 10140-4:2010", + "EN 12354-6:2003", + "EN ISO 10848-1:2017", + "EN ISO 16251-1:2014", + "EN 12354-5:2009", + "EN ISO 12999-2:2020", + "EN ISO 9053-1:2018", + "EN ISO 3822-4:1997", + "EN ISO 15186-1:2003", + "EN ISO 16283-1:2014", + "EN ISO 354:2003", + "EN 16487:2014", + "EN ISO 10052:2004", + "EN 1748-2-1:2004", + "EN ISO 14438:2002", + "EN 14178-1:2004", + "EN 14178-2:2004", + "EN 1748-1-1:2004", + "EN 14449:2005/AC:2005", + "EN ISO 12543-5:2011", + "EN ISO 12543-2:2011", + "EN ISO 12543-4:2011", + "EN ISO 12543-3:2011", + "EN 13024-1:2011", + "EN 1863-1:2011", + "EN 15681-1:2016", + "EN 1096-5:2016", + "EN 15681-2:2017", + "EN 16612:2019", + "EN 12150-1:2015+A1:2019", + "EN 1096-4:2018", + "EN 1279-6:2018", + "EN 1279-3:2018", + "EN 1279-5:2018", + "EN 1279-1:2018", + "EN 14179-1:2016", + "EN 17074:2019", + "EN 12898:2019", + "EN 12488:2016", + "EN 1748-1-2:2004", + "EN 1748-2-2:2004", + "EN 572-9:2004", + "EN ISO 12543-6:2011/AC:2012", + "EN 16613:2019", + "EN ISO 12543-1:2011", + "EN 14449:2005", + "EN ISO 12543-6:2011", + "EN 1279-2:2018", + "EN 1279-4:2018", + "EN 16477-1:2016", + "EN 12758:2019", + "EN 572-8:2012+A1:2016", + "EN 12337-2:2004", + "EN 1288-3:2000", + "EN 572-7:2012", + "EN 1096-1:2012", + "EN 1288-1:2000", + "EN 14321-2:2005", + "EN 572-1:2012+A1:2016", + "EN 1036-2:2008", + "EN 356:1999", + "EN 12150-2:2004", + "EN 410:2011", + "EN 1288-4:2000", + "EN 13541:2012", + "EN 1051-2:2007", + "EN 12600:2002", + "EN 12603:2002", + "EN 673:2011", + "EN 675:2011", + "EN 13022-1:2014", + "EN 1288-5:2000", + "EN 13022-2:2014", + "EN 12337-1:2000", + "EN 15682-2:2013", + "EN 1288-2:2000", + "EN 15755-1:2014", + "EN 14179-2:2005", + "EN 1096-3:2012", + "EN 15998:2010", + "EN 1063:1999", + "EN 1096-2:2012", + "EN 15683-2:2013", + "EN 572-6:2012", + "EN 14321-1:2005", + "EN 1863-2:2004", + "EN 15683-1:2013", + "EN 1036-1:2007", + "EN 15682-1:2013", + "EN 572-5:2012", + "EN 572-4:2012", + "EN 13024-2:2004", + "EN 15752-1:2014", + "EN 572-2:2012", + "EN 1051-1:2003", + "EN 674:2011", + "EN 572-3:2012", + "EN ISO 5353:1998", + "EN ISO 3411:2007", + "EN ISO 3450:2011", + "EN ISO 2867:2011", + "EN ISO 6683:2008", + "EN ISO 2860:2008", + "EN ISO 3457:2008", + "EN ISO 3449:2008", + "EN 13035-3:2003+A1:2009/AC:2010", + "EN 474-2:2006+A1:2008", + "EN 474-11:2006+A1:2008", + "EN 474-12:2006+A1:2008", + "EN 13019:2001+A1:2008", + "EN 474-9:2006+A1:2009", + "EN 474-10:2006+A1:2009", + "EN 474-8:2006+A1:2009", + "EN 12110:2014", + "EN 13367:2005+A1:2008/AC:2009", + "EN ISO 13766-2:2018", + "EN ISO 13766-1:2018", + "EN ISO 3164:2013", + "EN 474-4:2006+A2:2012", + "EN 536:2015", + "EN 16564:2014", + "EN 1009-4:2020", + "EN 1009-5:2020", + "EN 1009-2:2020", + "EN 474-5:2006+A3:2013", + "EN 15163:2017", + "EN 474-1:2006+A4:2013/AC:2014", + "EN 15059:2009+A1:2015", + "EN ISO 19432-1:2020", + "EN 13042-3:2007+A1:2009", + "EN 13102:2005+A1:2008", + "EN 500-4:2011", + "EN 12348:2000+A1:2009", + "EN 500-1:2006+A1:2009", + "EN 500-6:2006+A1:2008", + "EN 13035-2:2008", + "EN ISO 16001:2017", + "EN 474-1:2006+A6:2019", + "EN ISO 19014-1:2018", + "EN ISO 7096:2020", + "EN ISO 19014-3:2018", + "EN 15573:2008", + "EN 12629-4:2001+A1:2010", + "EN 12629-5-1:2003+A1:2010", + "EN 13035-7:2006+A1:2009", + "EN 13035-3:2003+A1:2009", + "EN 15162:2008", + "EN 13531:2001+A1:2008", + "EN 15164:2008", + "EN 12629-3:2002+A1:2010", + "EN 12629-5-3:2003+A1:2010", + "EN 13042-5:2003+A1:2009", + "EN 12629-8:2002+A1:2010", + "EN 13042-2:2004+A1:2009", + "EN 12629-5-4:2003+A1:2010", + "EN 13035-4:2003+A1:2009", + "EN 12629-1:2000+A1:2010", + "EN 13035-9:2006+A1:2010", + "EN 12629-5-2:2003+A1:2010", + "EN 13042-1:2007+A1:2009", + "EN 12629-7:2004+A1:2010", + "EN 1009-1:2020", + "EN 13524:2003+A2:2014", + "EN 15572:2015", + "EN 13020:2015", + "EN 474-6:2006+A1:2009", + "EN 1009-3:2020", + "EN ISO 19014-4:2020", + "EN ISO 6682:2008", + "EN ISO 6165:2012", + "EN 15571:2014", + "EN 13367:2005+A1:2008", + "EN 15027:2007+A1:2009", + "EN ISO 5010:2019", + "EN 16191:2014", + "EN 500-3:2006+A1:2008", + "EN 474-7:2006+A1:2009", + "EN 13035-1:2008", + "EN 474-3:2006+A1:2009", + "EN 12001:2012", + "EN 13035-5:2006+A1:2009", + "EN ISO 3471:2008", + "EN 13021:2003+A1:2008", + "EN 13035-6:2006+A1:2009", + "EN 12629-2:2002+A1:2010", + "CEN/TS 15730:2008", + "EN 12629-6:2004+A1:2010", + "EN 13035-11:2006+A1:2010", + "EN 16228-3:2014", + "EN 13862:2001+A1:2009", + "EN 16228-4:2014", + "EN 16228-1:2014", + "EN 12418:2000+A1:2009", + "EN 12649:2008+A1:2011", + "EN 500-2:2006+A1:2008", + "EN 16228-2:2014", + "EN 16228-6:2014", + "EN 16228-5:2014", + "EN 16228-7:2014", + "EN 13813:2002", + "EN 13318:2000", + "EN 13892-6:2002", + "EN 13892-9:2018", + "EN 14016-1:2004", + "EN 13892-3:2014", + "EN 13892-2:2002", + "EN 13892-4:2002", + "EN 14016-2:2004", + "EN 13892-1:2002", + "EN 13892-7:2003", + "EN 13892-5:2003", + "EN 13892-8:2002", + "CWA 17377:2019", + "EN ISO 12006-3:2016", + "EN ISO 23387:2020", + "EN ISO 23386:2020", + "EN ISO 16757-2:2019", + "CEN/TR 17439:2020", + "EN ISO 16739-1:2020", + "EN ISO 19650-3:2020", + "EN ISO 19650-5:2020", + "EN ISO 29481-2:2016", + "EN ISO 29481-1:2017", + "EN ISO 21597-1:2020", + "EN ISO 19650-2:2018", + "EN ISO 16757-1:2019", + "EN ISO 12006-2:2020", + "EN ISO 19650-1:2018", + "CWA 17316:2018", + "EN ISO 8394-1:2010", + "EN 15651-1:2017", + "EN 15651-4:2017", + "EN 15651-5:2017", + "CEN/TR 17068:2017", + "EN 15651-4:2017/AC:2017", + "EN ISO 8394-2:2017", + "EN 15651-3:2017", + "EN 15651-2:2017", + "EN 15434:2006+A1:2010", + "CEN/TR 15941:2010", + "EN 15643-5:2017", + "CEN/TR 17005:2016", + "EN 15643-1:2010", + "EN 15643-2:2011", + "EN 15643-4:2012", + "EN 15804:2012+A2:2019", + "EN 16627:2015", + "CEN/TR 16970:2016", + "EN 15643-3:2012", + "EN 16309:2014+A1:2014", + "EN 15942:2011", + "EN 15978:2011", + "CEN/TR 15858:2009", + "CEN/TR 16496:2013", + "CEN/TR 16098:2010", + "CEN/TS 16637-3:2016", + "CEN/TR 16220:2011", + "CEN/TS 17216:2018", + "CEN/TR 16410:2012", + "CEN/TS 17195:2018", + "CEN/TS 17196:2018", + "CEN/TR 17113:2017", + "CEN/TR 16797-1:2015", + "CEN/TR 16797-2:2015", + "CEN/TS 17331:2019", + "CEN/TS 17332:2019", + "EN 17087:2019", + "CEN/TR 17105:2017", + "CEN/TS 16637-1:2018", + "CEN/TS 17200:2018+AC:2018", + "CEN/TS 17201:2018+AC:2018", + "EN 16687:2015", + "EN 16516:2017+A1:2020", + "CEN/TR 15855:2009", + "CEN/TR 16045:2010", + "CEN/TS 16637-2:2014", + "CEN/TS 17197:2018+AC:2018", + "CEN/TR 17304:2018", + "CWA 16519:2012", + "EN 771-3:2011", + "EN 772-1:2011", + "DIN EN 13460", + "DIN EN 13306", + "ISO 13372", + "VDMA 24223", + "VDMA 24223-1", + "DIN ISO 21360-1", + "DIN EN ISO 17769-1", + "ISO/TR 25417", + "DIN 28400-2", + "DIN EN ISO 17769-2", + "DIN EN ISO 80000-8", + "ISO 3529-2", + "VDI 3805-4", + "IEC 60050-351", + "ISO 2710-1", + "ISO 7967-6", + "VDMA 24224", + "DIN EN 1333", + "ISO 6708", + "IEC CDD", + "OPC 10000-100 - Part 100", + "OPC 40001-1", + "IEC 61987-1", + "DIN 105-4:2019-01", + "DIN 1055-4:2005-03", + "DIN 1168-2:1975-07", + "DIN 17611:2022-08", + "DIN 18032-3:2018-11", + "DIN 18202:2019-07", + "DIN 18516-1:2010-06", + "DIN 4074-1:2012-06", + "DIN 4102-1:1998-05", + "DIN 4102-17:2017-12", + "DIN 4102-4:2016-05", + "DIN 4108-10:2021-11", + "DIN 4108-3:2018-10", + "DIN 4108-4:2020-11", + "DIN 4109-1:2018-01", + "EAD 090062-00-0404", + "EN ISO 10545-12:1997-12", + "EN 12467:2018-07", + "EN 13162:2015-04", + "prEN 13300:2021-04", + "EN 13501-1:2019-05", + "EN 13830:2020-11", + "EN 1396:2015-06", + "EN 14081-1:2019-10", + "EN 14351-1:2016-12", + "EN 14411:2016-12", + "EN 1607:2013-05", + "EN 16733:2016-07", + "EN 1991-1-4:2010-12", + "EN 1992-4:2019-04", + "EN 1993-1-4:2015-10", + "EN 1998-1:2010-12", + "EN 338:2016-07", + "EN 492:2018-07", + "EN 494:2015-12", + "EN 60672-2:2000-10", + "EN 61140:2016-11", + "EN 998-1:2017-02", + "EN ISO 10140-1:2021-09", + "EN ISO 10211:2018-03", + "EN ISO 10456:2010-05", + "EN ISO 10545-13:2017-04", + "EN ISO 10545-14:2016-02", + "EN ISO 10545-15:2021-09", + "EN ISO 10545-3:2018-06", + "EN ISO 10545-4:2019-06", + "EN ISO 10545-5:1997-12", + "EN ISO 10545-6:2012-05", + "EN ISO 10545-9:2013-12", + "EN ISO 12944-1:2019-01", + "EN 539-2:2013-08", + "prEN IEC 60904-1:2019-10", + "EN IEC 61730-1:2018-10", + "Musterbauordnung (MBO)", + "MVV TB Anhang 6", + "VKF Prüfbestimmungen", + "VW PV 3.10.7:1992-01", + "EN 54-11:2001/A1:2005", + "EN 54-2:1997/AC:1999", + "EN 54-4:1997/AC:1999", + "EN 54-25:2008", + "EN 54-4:1997/A1:2002", + "CEN/TR 14568:2003", + "EN 54-4:1997/A2:2006", + "EN 54-21:2006", + "EN 54-18:2005/AC:2007", + "EN 54-17:2005/AC:2007", + "EN 54-20:2006/AC:2008", + "EN 54-30:2015", + "EN 54-26:2015", + "CEN/TS 54-14:2018", + "EN 54-29:2015", + "EN 54-1:2021", + "EN 54-3:2014+A1:2019", + "EN 54-7:2018", + "EN 54-22:2015+A1:2020", + "EN 14604:2005", + "EN 54-27:2015", + "EN 54-18:2005", + "EN 54-25:2008/AC:2012", + "EN 54-2:1997/A1:2006", + "EN 14604:2005/AC:2008", + "EN 54-12:2015", + "EN 54-10:2002/A1:2005", + "EN 54-4:1997", + "CEN/TS 54-32:2015", + "EN 54-5:2017+A1:2018", + "EN 54-24:2008", + "EN 54-16:2008", + "EN 54-13:2017+A1:2019", + "EN 54-17:2005", + "EN 54-20:2006", + "EN 54-11:2001", + "EN 54-23:2010", + "EN 54-2:1997", + "EN 54-31:2014+A1:2016", + "EN 54-10:2002", + "EN 54-28:2016", + "EN 13501-2:2016-06", + "UNI 9795:2021", + "EN 10545-2:2019", + "EN 13986", + "EN 15497", + "EN 14342", + "EN 14080", + "EN 14374", + "EN 14915", + "EN 14322", + "EN 1912", + "EN 317", + "ISO 50001", + "EN 12369-1", + "RAL", + "EN 789", + "EN 319", + "EN 13271", + "EN 312", + "EN 318", + "EN 383", + "EN 350", + "EN 12524", + "EN 12871", + "CITES", + "OI3", + "EN 320", + "swiss eco-factors 2013", + "EN 1995-1-1", + "EN 15228", + "LVL", + "EN 1128", + "EN 13183-2", + "EN 13556", + "EN 1995-1-2", + "NCS", + "EN 408", + "EN 594", + "EN 12664", + "EN 351-1", + "CEN/TS 13354", + "EN 324-1", + "EN 12114", + "ISO 14001", + "ISO 140-3", + "EN 1058", + "EC Decision 2000/147/EC", + "EN 301", + "ISO 15686-8:2008", + "ISO 21930:2017", + "EN 1328", + "EN 1309-1", + "ISO 717-1", + "EN 322", + "ISO 3340", + "EN 717-2", + "EN 1533", + "EN ISO 9001", + "WGSRPD", + "ISO 14046:2014", + "CEN/TS 15676", + "EN 14755", + "EN 335", + "EN 335-3", + "EN 975-1", + "EN 13446", + "EN 15425", + "EN 382-2", + "EN 323", + "EN 326-1", + "EN 717-1", + "EN 314-2", + "CEN/TR 14823", + "EN 13017-2", + "ISO 18001", + "ISO 12572", + "EN 384", + "EN 12369-2", + "EN 300", + "EN 16351", + "CML-IA 4.1", + "EN 13353", + "EN 13017-1", + "EN 1195", + "CEN/TS 635-4", + "EN 635-1", + "EN ISO 717-1:2021", + "EN ISO 717-2:2021", + "EN ISO 6946:2017", + "EN ISO 13788:2012", + "ISO 14021:2016", + "ATG-4", + "FHWA-NHI-23-024", + "LRFDBDS-9", + "EwaGlos", + "ICOMOS-ISCS-Glossary", + "UNI 11182:2006", + "ASTM D 610 – 08", + "NORMAL 1/88", +] + +PROPERTY_VALUE_KIND_TYPE = Literal["Single", "Range", "List", "Complex", "ComplexList"]