Skip to content

Commit

Permalink
Refactor Entity and AssetInformation
Browse files Browse the repository at this point in the history
- Refactor hook funcs param names
- Set all private attributes, bypassing setters.
- Place setting of `Entity._global_asset_id` ahead of `Entity._specific_asset_id` to set item_add_hook directly in the ConstrainedList initialization
- Rename `Entity._validate_asset_ids_for_entity_type` to `Entity._validate_asset_ids`
- Place check of `global_asset_id` value into `_validate_asset_ids`
- Run `_validate_asset_ids` at the end of init
  • Loading branch information
zrgt committed Nov 7, 2023
1 parent f8a2bf6 commit 9ed5704
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 45 deletions.
32 changes: 17 additions & 15 deletions basyx/aas/model/aas.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,26 @@ def __init__(self,

super().__init__()
self.asset_kind: base.AssetKind = asset_kind
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = \
base.ConstrainedList(specific_asset_id, item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id)
self._global_asset_id: Optional[base.Identifier]
# AASd-131 is validated via the global_asset_id setter
self.global_asset_id = global_asset_id
self.asset_type: Optional[base.Identifier] = asset_type
self.default_thumbnail: Optional[base.Resource] = default_thumbnail

def _check_constraint_set_spec_asset_id(self, old: List[base.SpecificAssetId], new: List[base.SpecificAssetId],
list_: List[base.SpecificAssetId]) -> None:
# assign private attributes, bypassing setters, as constraints will be checked below
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = base.ConstrainedList(
specific_asset_id,
item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id
)
self._global_asset_id: Optional[base.Identifier] = global_asset_id
self._validate_asset_ids(global_asset_id, bool(specific_asset_id))

def _check_constraint_set_spec_asset_id(self, items_to_replace: List[base.SpecificAssetId],
new_items: List[base.SpecificAssetId],
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.global_asset_id,
# whether the list is nonempty after the set operation
len(old) < len(list_) or len(new) > 0)
len(old_list) - len(items_to_replace) + len(new_items) > 0)

def _check_constraint_del_spec_asset_id(self, _item_to_del: base.SpecificAssetId,
list_: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.global_asset_id, len(list_) > 1)
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.global_asset_id, len(old_list) > 1)

@property
def global_asset_id(self) -> Optional[base.Identifier]:
Expand All @@ -86,8 +88,6 @@ def global_asset_id(self) -> Optional[base.Identifier]:
@global_asset_id.setter
def global_asset_id(self, global_asset_id: Optional[base.Identifier]) -> None:
self._validate_asset_ids(global_asset_id, bool(self.specific_asset_id))
if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)
self._global_asset_id = global_asset_id

@property
Expand All @@ -104,6 +104,8 @@ def _validate_asset_ids(global_asset_id: Optional[base.Identifier], specific_ass
if global_asset_id is None and not specific_asset_id_nonempty:
raise base.AASConstraintViolation(131,
"An AssetInformation has to have a globalAssetId or a specificAssetId")
if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)

def __repr__(self) -> str:
return "AssetInformation(assetKind={}, globalAssetId={}, specificAssetId={}, assetType={}, " \
Expand Down
58 changes: 28 additions & 30 deletions basyx/aas/model/submodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,41 +1106,38 @@ def __init__(self,
super().__init__(id_short, display_name, category, description, parent, semantic_id, qualifier, extension,
supplemental_semantic_id, embedded_data_specifications)
self.statement = base.NamespaceSet(self, [("id_short", True)], statement)
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = \
base.ConstrainedList(specific_asset_id, item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id)
# assign private attributes, bypassing setters, as constraints will be checked below
self._entity_type: base.EntityType = entity_type
# add item_add_hook after items have been added, because checking the constraints requires the global_asset_id
# to be set
self._specific_asset_id._item_add_hook = self._check_constraint_add_spec_asset_id
# use setter for global_asset_id, as it also checks the string constraint,
# which hasn't been checked at this point
# furthermore, the setter also validates AASd-014
self._global_asset_id: Optional[base.Identifier]
self.global_asset_id = global_asset_id

def _check_constraint_add_spec_asset_id(self, _new: base.SpecificAssetId, _list: List[base.SpecificAssetId]) \
-> None:
self._validate_asset_ids_for_entity_type(self.entity_type, self.global_asset_id, True)

def _check_constraint_set_spec_asset_id(self, old: List[base.SpecificAssetId], new: List[base.SpecificAssetId],
list_: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids_for_entity_type(self.entity_type, self.global_asset_id,
# whether the list is nonempty after the set operation
len(old) < len(list_) or len(new) > 0)
self._global_asset_id: Optional[base.Identifier] = global_asset_id
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = base.ConstrainedList(
specific_asset_id,
item_add_hook=self._check_constraint_add_spec_asset_id,
item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id
)
self._validate_asset_ids(entity_type, global_asset_id, bool(specific_asset_id))

def _check_constraint_add_spec_asset_id(self, _new_item: base.SpecificAssetId,
_old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.entity_type, self.global_asset_id, True)

def _check_constraint_set_spec_asset_id(self, items_to_replace: List[base.SpecificAssetId],
new_items: List[base.SpecificAssetId],
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.entity_type, self.global_asset_id,
len(old_list) - len(items_to_replace) + len(new_items) > 0)

def _check_constraint_del_spec_asset_id(self, _item_to_del: base.SpecificAssetId,
list_: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids_for_entity_type(self.entity_type, self.global_asset_id, len(list_) > 1)
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.entity_type, self.global_asset_id, len(old_list) > 1)

@property
def entity_type(self) -> base.EntityType:
return self._entity_type

@entity_type.setter
def entity_type(self, entity_type: base.EntityType) -> None:
self._validate_asset_ids_for_entity_type(entity_type, self.global_asset_id, bool(self.specific_asset_id))
self._validate_asset_ids(entity_type, self.global_asset_id, bool(self.specific_asset_id))
self._entity_type = entity_type

@property
Expand All @@ -1149,9 +1146,7 @@ def global_asset_id(self) -> Optional[base.Identifier]:

@global_asset_id.setter
def global_asset_id(self, global_asset_id: Optional[base.Identifier]) -> None:
self._validate_asset_ids_for_entity_type(self.entity_type, global_asset_id, bool(self.specific_asset_id))
if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)
self._validate_asset_ids(self.entity_type, global_asset_id, bool(self.specific_asset_id))
self._global_asset_id = global_asset_id

@property
Expand All @@ -1164,9 +1159,9 @@ def specific_asset_id(self, specific_asset_id: Iterable[base.SpecificAssetId]) -
self._specific_asset_id[:] = specific_asset_id

@staticmethod
def _validate_asset_ids_for_entity_type(entity_type: base.EntityType,
global_asset_id: Optional[base.Identifier],
specific_asset_id_nonempty: bool) -> None:
def _validate_asset_ids(entity_type: base.EntityType,
global_asset_id: Optional[base.Identifier],
specific_asset_id_nonempty: bool) -> None:
if entity_type == base.EntityType.SELF_MANAGED_ENTITY and global_asset_id is None \
and not specific_asset_id_nonempty:
raise base.AASConstraintViolation(
Expand All @@ -1176,6 +1171,9 @@ def _validate_asset_ids_for_entity_type(entity_type: base.EntityType,
raise base.AASConstraintViolation(
14, "A co-managed entity has to have neither a globalAssetId nor a specificAssetId")

if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)


class EventElement(SubmodelElement, metaclass=abc.ABCMeta):
"""
Expand Down

0 comments on commit 9ed5704

Please sign in to comment.