Skip to content

Commit

Permalink
adapter: adjust for the new ConstrainedLangStringSets
Browse files Browse the repository at this point in the history
This commit changes the XML/JSON (de-)serialization adapter and
corresponding schemata such that they are compatible with the new
`ConstrainedLangStringSet` types.
  • Loading branch information
jkhsjdhjs committed Aug 24, 2023
1 parent 4e1476c commit b9639bc
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 72 deletions.
110 changes: 91 additions & 19 deletions basyx/aas/adapter/json/aasJSONSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@
"SubmodelElementList"
]
},
"AbstractLangString": {
"type": "object",
"properties": {
"language": {
"type": "string",
"pattern": "^(([a-zA-Z]{2,3}(-[a-zA-Z]{3}(-[a-zA-Z]{3}){2})?|[a-zA-Z]{4}|[a-zA-Z]{5,8})(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?(-(([a-zA-Z0-9]){5,8}|[0-9]([a-zA-Z0-9]){3}))*(-[0-9A-WY-Za-wy-z](-([a-zA-Z0-9]){2,8})+)*(-[xX](-([a-zA-Z0-9]){1,8})+)?|[xX](-([a-zA-Z0-9]){1,8})+|((en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)))$"
},
"text": {
"type": "string",
"minLength": 1,
"pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$"
}
},
"required": [
"language",
"text"
]
},
"AdministrativeInformation": {
"allOf": [
{
Expand Down Expand Up @@ -263,14 +281,14 @@
"preferredName": {
"type": "array",
"items": {
"$ref": "#/definitions/LangString"
"$ref": "#/definitions/LangStringPreferredNameTypeIec61360"
},
"minItems": 1
},
"shortName": {
"type": "array",
"items": {
"$ref": "#/definitions/LangString"
"$ref": "#/definitions/LangStringShortNameTypeIec61360"
},
"minItems": 1
},
Expand All @@ -295,7 +313,7 @@
"definition": {
"type": "array",
"items": {
"$ref": "#/definitions/LangString"
"$ref": "#/definitions/LangStringDefinitionTypeIec61360"
},
"minItems": 1
},
Expand Down Expand Up @@ -337,7 +355,7 @@
"definition": {
"type": "array",
"items": {
"$ref": "#/definitions/LangString"
"$ref": "#/definitions/LangStringDefinitionTypeIec61360"
},
"minItems": 1
},
Expand Down Expand Up @@ -748,20 +766,74 @@
"SubmodelElementList"
]
},
"LangString": {
"type": "object",
"properties": {
"language": {
"type": "string",
"pattern": "^(([a-zA-Z]{2,3}(-[a-zA-Z]{3}(-[a-zA-Z]{3}){2})?|[a-zA-Z]{4}|[a-zA-Z]{5,8})(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?(-(([a-zA-Z0-9]){5,8}|[0-9]([a-zA-Z0-9]){3}))*(-[0-9A-WY-Za-wy-z](-([a-zA-Z0-9]){2,8})+)*(-[xX](-([a-zA-Z0-9]){1,8})+)?|[xX](-([a-zA-Z0-9]){1,8})+|((en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)))$"
"LangStringDefinitionTypeIec61360": {
"allOf": [
{
"$ref": "#/definitions/AbstractLangString"
},
"text": {
"type": "string"
{
"properties": {
"text": {
"maxLength": 1023
}
}
}
]
},
"LangStringNameType": {
"allOf": [
{
"$ref": "#/definitions/AbstractLangString"
},
{
"properties": {
"text": {
"maxLength": 128
}
}
}
]
},
"LangStringPreferredNameTypeIec61360": {
"allOf": [
{
"$ref": "#/definitions/AbstractLangString"
},
{
"properties": {
"text": {
"maxLength": 255
}
}
}
]
},
"LangStringShortNameTypeIec61360": {
"allOf": [
{
"$ref": "#/definitions/AbstractLangString"
},
{
"properties": {
"text": {
"maxLength": 18
}
}
}
]
},
"LangStringTextType": {
"allOf": [
{
"$ref": "#/definitions/AbstractLangString"
},
{
"properties": {
"text": {
"maxLength": 1023
}
}
}
},
"required": [
"language",
"text"
]
},
"LevelType": {
Expand Down Expand Up @@ -828,7 +900,7 @@
"value": {
"type": "array",
"items": {
"$ref": "#/definitions/LangString"
"$ref": "#/definitions/LangStringTextType"
},
"minItems": 1
},
Expand Down Expand Up @@ -1004,14 +1076,14 @@
"displayName": {
"type": "array",
"items": {
"$ref": "#/definitions/LangString"
"$ref": "#/definitions/LangStringNameType"
},
"minItems": 1
},
"description": {
"type": "array",
"items": {
"$ref": "#/definitions/LangString"
"$ref": "#/definitions/LangStringTextType"
},
"minItems": 1
},
Expand Down
28 changes: 17 additions & 11 deletions basyx/aas/adapter/json/json_deserialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
# #############################################################################

T = TypeVar('T')
LSS = TypeVar('LSS', bound=model.LangStringSet)


def _get_ts(dct: Dict[str, object], key: str, type_: Type[T]) -> T:
Expand Down Expand Up @@ -235,9 +236,11 @@ def _amend_abstract_attributes(cls, obj: object, dct: Dict[str, object]) -> None
if 'category' in dct:
obj.category = _get_ts(dct, 'category', str)
if 'displayName' in dct:
obj.display_name = cls._construct_lang_string_set(_get_ts(dct, 'displayName', list))
obj.display_name = cls._construct_lang_string_set(_get_ts(dct, 'displayName', list),
model.MultiLanguageNameType)
if 'description' in dct:
obj.description = cls._construct_lang_string_set(_get_ts(dct, 'description', list))
obj.description = cls._construct_lang_string_set(_get_ts(dct, 'description', list),
model.MultiLanguageTextType)
if isinstance(obj, model.Identifiable):
if 'idShort' in dct:
obj.id_short = _get_ts(dct, 'idShort', str)
Expand Down Expand Up @@ -371,19 +374,19 @@ def _construct_operation_variable(
return ret

@classmethod
def _construct_lang_string_set(cls, lst: List[Dict[str, object]]) -> Optional[model.LangStringSet]:
def _construct_lang_string_set(cls, lst: List[Dict[str, object]], object_class: Type[LSS]) -> LSS:
ret = {}
for desc in lst:
try:
ret[_get_ts(desc, 'language', str)] = _get_ts(desc, 'text', str)
except (KeyError, TypeError) as e:
error_message = "Error while trying to convert JSON object into LangString: {} >>> {}".format(
e, pprint.pformat(desc, depth=2, width=2 ** 14, compact=True))
error_message = "Error while trying to convert JSON object into {}: {} >>> {}".format(
object_class.__name__, e, pprint.pformat(desc, depth=2, width=2 ** 14, compact=True))
if cls.failsafe:
logger.error(error_message, exc_info=e)
else:
raise type(e)(error_message) from e
return model.LangStringSet(ret)
return object_class(ret)

@classmethod
def _construct_value_list(cls, dct: Dict[str, object], value_format: model.DataTypeDefXsd) -> model.ValueList:
Expand Down Expand Up @@ -464,7 +467,7 @@ def _construct_data_specification_physical_unit(cls, dct: Dict[str, object],
ret = object_class(
unit_name=_get_ts(dct, 'unitName', str),
unit_symbol=_get_ts(dct, 'unitSymbol', str),
definition=cls._construct_lang_string_set(_get_ts(dct, 'definition', list))
definition=cls._construct_lang_string_set(_get_ts(dct, 'definition', list), model.DefinitionTypeIEC61360)
)
if 'siNotation' in dct:
ret.si_notation = _get_ts(dct, 'siNotation', str)
Expand Down Expand Up @@ -492,13 +495,16 @@ def _construct_data_specification_physical_unit(cls, dct: Dict[str, object],
def _construct_data_specification_iec61360(cls, dct: Dict[str, object],
object_class=model.base.DataSpecificationIEC61360)\
-> model.base.DataSpecificationIEC61360:
ret = object_class(preferred_name=cls._construct_lang_string_set(_get_ts(dct, 'preferredName', list)))
ret = object_class(preferred_name=cls._construct_lang_string_set(_get_ts(dct, 'preferredName', list),
model.PreferredNameTypeIEC61360))
if 'dataType' in dct:
ret.data_type = IEC61360_DATA_TYPES_INVERSE[_get_ts(dct, 'dataType', str)]
if 'definition' in dct:
ret.definition = cls._construct_lang_string_set(_get_ts(dct, 'definition', list))
ret.definition = cls._construct_lang_string_set(_get_ts(dct, 'definition', list),
model.DefinitionTypeIEC61360)
if 'shortName' in dct:
ret.short_name = cls._construct_lang_string_set(_get_ts(dct, 'shortName', list))
ret.short_name = cls._construct_lang_string_set(_get_ts(dct, 'shortName', list),
model.ShortNameTypeIEC61360)
if 'unit' in dct:
ret.unit = _get_ts(dct, 'unit', str)
if 'unitId' in dct:
Expand Down Expand Up @@ -727,7 +733,7 @@ def _construct_multi_language_property(
ret = object_class(id_short=_get_ts(dct, "idShort", str))
cls._amend_abstract_attributes(ret, dct)
if 'value' in dct and dct['value'] is not None:
ret.value = cls._construct_lang_string_set(_get_ts(dct, 'value', list))
ret.value = cls._construct_lang_string_set(_get_ts(dct, 'value', list), model.MultiLanguageTextType)
if 'valueId' in dct:
ret.value_id = cls._construct_reference(_get_ts(dct, 'valueId', dict))
return ret
Expand Down
Loading

0 comments on commit b9639bc

Please sign in to comment.