diff --git a/aas/adapter/json/json_deserialization.py b/aas/adapter/json/json_deserialization.py index 3dcfaf9a076d3143ba69a900b41e10fc2252828b..85dd61997872ded0985dcc0ebc086f81ffc6217f 100644 --- a/aas/adapter/json/json_deserialization.py +++ b/aas/adapter/json/json_deserialization.py @@ -218,6 +218,11 @@ def _construct_security(_dct: Dict[str, object]) -> model.Security: return model.Security() +def _construct_operation_variable(dct: Dict[str, object], failsafe: bool) -> model.OperationVariable: + ret = model.OperationVariable(value=_get_ts(dct, 'value', model.SubmodelElement)) + return ret + + def _construct_lang_string_set(lst: List[Dict[str, object]], failsafe: bool) -> model.LangStringSet: ret = {} for desc in lst: @@ -322,26 +327,22 @@ def construct_basic_event(dct: Dict[str, object], failsafe: bool) -> model.Basic def construct_operation(dct: Dict[str, object], failsafe: bool) -> model.Operation: ret = model.Operation(_get_ts(dct, "idShort", str), kind=_get_kind(dct)) _amend_abstract_attributes(ret, dct, failsafe) - if 'inputVariable' in dct: - for variable in _get_ts(dct, "inputVariable", list): - if _expect_type(variable, model.OperationVariable, "{}.inputVariable".format(ret), failsafe): - ret.input_variable.add(variable) - if 'outputVariable' in dct: - for variable in _get_ts(dct, "outputVariable", list): - if _expect_type(variable, model.OperationVariable, "{}.outputVariable".format(ret), failsafe): - ret.output_variable.add(variable) - if 'inoutputVariable' in dct: - for variable in _get_ts(dct, "inoutputVariable", list): - if _expect_type(variable, model.OperationVariable, "{}.inoutputVariable".format(ret), failsafe): - ret.in_output_variable.add(variable) - return ret - -def construct_operation_variable(dct: Dict[str, object], failsafe: bool) -> model.OperationVariable: - ret = model.OperationVariable(id_short=_get_ts(dct, "idShort", str), - value=_get_ts(dct, 'value', model.SubmodelElement), - kind=_get_kind(dct)) - _amend_abstract_attributes(ret, dct, failsafe) + # Deserialize variables (they are not Referable, thus we don't + for json_name, target in (('inputVariable', ret.input_variable), + ('outputVariable', ret.output_variable), + ('inoutputVariable', ret.in_output_variable)): + if json_name in dct: + for variable_data in _get_ts(dct, json_name, list): + try: + target.append(_construct_operation_variable(variable_data, failsafe)) + except (KeyError, TypeError) as e: + error_message = "Error while trying to convert JSON object into {} of {}: {}".format( + json_name, ret, pprint.pformat(variable_data, depth=2, width=2 ** 14, compact=True)) + if failsafe: + logger.error(error_message, exc_info=e) + else: + raise type(e)(error_message) from e return ret @@ -473,7 +474,6 @@ AAS_CLASS_PARSERS: Dict[str, Callable[[Dict[str, object], bool], object]] = { 'Entity': construct_entity, 'BasicEvent': construct_basic_event, 'Operation': construct_operation, - 'OperationVariable': construct_operation_variable, 'RelationshipElement': construct_relationship_element, 'AnnotatedRelationshipElement': construct_annotated_relationship_element, 'SubmodelElementCollection': construct_submodel_element_collection, diff --git a/aas/examples/example_create_aas.py b/aas/examples/example_create_aas.py index 69151e5ba363ff5d31ccbc016bec26368b44b9b8..d041464da44648ce9af6f86898791c5704d26a3d 100644 --- a/aas/examples/example_create_aas.py +++ b/aas/examples/example_create_aas.py @@ -307,58 +307,19 @@ def create_example_submodel() -> model.Submodel: kind=model.ModelingKind.INSTANCE) submodel_element_operation_variable_input = model.OperationVariable( - id_short='ExampleInputOperationVariable', - value=submodel_element_property, - category='PARAMETER', - description={'en-us': 'Example ExampleInputOperationVariable object', - 'de': 'Beispiel ExampleInputOperationVariable Element'}, - parent=None, - data_specification=None, - semantic_id=model.Reference([model.Key(type_=model.KeyElements.GLOBAL_REFERENCE, - local=False, - value='http://acplt.org/Operations/' - 'ExampleInputOperationVariable', - id_type=model.KeyType.IRDI)]), - qualifier=None, - kind=model.ModelingKind.INSTANCE) + value=submodel_element_property) submodel_element_operation_variable_output = model.OperationVariable( - id_short='ExampleOutputOperationVariable', - value=submodel_element_property, - category='PARAMETER', - description={'en-us': 'Example OutputOperationVariable object', - 'de': 'Beispiel OutputOperationVariable Element'}, - parent=None, - data_specification=None, - semantic_id=model.Reference([model.Key(type_=model.KeyElements.GLOBAL_REFERENCE, - local=False, - value='http://acplt.org/Operations/' - 'ExampleOutputOperationVariable', - id_type=model.KeyType.IRDI)]), - qualifier=None, - kind=model.ModelingKind.INSTANCE) + value=submodel_element_property) submodel_element_operation_variable_in_output = model.OperationVariable( - id_short='ExampleInOutputOperationVariable', - value=submodel_element_property, - category='PARAMETER', - description={'en-us': 'Example InOutputOperationVariable object', - 'de': 'Beispiel InOutputOperationVariable Element'}, - parent=None, - data_specification=None, - semantic_id=model.Reference([model.Key(type_=model.KeyElements.GLOBAL_REFERENCE, - local=False, - value='http://acplt.org/Operations/' - 'ExampleInOutputOperationVariable', - id_type=model.KeyType.IRDI)]), - qualifier=None, - kind=model.ModelingKind.INSTANCE) + value=submodel_element_property) submodel_element_operation = model.Operation( id_short='ExampleOperation', - input_variable={submodel_element_operation_variable_input}, - output_variable={submodel_element_operation_variable_output}, - in_output_variable={submodel_element_operation_variable_in_output}, + input_variable=[submodel_element_operation_variable_input], + output_variable=[submodel_element_operation_variable_output], + in_output_variable=[submodel_element_operation_variable_in_output], category='PARAMETER', description={'en-us': 'Example Operation object', 'de': 'Beispiel Operation Element'}, diff --git a/aas/model/__init__.py b/aas/model/__init__.py index 8a3ddf308797a0eb753f4efdc095f7e87e221d85..6f1b5ca1c45848face357e27b48516c031280468 100644 --- a/aas/model/__init__.py +++ b/aas/model/__init__.py @@ -53,7 +53,6 @@ KEY_ELEMENTS_CLASSES: Dict[type, KeyElements] = { Blob: KeyElements.BLOB, File: KeyElements.FILE, Operation: KeyElements.OPERATION, - OperationVariable: KeyElements.OPERATION_VARIABLE, Capability: KeyElements.CAPABILITY, Property: KeyElements.PROPERTY, MultiLanguageProperty: KeyElements.MULTI_LANGUAGE_PROPERTY, diff --git a/aas/model/base.py b/aas/model/base.py index bc44d62e54e6291feaf14948fc0a838d2505997c..3dfdd2e4687caa09928cd0510e2bd057bd022685 100644 --- a/aas/model/base.py +++ b/aas/model/base.py @@ -114,7 +114,6 @@ class KeyElements(Enum): FILE = 1009 MULTI_LANGUAGE_PROPERTY = 1010 OPERATION = 1011 - OPERATION_VARIABLE = 1119 PROPERTY = 1012 RANGE = 1013 REFERENCE_ELEMENT = 1014 diff --git a/aas/model/submodel.py b/aas/model/submodel.py index 9fb28a4427cb19f4bb00cdd576840d18eb3e993a..c8b2031641c5a6c8049369ee31a4a70ec190a6c9 100644 --- a/aas/model/submodel.py +++ b/aas/model/submodel.py @@ -13,7 +13,7 @@ This module contains everything needed to model Submodels and define Events acco """ import abc -from typing import Optional, Set, Iterable, TYPE_CHECKING +from typing import Optional, Set, Iterable, TYPE_CHECKING, List from . import base if TYPE_CHECKING: @@ -739,7 +739,7 @@ class AnnotatedRelationshipElement(RelationshipElement): self.annotation: Set[base.AASReference[DataElement]] = set() if annotation is None else annotation -class OperationVariable(SubmodelElement): +class OperationVariable: """ An operation variable is a submodel element that is used as input or output variable of an operation. @@ -748,55 +748,31 @@ class OperationVariable(SubmodelElement): """ def __init__(self, - id_short: str, - value: SubmodelElement, - category: Optional[str] = None, - description: Optional[base.LangStringSet] = None, - parent: Optional[base.Namespace] = None, - data_specification: Optional[Set[base.Reference]] = None, - semantic_id: Optional[base.Reference] = None, - qualifier: Optional[Set[base.Constraint]] = None, - kind: base.ModelingKind = base.ModelingKind.INSTANCE): + value: SubmodelElement): """ Initializer of OperationVariable - :param id_short: Identifying string of the element within its name space. (from base.Referable) :param value: Describes the needed argument for an operation via a submodel element of kind=Type. - :param category: The category is a value that gives further meta information w.r.t. to the class of the element. - It affects the expected existence of attributes and the applicability of constraints. - (from base.Referable) - :param description: Description or comments on the element. (from base.Referable) - :param parent: Reference to the next referable parent element of the element. (from base.Referable) - :param data_specification: Unordered list of global references to the data specification template used by the - element. (from base.HasDataSpecification) - :param semantic_id: Identifier of the semantic definition of the element. It is called semantic id of the - element. The semantic id may either reference an external global id or it may reference a - referable model element of kind=Type that defines the semantics of the element. - (from base.HasSemantics) - :param qualifier: Unordered list of Constraints that gives additional qualification of a qualifiable element. - (from base.Qualifiable) TODO: Add instruction what to do after construction """ - - super().__init__(id_short, category, description, parent, data_specification, semantic_id, qualifier, kind) # Constraint AASd-008: The submodel element shall be of kind=Template. self.value: SubmodelElement = value # TODO check the kind of the object in value -class Operation(SubmodelElement, base.Namespace): +class Operation(SubmodelElement): """ An operation is a submodel element with input and output variables. - :ivar input_variable: Unordered list of input parameters of the operation - :ivar output_variable: Unordered list of output parameters of the operation - :ivar in_output_variable: Unordered list of parameters that are input and output of the operation + :ivar input_variable: list of input parameters of the operation + :ivar output_variable: of output parameters of the operation + :ivar in_output_variable: of parameters that are input and output of the operation """ def __init__(self, id_short: str, - input_variable: Iterable[OperationVariable] = (), - output_variable: Iterable[OperationVariable] = (), - in_output_variable: Iterable[OperationVariable] = (), + input_variable: Optional[List[OperationVariable]] = None, + output_variable: Optional[List[OperationVariable]] = None, + in_output_variable: Optional[List[OperationVariable]] = None, category: Optional[str] = None, description: Optional[base.LangStringSet] = None, parent: Optional[base.Namespace] = None, @@ -808,9 +784,9 @@ class Operation(SubmodelElement, base.Namespace): Initializer of Operation :param id_short: Identifying string of the element within its name space. (from base.Referable) - :param input_variable: Unordered list of input parameters of the operation - :param output_variable: Unordered list output parameters of the operation - :param in_output_variable: Unordered list of parameters that is input and output of the operation + :param input_variable: list of input parameters of the operation + :param output_variable: list output parameters of the operation + :param in_output_variable: list of parameters that is input and output of the operation :param category: The category is a value that gives further meta information w.r.t. to the class of the element. It affects the expected existence of attributes and the applicability of constraints. (from base.Referable) @@ -830,9 +806,9 @@ class Operation(SubmodelElement, base.Namespace): """ super().__init__(id_short, category, description, parent, data_specification, semantic_id, qualifier, kind) - self.input_variable: base.NamespaceSet[OperationVariable] = base.NamespaceSet(self, input_variable) - self.output_variable: base.NamespaceSet[OperationVariable] = base.NamespaceSet(self, output_variable) - self.in_output_variable: base.NamespaceSet[OperationVariable] = base.NamespaceSet(self, in_output_variable) + self.input_variable = input_variable if input_variable is not None else [] + self.output_variable = output_variable if output_variable is not None else [] + self.in_output_variable = in_output_variable if in_output_variable is not None else [] class Capability(SubmodelElement):