Skip to content

Commit b158090

Browse files
authored
Merge pull request #471 from OP-TED/feature/TED-1312
2 parents 78a290f + 5994de7 commit b158090

12 files changed

Lines changed: 285 additions & 103 deletions

File tree

ted_sws/core/model/manifestation.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class SPARQLQueryRefinedResultType(Enum):
3535
INVALID = "invalid"
3636
ERROR = "error"
3737
WARNING = "warning"
38+
UNKNOWN = "unknown"
3839

3940

4041
class Manifestation(PropertyBaseModel):
@@ -224,6 +225,7 @@ class SPARQLQueryResult(PropertyBaseModel):
224225
fields_covered: Optional[bool] = True
225226
missing_fields: Optional[List[str]] = []
226227
error: Optional[str]
228+
message: Optional[str]
227229
identifier: Optional[str]
228230

229231
class Config:

ted_sws/core/model/validation_report.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class SPARQLValidationSummaryCountReport(PropertyBaseModel):
3030
warning: Optional[QueryValidationSummaryCountReportStatus] = QueryValidationSummaryCountReportStatus()
3131
invalid: Optional[QueryValidationSummaryCountReportStatus] = QueryValidationSummaryCountReportStatus()
3232
error: Optional[QueryValidationSummaryCountReportStatus] = QueryValidationSummaryCountReportStatus()
33+
unknown: Optional[QueryValidationSummaryCountReportStatus] = QueryValidationSummaryCountReportStatus()
3334

3435

3536
class SPARQLSummaryQuery(PropertyBaseModel):

ted_sws/mapping_suite_processor/services/conceptual_mapping_generate_sparql_queries.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
SPARQL_PREFIX_LINE = 'PREFIX {prefix}: <{value}>'
2727
SPARQL_LOGGER_NAME = "SPARQL"
2828

29+
SPARQL_XPATH_SEPARATOR = " ;; "
30+
2931

3032
def get_sparql_prefixes(sparql_q: str) -> list:
3133
finds: list = re.findall(SPARQL_PREFIX_PATTERN, sparql_q)
3234
return sorted(set(finds))
3335

3436

