Skip to content

Commit 509262a

Browse files
committed
Define a new CHECK function attributes_not_null; Expand schema_PoC_optimizer.json with new rules
1 parent a4a063f commit 509262a

2 files changed

Lines changed: 335 additions & 0 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from esdlvalidator.validation.functions import utils
2+
from esdlvalidator.validation.functions.function import FunctionFactory, FunctionCheck, FunctionDefinition, ArgDefinition, FunctionType, CheckResult
3+
4+
5+
@FunctionFactory.register(FunctionType.CHECK, "attributes_not_null")
6+
class AttributesNotSet(FunctionCheck):
7+
8+
def get_function_definition(self):
9+
return FunctionDefinition(
10+
"attributes_not_null",
11+
"Check if required attributes are all set (not null).",
12+
[
13+
ArgDefinition("checks", "A list of dictionaries with structure as {attribute: str, count_as_null: list[Any]} to be checked", True),
14+
ArgDefinition("resultMsgJSON", "Display output in JSON format", False)
15+
]
16+
)
17+
18+
def execute(self):
19+
value = self.value
20+
msg = {"offending_asset": self.value.id}
21+
22+
checks = utils.get_attribute(self.args, "checks")
23+
24+
if not isinstance(checks, list):
25+
raise TypeError(f"Invalid function argument. Argument 'checks' should be a list, got {type(checks)}.")
26+
27+
results = []
28+
for dict in checks:
29+
if 'attribute' not in dict or 'count_as_null' not in dict:
30+
raise ValueError("Missing required keys: 'attribute' and/or 'count_as_null'.")
31+
32+
attr = dict['attribute']
33+
count_as_null = dict['count_as_null']
34+
35+
if not isinstance(attr, str):
36+
raise TypeError("'attribute' must be a string")
37+
if not isinstance(count_as_null, list):
38+
raise TypeError("'count_as_null' must be a list")
39+
40+
if not utils.has_attribute(value, attr):
41+
r = f"Attribute '{attr}' not found."
42+
results.append(r)
43+
else:
44+
# if attribute and value is set, eIsSet() returns True
45+
attrValueIsSet = self.value.eIsSet(attr)
46+
47+
if not attrValueIsSet:
48+
r = f"Attribute value of '{attr}' should be defined."
49+
results.append(r)
50+
# Handle the case when attribute value is set, but should still be considered as undefined.
51+
else:
52+
attrValue = utils.get_attribute(value, attr)
53+
54+
for nullValue in count_as_null:
55+
if (isinstance(nullValue, str) and str(nullValue).lower() == str(attrValue).lower()) \
56+
or (nullValue == attrValue):
57+
# TODO: more explicit message?
58+
r = f"'{attr}' value cannot be null."
59+
results.append(r)
60+
break
61+
62+
if len(results) > 0:
63+
if 'resultMsgJSON' in self.args and self.args['resultMsgJSON']:
64+
msg["message"] = "; ".join(results)
65+
return CheckResult(False, msg)
66+
else:
67+
return CheckResult(False, results)
68+
else:
69+
return CheckResult(True)

