From daa770fe1233675dbd8318544375a354630f7bab Mon Sep 17 00:00:00 2001 From: Sebastian Heppner Date: Wed, 15 Nov 2023 10:10:18 +0100 Subject: [PATCH] model.Extension: Change refers_to to be of type `Set[Reference]` Currently, `Extension.refers_to` is declared as a `Iterable[Reference]`. This implies, that we can not necessarily check, whether or not the attribute is empty or not. This creates a problem with the XML serialization, since the `` element should only appear if there is at least one `Reference` inside. This commit changes the `Extension.refers_to` to be a set of `Reference`s, as well as adapting a more clear check whether or not the attribute is empty in `adapter.xml.xml_serialization`. --- basyx/aas/adapter/xml/xml_deserialization.py | 9 +++++---- basyx/aas/adapter/xml/xml_serialization.py | 2 +- basyx/aas/examples/data/example_aas.py | 4 ++-- basyx/aas/model/base.py | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/basyx/aas/adapter/xml/xml_deserialization.py b/basyx/aas/adapter/xml/xml_deserialization.py index abc737b2f..4dfbe06d7 100644 --- a/basyx/aas/adapter/xml/xml_deserialization.py +++ b/basyx/aas/adapter/xml/xml_deserialization.py @@ -692,10 +692,11 @@ def construct_extension(cls, element: etree.Element, object_class=model.Extensio value = _get_text_or_none(element.find(NS_AAS + "value")) if value is not None: extension.value = model.datatypes.from_xsd(value, extension.value_type) - extension.refers_to = _failsafe_construct_multiple( - element.find(NS_AAS + "refersTo").findall(NS_AAS + "reference"), - cls._construct_referable_reference, cls.failsafe - ) + refers_to = element.find(NS_AAS + "refersTo") + if refers_to is not None: + for ref in _child_construct_multiple(refers_to, NS_AAS + "reference", cls._construct_referable_reference, + cls.failsafe): + extension.refers_to.add(ref) cls._amend_abstract_attributes(extension, element) return extension diff --git a/basyx/aas/adapter/xml/xml_serialization.py b/basyx/aas/adapter/xml/xml_serialization.py index f3c93800a..106535ae1 100644 --- a/basyx/aas/adapter/xml/xml_serialization.py +++ b/basyx/aas/adapter/xml/xml_serialization.py @@ -277,7 +277,7 @@ def extension_to_xml(obj: model.Extension, tag: str = NS_AAS+"extension") -> etr text=model.datatypes.XSD_TYPE_NAMES[obj.value_type])) if obj.value: et_extension.append(_value_to_xml(obj.value, obj.value_type)) # type: ignore # (value_type could be None) - if obj.refers_to: + if len(obj.refers_to) > 0: refers_to = _generate_element(NS_AAS+"refersTo") for reference in obj.refers_to: refers_to.append(reference_to_xml(reference, NS_AAS+"reference")) diff --git a/basyx/aas/examples/data/example_aas.py b/basyx/aas/examples/data/example_aas.py index 49d3847c4..925b4508f 100644 --- a/basyx/aas/examples/data/example_aas.py +++ b/basyx/aas/examples/data/example_aas.py @@ -101,9 +101,9 @@ def create_example_asset_identification_submodel() -> model.Submodel: name='ExampleExtension', value_type=model.datatypes.String, value="ExampleExtensionValue", - refers_to=(model.ModelReference((model.Key(type_=model.KeyTypes.ASSET_ADMINISTRATION_SHELL, + refers_to=[model.ModelReference((model.Key(type_=model.KeyTypes.ASSET_ADMINISTRATION_SHELL, value='http://acplt.org/RefersTo/ExampleRefersTo'),), - model.AssetAdministrationShell),)) + model.AssetAdministrationShell)],) # Property-Element conform to 'Verwaltungssschale in der Praxis' page 41 ManufacturerName: # https://www.plattform-i40.de/PI40/Redaktion/DE/Downloads/Publikation/2019-verwaltungsschale-in-der-praxis.html diff --git a/basyx/aas/model/base.py b/basyx/aas/model/base.py index 439f45427..9bc2386b1 100644 --- a/basyx/aas/model/base.py +++ b/basyx/aas/model/base.py @@ -1468,7 +1468,7 @@ def __init__(self, self.value_type: Optional[DataTypeDefXsd] = value_type self._value: Optional[ValueDataType] self.value = value - self.refers_to: Iterable[ModelReference] = refers_to + self.refers_to: Set[ModelReference] = set(refers_to) self.semantic_id: Optional[Reference] = semantic_id self.supplemental_semantic_id: ConstrainedList[Reference] = ConstrainedList(supplemental_semantic_id)