|
| 1 | +# Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH |
| 2 | +# |
| 3 | +# See the AUTHORS file(s) distributed with this work for additional |
| 4 | +# information regarding authorship. |
| 5 | +# |
| 6 | +# This Source Code Form is subject to the terms of the Mozilla Public |
| 7 | +# License, v. 2.0. If a copy of the MPL was not distributed with this |
| 8 | +# file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| 9 | +# |
| 10 | +# SPDX-License-Identifier: MPL-2.0 |
| 11 | + |
| 12 | +from typing import Any, Dict, Optional |
| 13 | + |
| 14 | +import rdflib # type: ignore |
| 15 | + |
| 16 | +from rdflib.term import Node |
| 17 | + |
| 18 | +from esmf_aspect_meta_model_python.base.characteristics.state import State |
| 19 | +from esmf_aspect_meta_model_python.impl.characteristics.default_state import DefaultState |
| 20 | +from esmf_aspect_meta_model_python.loader.instantiator.constants import DATA_TYPE_ERROR_MSG |
| 21 | +from esmf_aspect_meta_model_python.loader.instantiator.enumeration_instantiator import EnumerationInstantiator |
| 22 | +from esmf_aspect_meta_model_python.loader.rdf_helper import RdfHelper |
| 23 | +from esmf_aspect_meta_model_python.vocabulary.SAMM import SAMM |
| 24 | +from esmf_aspect_meta_model_python.vocabulary.SAMMC import SAMMC |
| 25 | + |
| 26 | + |
| 27 | +class StateInstantiator(EnumerationInstantiator): |
| 28 | + def _create_instance(self, element_node: Node) -> State: |
| 29 | + data_type = self._get_data_type(element_node) |
| 30 | + if data_type is None: |
| 31 | + raise TypeError(DATA_TYPE_ERROR_MSG) |
| 32 | + |
| 33 | + meta_model_base_attributes = self._get_base_attributes(element_node) |
| 34 | + value_collection_node = self._aspect_graph.value( |
| 35 | + subject=element_node, |
| 36 | + predicate=self._sammc.get_urn(SAMMC.values), |
| 37 | + ) |
| 38 | + value_nodes = RdfHelper.get_rdf_list_values(value_collection_node, self._aspect_graph) |
| 39 | + values = [self.__to_state_node_value(value_node) for value_node in value_nodes] |
| 40 | + |
| 41 | + defaultValue = self._aspect_graph.value( |
| 42 | + subject=element_node, |
| 43 | + predicate=self._sammc.get_urn(SAMMC.default_value), |
| 44 | + ) |
| 45 | + default = self.__to_state_node_value(defaultValue) |
| 46 | + |
| 47 | + return DefaultState(meta_model_base_attributes, data_type, values, default) |
| 48 | + |
| 49 | + def __to_state_node_value(self, value_node: Optional[Node]) -> Dict: |
| 50 | + """ |
| 51 | + This method instantiates one possible value of a state. |
| 52 | + :param value_node: Node of the Graph that represents one state value. |
| 53 | + The Argument can either be a Literal or a URIRef. |
| 54 | + - If value_node is a Literal it will represent e.g. a string or an integer value |
| 55 | + - If value_node is a URIRef it will represent a value of a ComplexType |
| 56 | + :return: the one generated value of the state |
| 57 | + """ |
| 58 | + if isinstance(value_node, rdflib.Literal): |
| 59 | + # value represents a simple data type |
| 60 | + return value_node.toPython() |
| 61 | + |
| 62 | + elif isinstance(value_node, rdflib.URIRef): |
| 63 | + # value represents a complex data type |
| 64 | + value = {} |
| 65 | + value_node_properties = self._aspect_graph.predicate_objects(value_node) |
| 66 | + for property_urn, property_value in value_node_properties: |
| 67 | + if property_urn != rdflib.RDF.type and isinstance(property_urn, str): |
| 68 | + property_name = property_urn.split("#")[1] |
| 69 | + actual_value: Optional[Any] |
| 70 | + if self.__is_collection_value(property_urn): |
| 71 | + actual_value = self.__instantiate_enum_collection(property_value) |
| 72 | + else: |
| 73 | + actual_value = self.__to_state_node_value(property_value) |
| 74 | + value[property_name] = actual_value |
| 75 | + |
| 76 | + value_node_name = value_node.split("#")[1] |
| 77 | + value_key = self._samm.get_urn(SAMM.name).toPython() |
| 78 | + value[value_key] = value_node_name # type: ignore |
| 79 | + return value |
| 80 | + |
| 81 | + else: |
| 82 | + # illegal node type for state value (e.g., Blank Node) |
| 83 | + raise TypeError( |
| 84 | + f"Every value of an state must either be a Literal (string, int, etc.) or " |
| 85 | + f"a URI reference to a ComplexType. Values of type {type(value_node).__name__} are not allowed" |
| 86 | + ) |
0 commit comments