diff --git a/aas/model/base.py b/aas/model/base.py index 450fbb2d36a57888e2736023632ce242d33ce688..6f676bbde6e1841f63202c2dbb868d3ca6476829 100644 --- a/aas/model/base.py +++ b/aas/model/base.py @@ -449,6 +449,19 @@ class Namespace(metaclass=abc.ABCMeta): continue raise KeyError(f"{object_type.__name__} with {attribute_name} {attribute} not found in this namespace") + def _add_object(self, attribute_name: str, obj: _NSO) -> None: + """ + Add an :class:`~._NSO` to this namespace by its attribute + + :raises KeyError: If no such :class:`~._NSO` can be found + """ + for ns_set in self.namespace_element_sets: + if attribute_name not in ns_set.get_attribute_name_list(): + continue + ns_set.add(obj) + return + raise ValueError(f"{obj!r} can't be added to this namespace") + def _remove_object(self, object_type: type, attribute_name: str, attribute) -> None: """ Remove an :class:`~.NSO` from this namespace by its attribute @@ -494,6 +507,16 @@ class HasExtension(Namespace, metaclass=abc.ABCMeta): """ return super()._get_object(HasExtension, "name", name) + def add_extension(self, extension: "Extension") -> None: + """ + Add a :class:`~.Extension` to this Namespace + + :param extension: The :class:`~.Extension` to add + :raises KeyError: If a :class:`~.Extension` with the same name is already present in this namespace + :raises ValueError: If the given :class:`~.Extension` already has a parent namespace + """ + return super()._add_object("name", extension) + def remove_extension_by_name(self, name: str) -> None: """ Remove an :class:`~.Extension` from this namespace by its name @@ -1131,6 +1154,16 @@ class Qualifiable(Namespace, metaclass=abc.ABCMeta): """ return super()._get_object(Qualifiable, "type", qualifier_type) + def add_qualifier(self, qualifier: "Qualifier") -> None: + """ + Add a :class:`~.Qualifier` to this Namespace + + :param qualifier: The :class:`~.Qualifier` to add + :raises KeyError: If a qualifier with the same type is already present in this namespace + :raises ValueError: If the passed object already has a parent namespace + """ + return super()._add_object("type", qualifier) + def remove_qualifier_by_type(self, qualifier_type: QualifierType) -> None: """ Remove a :class:`~.Qualifier` from this Namespace by its type @@ -1279,6 +1312,16 @@ class UniqueIdShortNamespace(Namespace, metaclass=abc.ABCMeta): """ return super()._get_object(Referable, "id_short", id_short) + def add_referable(self, referable: Referable) -> None: + """ + Add a :class:`~.Referable` to this Namespace + + :param referable: The :class:`~.Referable` to add + :raises KeyError: If a :class:`~.Referable` with the same name is already present in this namespace + :raises ValueError: If the given :class:`~.Referable` already has a parent namespace + """ + return super()._add_object("id_short", referable) + def remove_referable(self, id_short: str) -> None: """ Remove a Referable from this Namespace by its id_short diff --git a/test/model/test_base.py b/test/model/test_base.py index 87c5eff7e18e023ed31fbc007879941d5d5da0b0..c8f887cf40a7eaa372ec621c1404fcfe55edcda0 100644 --- a/test/model/test_base.py +++ b/test/model/test_base.py @@ -303,17 +303,46 @@ class ReferableTest(unittest.TestCase): # Sources of embedded objects should always be updated self.assertEqual("scheme:NewRelElSource", example_relel.source) - def test_update_commit_qualifier(self): + def test_update_commit_qualifier_extension_semantic_id(self): submodel = model.Submodel(model.Identifier("https://acplt.org/Test_Submodel", model.IdentifierType.IRI)) submodel.update() qualifier = model.Qualifier("test", model.datatypes.String) - submodel.qualifier.add(qualifier) + extension = model.Extension("test") + collection = model.SubmodelElementCollection.create("test") + semantic_id = model.Reference((model.Key(model.KeyElements.GLOBAL_REFERENCE, "test", model.KeyType.IRI),)) + property = model.MultiLanguageProperty("test", semantic_id=semantic_id) + + collection.add_referable(property) + submodel.add_qualifier(qualifier) + submodel.add_extension(extension) + submodel.add_referable(collection) submodel.commit() + self.assertEqual(next(iter(submodel.qualifier)), qualifier) + self.assertEqual(next(iter(submodel.extension)), extension) + self.assertEqual(next(iter(submodel.submodel_element)), collection) + self.assertEqual(next(iter(collection.value)), property) + submodel.get_qualifier_by_type("test") + submodel.get_extension_by_name("test") + collection_ = submodel.get_referable("test") + self.assertIsInstance(collection_, model.SubmodelElementCollectionUnorderedUniqueSemanticId) + assert isinstance(collection_, model.SubmodelElementCollectionUnorderedUniqueSemanticId) + collection_.get_object_by_semantic_id(semantic_id) + submodel.remove_qualifier_by_type("test") + submodel.remove_extension_by_name("test") + submodel.remove_referable("test") + collection_.remove_object_by_semantic_id(semantic_id) + with self.assertRaises(StopIteration): next(iter(submodel.qualifier)) + with self.assertRaises(StopIteration): + next(iter(submodel.extension)) + with self.assertRaises(StopIteration): + next(iter(submodel.submodel_element)) + with self.assertRaises(StopIteration): + next(iter(collection_.value)) submodel.commit()