35-
def concat_field_xpath(base_xpath: str, field_xpath: str, separator: str = ", ") -> str:
37+
def concat_field_xpath(base_xpath: str, field_xpath: str, separator: str = SPARQL_XPATH_SEPARATOR) -> str:
3638
base_xpath = base_xpath if not pd.isna(base_xpath) else ''
3739
field_xpath = field_xpath if not pd.isna(field_xpath) else ''
3840
return separator.join(
@@ -137,7 +139,7 @@ def sparql_validation_generator(data: pd.DataFrame, base_xpath: str, controlled_
137139
f"{e_form_bt_name}” in eForms. The corresponding XML element is " \
138140
f"{concat_field_xpath(base_xpath, field_xpath)}. " \
139141
f"The expected ontology instances are epo: {class_path} .\n" \
140-
f"#xpath: {concat_field_xpath(base_xpath, field_xpath, separator=',')}" \
142+
f"#xpath: {concat_field_xpath(base_xpath, field_xpath, separator=SPARQL_XPATH_SEPARATOR)}" \
141143
"\n" + "\n" + "\n".join(prefixes) + "\n\n" \
142144
f"ASK WHERE {{ " \
143145
f"{subject_type_display}" \

ted_sws/notice_validator/resources/templates/sparql_query_results_report.jinja2

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
</tr>
125125
</thead>
126126
<tbody>
127-
{% for _value in ['valid', 'unverifiable', 'warning', 'invalid', 'error'] %}
127+
{% for _value in ['valid', 'unverifiable', 'warning', 'invalid', 'error', 'unknown'] %}
128128
<tr>
129129
{% set _results = validation_results | selectattr("result", "equalto", _value) | list | count %}
130130
<td class="strong {{ _value }}">{{ _value }}</td>
@@ -187,8 +187,16 @@
187187
</ol>
188188
</li>
189189
{% endif %}
190+
{% if result.message and (result.message|length > 0) %}
191+
<li>
192+
<hr>
193+
<h4 class="info strong">MESSAGE:</h4>
194+
{{ result.message }}
195+
</li>
196+
{% endif %}
190197
{% if result.error and (result.error|length > 0) %}
191198
<li>
199+
<hr>
192200
<h4 class="danger strong">ERROR:</h4>
193201
{{ result.error }}
194202
</li>

ted_sws/notice_validator/resources/templates/sparql_summary_report.jinja2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% set result_values = ['valid', 'unverifiable', 'warning', 'invalid', 'error'] %}
1+
{% set result_values = ['valid', 'unverifiable', 'warning', 'invalid', 'error', 'unknown'] %}
22

33
<!DOCTYPE html>
44
<html lang="en">

ted_sws/notice_validator/services/shacl_test_suite_runner.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def validate_notice_with_shacl_suite(notice: Notice, mapping_suite_package: Mapp
185185
:return:
186186
"""
187187

188-
def shacl_validation(notice_item: Notice, rdf_manifestation: RDFManifestation, with_html: bool = False) \
188+
def shacl_validation(notice_item: Notice, rdf_manifestation: RDFManifestation) \
189189
-> List[SHACLTestSuiteValidationReport]:
190190
reports = []
191191
shacl_test_suites = mapping_suite_package.shacl_test_suites
@@ -199,12 +199,10 @@ def shacl_validation(notice_item: Notice, rdf_manifestation: RDFManifestation, w
199199
return sorted(reports, key=lambda x: x.test_suite_identifier)
200200

201201
if execute_full_validation:
202-
for report in shacl_validation(notice_item=notice, rdf_manifestation=notice.rdf_manifestation,
203-
with_html=with_html):
202+
for report in shacl_validation(notice_item=notice, rdf_manifestation=notice.rdf_manifestation):
204203
notice.set_rdf_validation(rdf_validation=report)
205204

206-
for report in shacl_validation(notice_item=notice, rdf_manifestation=notice.distilled_rdf_manifestation,
207-
with_html=with_html):
205+
for report in shacl_validation(notice_item=notice, rdf_manifestation=notice.distilled_rdf_manifestation):
208206
notice.set_distilled_rdf_validation(rdf_validation=report)
209207

210208
return notice

ted_sws/notice_validator/services/sparql_test_suite_runner.py

Lines changed: 127 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
ReportNotice
1313
from ted_sws.core.model.validation_report_data import ReportPackageNoticeData
1414
from ted_sws.data_manager.adapters.repository_abc import NoticeRepositoryABC, MappingSuiteRepositoryABC
15+
from ted_sws.mapping_suite_processor.services.conceptual_mapping_generate_sparql_queries import SPARQL_XPATH_SEPARATOR
1516
from ted_sws.notice_transformer.adapters.notice_transformer import NoticeTransformer
1617
from ted_sws.notice_validator.adapters.sparql_runner import SPARQLRunner
1718
from ted_sws.notice_validator.resources.templates import TEMPLATE_METADATA_KEY
@@ -58,11 +59,25 @@ def _sparql_query_from_file_resource(cls, file_resource: FileResource) -> SPARQL
5859
if QUERY_METADATA_TITLE in metadata else DEFAULT_QUERY_TITLE
5960
description = metadata[QUERY_METADATA_DESCRIPTION] \
6061
if QUERY_METADATA_DESCRIPTION in metadata else DEFAULT_QUERY_DESCRIPTION
61-
xpath = metadata[QUERY_METADATA_XPATH].split(",") if QUERY_METADATA_XPATH in metadata and metadata[
62-
QUERY_METADATA_XPATH] else DEFAULT_QUERY_XPATH
62+
xpath = metadata[QUERY_METADATA_XPATH].split(
63+
SPARQL_XPATH_SEPARATOR
64+
) if QUERY_METADATA_XPATH in metadata and metadata[QUERY_METADATA_XPATH] else DEFAULT_QUERY_XPATH
6365
query = cls._sanitize_query(file_resource.file_content)
6466
return SPARQLQuery(title=title, description=description, xpath=xpath, query=query)
6567

68+
@classmethod
69+
def _refined_result(cls, ask_answer, sparql_query_result,
70+
result: SPARQLQueryRefinedResultType) -> SPARQLQueryRefinedResultType:
71+
if ask_answer and sparql_query_result.fields_covered:
72+
result = SPARQLQueryRefinedResultType.VALID.value
73+
elif not ask_answer and not sparql_query_result.fields_covered:
74+
result = SPARQLQueryRefinedResultType.UNVERIFIABLE.value
75+
elif ask_answer and not sparql_query_result.fields_covered:
76+
result = SPARQLQueryRefinedResultType.WARNING.value
77+
elif not ask_answer and sparql_query_result.fields_covered:
78+
result = SPARQLQueryRefinedResultType.INVALID.value
79+
return result
80+
6681
def _process_sparql_ask_result(self, query_result, sparql_query: SPARQLQuery,
6782
sparql_query_result: SPARQLQueryResult):
6883
ask_answer = query_result.askAnswer
@@ -87,14 +102,7 @@ def _process_sparql_ask_result(self, query_result, sparql_query: SPARQLQuery,
87102
sparql_query_result.missing_fields = list(sparql_query_xpath - xpaths_in_notice)
88103

89104
# Refined result
90-
if ask_answer and sparql_query_result.fields_covered:
91-
result = SPARQLQueryRefinedResultType.VALID.value
92-
elif not ask_answer and not sparql_query_result.fields_covered:
93-
result = SPARQLQueryRefinedResultType.UNVERIFIABLE.value
94-
elif ask_answer and not sparql_query_result.fields_covered:
95-
result = SPARQLQueryRefinedResultType.WARNING.value
96-
elif not ask_answer and sparql_query_result.fields_covered:
97-
result = SPARQLQueryRefinedResultType.INVALID.value
105+
result = self._refined_result(ask_answer, sparql_query_result, result)
98106

99107
sparql_query_result.result = result
100108

@@ -153,11 +161,75 @@ def generate_report(self) -> SPARQLTestSuiteValidationReport:
153161
return self.sparql_test_suite_execution
154162

155163

156-
def generate_sparql_validation_summary_report(report_notices: List[ReportNotice], mapping_suite_package: MappingSuite,
157-
execute_full_validation: bool = True,
158-
with_html: bool = False,
159-
report: SPARQLValidationSummaryReport = None,
160-
metadata: dict = None) -> SPARQLValidationSummaryReport:
164+
def process_sparql_validation_summary_report_data_with_notice(
165+
notice: Notice,
166+
mapping_suite_package: MappingSuite,
167+
report_notice_path: Path,
168+
report: SPARQLValidationSummaryReport
169+
):
170+
for sparql_validation in notice.rdf_manifestation.sparql_validations:
171+
test_suite_id = sparql_validation.test_suite_identifier
172+
report.test_suite_ids.append(test_suite_id)
173+
mapping_suite_versioned_id = sparql_validation.mapping_suite_identifier
174+
report.mapping_suite_ids.append(mapping_suite_versioned_id)
175+
validation: SPARQLQueryResult
176+
for validation in sparql_validation.validation_results:
177+
validation_query_result: SPARQLValidationSummaryQueryResult
178+
found_validation_query_result = list(filter(
179+
lambda record:
180+
(record.query.query == validation.query.query)
181+
and (record.query.title == validation.query.title)
182+
and (record.test_suite_identifier == test_suite_id),
183+
report.validation_results
184+
))
185+
if found_validation_query_result:
186+
validation_query_result = found_validation_query_result[0]
187+
else:
188+
validation_query_result = SPARQLValidationSummaryQueryResult(
189+
test_suite_identifier=test_suite_id,
190+
**validation.dict()
191+
)
192+
notice_data: ReportPackageNoticeData = ReportPackageNoticeData(
193+
notice_id=notice.ted_id,
194+
path=str(report_notice_path),
195+
mapping_suite_versioned_id=mapping_suite_versioned_id,
196+
mapping_suite_identifier=mapping_suite_package.identifier
197+
)
198+
if validation.result == SPARQLQueryRefinedResultType.VALID.value:
199+
validation_query_result.aggregate.valid.count += 1
200+
validation_query_result.aggregate.valid.notices.append(notice_data)
201+
elif validation.result == SPARQLQueryRefinedResultType.UNVERIFIABLE.value:
202+
validation_query_result.aggregate.unverifiable.count += 1
203+
validation_query_result.aggregate.unverifiable.notices.append(notice_data)
204+
elif validation.result == SPARQLQueryRefinedResultType.INVALID.value:
205+
validation_query_result.aggregate.invalid.count += 1
206+
validation_query_result.aggregate.invalid.notices.append(notice_data)
207+
elif validation.result == SPARQLQueryRefinedResultType.WARNING.value:
208+
validation_query_result.aggregate.warning.count += 1
209+
validation_query_result.aggregate.warning.notices.append(notice_data)
210+
elif validation.result == SPARQLQueryRefinedResultType.ERROR.value:
211+
validation_query_result.aggregate.error.count += 1
212+
validation_query_result.aggregate.error.notices.append(notice_data)
213+
elif validation.result == SPARQLQueryRefinedResultType.UNKNOWN.value:
214+
validation_query_result.aggregate.unknown.count += 1
215+
validation_query_result.aggregate.unknown.notices.append(notice_data)
216+
if not found_validation_query_result:
217+
report.validation_results.append(validation_query_result)
218+
219+
220+
def add_sparql_validation_summary_html_report(
221+
report: SPARQLValidationSummaryReport,
222+
metadata: dict = None
223+
):
224+
template_data: dict = report.dict()
225+
template_data[TEMPLATE_METADATA_KEY] = metadata
226+
html_report = TEMPLATES.get_template(SPARQL_SUMMARY_HTML_REPORT_TEMPLATE).render(template_data)
227+
report.object_data = html_report
228+
229+
230+
def init_sparql_validation_summary_report(
231+
report: SPARQLValidationSummaryReport,
232+
report_notices: List[ReportNotice]) -> SPARQLValidationSummaryReport:
161233
if report is None:
162234
report: SPARQLValidationSummaryReport = SPARQLValidationSummaryReport(
163235
object_data="SPARQLValidationSummaryReport",
@@ -168,6 +240,32 @@ def generate_sparql_validation_summary_report(report_notices: List[ReportNotice]
168240
report.notices = sorted(NoticeTransformer.transform_validation_report_notices(report_notices, group_depth=1) + (
169241
report.notices or []), key=lambda report_data: report_data.notice_id)
170242

243+
return report
244+
245+
246+
def finalize_sparql_validation_summary_report(report: SPARQLValidationSummaryReport, metadata: dict = None,
247+
with_html: bool = False):
248+
report.test_suite_ids = list(set(report.test_suite_ids))
249+
report.mapping_suite_ids = list(set(report.mapping_suite_ids))
250+
251+
if with_html:
252+
add_sparql_validation_summary_html_report(
253+
report=report,
254+
metadata=metadata
255+
)
256+
257+
258+
def generate_sparql_validation_summary_report(report_notices: List[ReportNotice],
259+
mapping_suite_package: MappingSuite,
260+
execute_full_validation: bool = True,
261+
with_html: bool = False,
262+
report: SPARQLValidationSummaryReport = None,
263+
metadata: dict = None) -> SPARQLValidationSummaryReport:
264+
report = init_sparql_validation_summary_report(
265+
report=report,
266+
report_notices=report_notices
267+
)
268+
171269
for report_notice in report_notices:
172270
notice = report_notice.notice
173271
validate_notice_with_sparql_suite(
@@ -176,65 +274,19 @@ def generate_sparql_validation_summary_report(report_notices: List[ReportNotice]
176274
execute_full_validation=execute_full_validation,
177275
with_html=False
178276
)
179-
for sparql_validation in notice.rdf_manifestation.sparql_validations:
180-
test_suite_id = sparql_validation.test_suite_identifier
181-
report.test_suite_ids.append(test_suite_id)
182-
mapping_suite_versioned_id = sparql_validation.mapping_suite_identifier
183-
report.mapping_suite_ids.append(mapping_suite_versioned_id)
184-
185-
validation: SPARQLQueryResult
186-
for validation in sparql_validation.validation_results:
187-
validation_query_result: SPARQLValidationSummaryQueryResult
188-
found_validation_query_result = list(filter(
189-
lambda record:
190-
(record.query.query == validation.query.query)
191-
and (record.query.title == validation.query.title)
192-
and (record.test_suite_identifier == test_suite_id),
193-
report.validation_results
194-
))
195-
196-
if found_validation_query_result:
197-
validation_query_result = found_validation_query_result[0]
198-
else:
199-
validation_query_result = SPARQLValidationSummaryQueryResult(
200-
test_suite_identifier=test_suite_id,
201-
**validation.dict()
202-
)
203-
204-
notice_data: ReportPackageNoticeData = ReportPackageNoticeData(
205-
notice_id=notice.ted_id,
206-
path=str(report_notice.metadata.path),
207-
mapping_suite_versioned_id=mapping_suite_versioned_id,
208-
mapping_suite_identifier=mapping_suite_package.identifier
209-
)
210277

211-
if validation.result == SPARQLQueryRefinedResultType.VALID.value:
212-
validation_query_result.aggregate.valid.count += 1
213-
validation_query_result.aggregate.valid.notices.append(notice_data)
214-
elif validation.result == SPARQLQueryRefinedResultType.UNVERIFIABLE.value:
215-
validation_query_result.aggregate.unverifiable.count += 1
216-
validation_query_result.aggregate.unverifiable.notices.append(notice_data)
217-
elif validation.result == SPARQLQueryRefinedResultType.INVALID.value:
218-
validation_query_result.aggregate.invalid.count += 1
219-
validation_query_result.aggregate.invalid.notices.append(notice_data)
220-
elif validation.result == SPARQLQueryRefinedResultType.WARNING.value:
221-
validation_query_result.aggregate.warning.count += 1
222-
validation_query_result.aggregate.warning.notices.append(notice_data)
223-
elif validation.result == SPARQLQueryRefinedResultType.ERROR.value:
224-
validation_query_result.aggregate.error.count += 1
225-
validation_query_result.aggregate.error.notices.append(notice_data)
226-
227-
if not found_validation_query_result:
228-
report.validation_results.append(validation_query_result)
229-
230-
report.test_suite_ids = list(set(report.test_suite_ids))
231-
report.mapping_suite_ids = list(set(report.mapping_suite_ids))
278+
process_sparql_validation_summary_report_data_with_notice(
279+
notice=notice,
280+
mapping_suite_package=mapping_suite_package,
281+
report_notice_path=report_notice.metadata.path,
282+
report=report
283+
)
232284

233-
if with_html:
234-
template_data: dict = report.dict()
235-
template_data[TEMPLATE_METADATA_KEY] = metadata
236-
html_report = TEMPLATES.get_template(SPARQL_SUMMARY_HTML_REPORT_TEMPLATE).render(template_data)
237-
report.object_data = html_report
285+
finalize_sparql_validation_summary_report(
286+
report=report,
287+
metadata=metadata,
288+
with_html=with_html
289+
)
238290

239291
return report
240292

@@ -250,7 +302,7 @@ def validate_notice_with_sparql_suite(notice: Notice, mapping_suite_package: Map
250302
:return:
251303
"""
252304

253-
def sparql_validation(notice_item: Notice, rdf_manifestation: RDFManifestation, with_html: bool = False) \
305+
def sparql_validation(notice_item: Notice, rdf_manifestation: RDFManifestation) \
254306
-> List[SPARQLTestSuiteValidationReport]:
255307
reports = []
256308
sparql_test_suites = mapping_suite_package.sparql_test_suites
@@ -266,12 +318,10 @@ def sparql_validation(notice_item: Notice, rdf_manifestation: RDFManifestation,
266318
return sorted(reports, key=lambda x: x.test_suite_identifier)
267319

268320
if execute_full_validation:
269-
for report in sparql_validation(notice_item=notice, rdf_manifestation=notice.rdf_manifestation,
270-
with_html=with_html):
321+
for report in sparql_validation(notice_item=notice, rdf_manifestation=notice.rdf_manifestation):
271322
notice.set_rdf_validation(rdf_validation=report)
272323

273-
for report in sparql_validation(notice_item=notice, rdf_manifestation=notice.distilled_rdf_manifestation,
274-
with_html=with_html):
324+
for report in sparql_validation(notice_item=notice, rdf_manifestation=notice.distilled_rdf_manifestation):
275325
notice.set_distilled_rdf_validation(rdf_validation=report)
276326

277327
return notice

0 commit comments

Comments
 (0)