2
2
from .adapter import AdapterPath
3
3
4
4
from aas_test_engines .result import AasTestResult , Level
5
- from typing import List , Dict , Optional , Tuple , Union
5
+ from typing import List , Dict , Tuple , Union
6
6
from collections import defaultdict
7
7
from dataclasses import is_dataclass , fields
8
8
from enum import Enum
9
+ import datetime
9
10
10
11
INVALID = object ()
11
12
LangString = Dict [str , str ]
12
13
13
14
15
+ def to_camel_case (s : str ) -> str :
16
+ return "" .join (s .title ().split ('_' ))
17
+
18
+
14
19
def _unwrap (cls ) -> Tuple [int , int , type ]:
15
20
try :
16
21
origin = cls .__origin__
@@ -45,21 +50,34 @@ def _parse_string(root_result: AasTestResult, element: SubmodelElement, path: Ad
45
50
if not isinstance (element , Property ):
46
51
root_result .append (AasTestResult (f"Cannot convert to string: must be a Property @ { path } " , level = Level .ERROR ))
47
52
return
48
- if element .value_type != DataTypeDefXsd .string :
49
- root_result .append (AasTestResult (f"Cannot convert to string: valueType must be xs:string @ { path } " , level = Level .ERROR ))
50
- return
51
53
if not element .value :
52
54
root_result .append (AasTestResult (f"Cannot convert to string: no value @ { path } " , level = Level .ERROR ))
53
55
return
56
+ if element .value_type != DataTypeDefXsd .string :
57
+ root_result .append (AasTestResult (f"Cannot convert '{ element .value } ' to string: valueType must be xs:string @ { path } " , level = Level .ERROR ))
58
+ return
54
59
return element .value .raw_value
55
60
56
61
62
+ def _parse_date (root_result : AasTestResult , element : SubmodelElement , path : AdapterPath ) -> str :
63
+ if not isinstance (element , Property ):
64
+ root_result .append (AasTestResult (f"Cannot convert to date: must be a Property @ { path } " , level = Level .ERROR ))
65
+ return
66
+ if not element .value :
67
+ root_result .append (AasTestResult (f"Cannot convert to date: no value @ { path } " , level = Level .ERROR ))
68
+ return
69
+ if element .value_type != DataTypeDefXsd .date :
70
+ root_result .append (AasTestResult (f"Cannot convert '{ element .value } ' to date: valueType must be xs:date @ { path } " , level = Level .ERROR ))
71
+ return
72
+ return datetime .date .fromisoformat (element .value .raw_value )
73
+
74
+
57
75
def _parse_lang_string (root_result : AasTestResult , element : SubmodelElement , path : AdapterPath ) -> LangString :
58
76
if not isinstance (element , MultiLanguageProperty ):
59
- root_result .append (AasTestResult (f"Cannot convert to lang string: not a MultiLanguageProperty @ { path } " ))
77
+ root_result .append (AasTestResult (f"Cannot convert to lang string: not a MultiLanguageProperty @ { path } " , Level . ERROR ))
60
78
return
61
79
if not element .value :
62
- root_result .append (AasTestResult (f"Cannot convert to lang string: no value @ { path } " ))
80
+ root_result .append (AasTestResult (f"Cannot convert to lang string: no value @ { path } " , Level . ERROR ))
63
81
return
64
82
result : LangString = {}
65
83
for i in element .value :
@@ -86,26 +104,28 @@ def _parse_elements(root_result: AasTestResult, cls, elements: List[SubmodelElem
86
104
try :
87
105
semantic_id = field .metadata ['semantic_id' ]
88
106
except KeyError :
89
- raise Exception (f"Field { field .name } is missing metadata 'semantic_id'" )
107
+ raise Exception (f"Internal error: field { field .name } is missing metadata 'semantic_id'" )
90
108
if semantic_id in all_semantic_ids :
91
- raise Exception (f"Duplicate metadata semantic_id { semantic_id } " )
109
+ raise Exception (f"Internal error: duplicate metadata semantic_id { semantic_id } " )
110
+
92
111
all_semantic_ids .add (semantic_id )
93
112
94
113
min_card , max_card , field_type = _unwrap (field .type )
95
114
sub_elements = elements_by_semantic_id [semantic_id ]
115
+ name = to_camel_case (field .name )
96
116
if len (sub_elements ) > max_card :
97
- root_result .append (AasTestResult (f"Field { field . name } : found { len (sub_elements )} elements with semanticId { semantic_id } , but at most { max_card } allowed" , level = Level .ERROR ))
117
+ root_result .append (AasTestResult (f"Field { name } : found { len (sub_elements )} elements with semanticId { semantic_id } , but at most { max_card } allowed" , level = Level .ERROR ))
98
118
field_val = INVALID
99
119
elif len (sub_elements ) < min_card :
100
- root_result .append (AasTestResult (f"Field { field . name } : found { len (sub_elements )} elements with semanticId { semantic_id } , but at least { min_card } required" , level = Level .ERROR ))
120
+ root_result .append (AasTestResult (f"Field { name } : found { len (sub_elements )} elements with semanticId { semantic_id } , but at least { min_card } required" , level = Level .ERROR ))
101
121
field_val = INVALID
102
122
else :
103
123
if len (sub_elements ) == 0 :
104
124
field_val = None
105
125
elif max_card == 1 :
106
- field_val = _parse (field_type , sub_elements [0 ], root_result , path + field . name )
107
- else : # i.e. list
108
- field_val = [_parse (field_type , el , root_result , path + field . name + idx ) for idx , el in enumerate (sub_elements )]
126
+ field_val = _parse (field_type , sub_elements [0 ], root_result , path + name )
127
+ else : # i.e. list
128
+ field_val = [_parse (field_type , el , root_result , path + name + idx ) for idx , el in enumerate (sub_elements )]
109
129
args [field .name ] = field_val
110
130
return cls (** args )
111
131
@@ -131,6 +151,8 @@ def _parse(cls, element: SubmodelElement, root_result, path: AdapterPath):
131
151
return _parse_element_collection (root_result , cls , element , path )
132
152
elif cls is str :
133
153
return _parse_string (root_result , element , path )
154
+ elif cls is datetime .date :
155
+ return _parse_date (root_result , element , path )
134
156
elif isinstance (cls , Enum .__class__ ):
135
157
return _parse_enum (root_result , cls , element , path )
136
158
raise NotImplementedError (
0 commit comments