testdata/schemas/schema_PoC_optimizer.json

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,272 @@
3535
"resultMsgJSON": true
3636
}
3737
}
38+
},
39+
{
40+
"name": "heatpump_required_attributes_are_set",
41+
"description": "Report errors if the required attributes of HeatPump are not set.",
42+
"type": "error",
43+
"message": "Required Attribute Not Set",
44+
"selects": [{
45+
"function": "get",
46+
"alias": "heatpumps",
47+
"args": {
48+
"type": ["HeatPump"]
49+
}
50+
}
51+
],
52+
"check": {
53+
"function": "attributes_not_null",
54+
"dataset": "heatpumps",
55+
"args": {
56+
"checks": [
57+
{
58+
"attribute": "name",
59+
"count_as_null": [""]
60+
},
61+
{
62+
"attribute": "power",
63+
"count_as_null": [0.0]
64+
},
65+
{
66+
"attribute": "COP",
67+
"count_as_null": [0.0]
68+
}
69+
],
70+
"resultMsgJSON": true
71+
}
72+
}
73+
},
74+
{
75+
"name": "producers_required_attributes_are_set",
76+
"description": "Report errors if the required attributes of producer assets are not set.",
77+
"type": "error",
78+
"message": "Required Attribute Not Set",
79+
"selects": [{
80+
"function": "get",
81+
"alias": "producers",
82+
"args": {
83+
"type": ["GeothermalSource", "ResidualHeatSource"]
84+
}
85+
}
86+
],
87+
"check": {
88+
"function": "attributes_not_null",
89+
"dataset": "producers",
90+
"args": {
91+
"checks": [
92+
{
93+
"attribute": "name",
94+
"count_as_null": [""]
95+
},
96+
{
97+
"attribute": "power",
98+
"count_as_null": [0.0]
99+
}
100+
],
101+
"resultMsgJSON": true
102+
}
103+
}
104+
},
105+
{
106+
"name": "heatingdemand_required_attributes_are_set",
107+
"description": "Report errors if the required attributes of HeatingDemand assets are not set.",
108+
"type": "error",
109+
"message": "Required Attribute Not Set",
110+
"selects": [{
111+
"function": "get",
112+
"alias": "heatingdemands",
113+
"args": {
114+
"type": ["HeatingDemand"]
115+
}
116+
}
117+
],
118+
"check": {
119+
"function": "attributes_not_null",
120+
"dataset": "heatingdemands",
121+
"args": {
122+
"checks": [
123+
{
124+
"attribute": "name",
125+
"count_as_null": [""]
126+
},
127+
{
128+
"attribute": "power",
129+
"count_as_null": [0.0]
130+
}
131+
],
132+
"resultMsgJSON": true
133+
}
134+
}
135+
},
136+
{
137+
"name": "heatstorage_required_attributes_are_set",
138+
"description": "Report errors if the required attributes of HeatStorage assets are not set. NOTE: excluding ATES here (also a kind of HeatStorage), which is checked separately below.",
139+
"type": "error",
140+
"message": "Required Attribute Not Set",
141+
"selects": [{
142+
"function": "get",
143+
"alias": "heatstorages",
144+
"args": {
145+
"type": ["HeatStorage"],
146+
"exclude_type": ["ATES"]
147+
}
148+
}
149+
],
150+
"check": {
151+
"function": "attributes_not_null",
152+
"dataset": "heatstorages",
153+
"args": {
154+
"checks": [
155+
{
156+
"attribute": "name",
157+
"count_as_null": [""]
158+
},
159+
{
160+
"attribute": "maxChargeRate",
161+
"count_as_null": [0.0]
162+
},
163+
{
164+
"attribute": "maxDischargeRate",
165+
"count_as_null": [0.0]
166+
},
167+
{
168+
"attribute": "volume",
169+
"count_as_null": [0.0]
170+
}
171+
],
172+
"resultMsgJSON": true
173+
}
174+
}
175+
},
176+
{
177+
"name": "ATES_required_attributes_are_set",
178+
"description": "Report errors if the required attributes of ATES assets are not set.",
179+
"type": "error",
180+
"message": "Required Attribute Not Set",
181+
"selects": [{
182+
"function": "get",
183+
"alias": "ates",
184+
"args": {
185+
"type": ["ATES"]
186+
}
187+
}
188+
],
189+
"check": {
190+
"function": "attributes_not_null",
191+
"dataset": "ates",
192+
"args": {
193+
"checks": [
194+
{
195+
"attribute": "name",
196+
"count_as_null": [""]
197+
},
198+
{
199+
"attribute": "aquiferTopDepth",
200+
"count_as_null": [0.0]
201+
},
202+
{
203+
"attribute": "aquiferThickness",
204+
"count_as_null": [0.0]
205+
},
206+
{
207+
"attribute": "aquiferMidTemperature",
208+
"count_as_null": [0.0]
209+
},
210+
{
211+
"attribute": "aquiferPorosity",
212+
"count_as_null": [0.0]
213+
},
214+
{
215+
"attribute": "aquiferPermeability",
216+
"count_as_null": [0.0]
217+
},
218+
{
219+
"attribute": "aquiferAnisotropy",
220+
"count_as_null": [0.0]
221+
},
222+
{
223+
"attribute": "salinity",
224+
"count_as_null": [0.0]
225+
},
226+
{
227+
"attribute": "wellCasingSize",
228+
"count_as_null": [0.0]
229+
},
230+
{
231+
"attribute": "wellDistance",
232+
"count_as_null": [0.0]
233+
}
234+
],
235+
"resultMsgJSON": true
236+
}
237+
}
238+
},
239+
{
240+
"name": "pipe_required_attributes_are_set",
241+
"description": "Report errors if the required attributes of Pipe assets are not set.",
242+
"type": "error",
243+
"message": "Required Attribute Not Set",
244+
"selects": [{
245+
"function": "get",
246+
"alias": "pipes",
247+
"args": {
248+
"type": ["Pipe"]
249+
}
250+
}
251+
],
252+
"check": {
253+
"function": "attributes_not_null",
254+
"dataset": "pipes",
255+
"args": {
256+
"checks": [
257+
{
258+
"attribute": "name",
259+
"count_as_null": [""]
260+
},
261+
{
262+
"attribute": "diameter",
263+
"count_as_null": ["VALUE_SPECIFIED"]
264+
},
265+
{
266+
"attribute": "length",
267+
"count_as_null": [0.0]
268+
}
269+
],
270+
"resultMsgJSON": true
271+
}
272+
}
273+
},
274+
{
275+
"name": "heatexchange_required_attributes_are_set",
276+
"description": "Report errors if the required attributes of HeatExchange assets are not set.",
277+
"type": "error",
278+
"message": "Required Attribute Not Set",
279+
"selects": [{
280+
"function": "get",
281+
"alias": "heatexchanges",
282+
"args": {
283+
"type": ["HeatExchange"]
284+
}
285+
}
286+
],
287+
"check": {
288+
"function": "attributes_not_null",
289+
"dataset": "heatexchanges",
290+
"args": {
291+
"checks": [
292+
{
293+
"attribute": "name",
294+
"count_as_null": [""]
295+
},
296+
{
297+
"attribute": "capacity",
298+
"count_as_null": [0.0]
299+
}
300+
],
301+
"resultMsgJSON": true
302+
}
303+
}
38304
}
39305
]
40306
}

0 commit comments

Comments
 (0)