From e50b6e7258862fe715886f23a4f01359ca227dea Mon Sep 17 00:00:00 2001 From: hoangtungdinh <11166240+hoangtungdinh@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:32:05 +0200 Subject: [PATCH] Update Signed-off-by: hoangtungdinh <11166240+hoangtungdinh@users.noreply.github.com> --- qc_openscenario/__init__.py | 1 + ...precondition.py => basic_preconditions.py} | 2 +- .../checks/basic_checker/__init__.py | 1 - .../checks/basic_checker/basic_checker.py | 63 ------ .../basic_checker/fileheader_is_present.py | 53 ++--- .../basic_checker/root_tag_is_openscenario.py | 50 ++--- .../basic_checker/valid_xml_document.py | 37 +--- .../basic_checker/version_is_defined.py | 51 ++--- .../checks/data_type_checker/__init__.py | 2 - .../data_type_checker/allowed_operators.py | 53 +---- .../data_type_checker/data_type_checker.py | 17 -- .../data_type_checker_precondition.py | 16 -- ...e_transition_time_in_light_state_action.py | 55 +----- .../positive_duration_in_phase.py | 53 +---- qc_openscenario/checks/models.py | 5 +- .../checks/parameters_checker/__init__.py | 2 - .../parameter_checker_precondition.py | 16 -- .../parameters_checker/parameters_checker.py | 10 - ...valid_parameter_declaration_in_catalogs.py | 53 +---- .../checks/reference_checker/__init__.py | 2 - .../reference_checker/reference_checker.py | 37 ---- .../resolvable_entity_references.py | 56 +----- ...ignal_id_in_traffic_signal_state_action.py | 53 +---- ...resolvable_storyboard_element_reference.py | 56 +----- ...roller_by_traffic_signal_controller_ref.py | 53 +---- .../resolvable_variable_reference.py | 56 +----- .../unique_element_names_on_same_level.py | 53 +---- .../uniquely_resolvable_entity_references.py | 57 +----- ...alid_actor_reference_in_private_actions.py | 57 +----- .../checks/schema_checker/__init__.py | 1 - .../checks/schema_checker/schema_checker.py | 13 -- .../checks/schema_checker/valid_schema.py | 41 +--- qc_openscenario/main.py | 181 ++++++++++++++++-- 33 files changed, 300 insertions(+), 956 deletions(-) rename qc_openscenario/{checks/reference_checker/reference_checker_precondition.py => basic_preconditions.py} (93%) delete mode 100644 qc_openscenario/checks/basic_checker/basic_checker.py delete mode 100644 qc_openscenario/checks/data_type_checker/data_type_checker.py delete mode 100644 qc_openscenario/checks/data_type_checker/data_type_checker_precondition.py delete mode 100644 qc_openscenario/checks/parameters_checker/parameter_checker_precondition.py delete mode 100644 qc_openscenario/checks/parameters_checker/parameters_checker.py delete mode 100644 qc_openscenario/checks/reference_checker/reference_checker.py delete mode 100644 qc_openscenario/checks/schema_checker/schema_checker.py diff --git a/qc_openscenario/__init__.py b/qc_openscenario/__init__.py index 137b3cc..0dc6a13 100644 --- a/qc_openscenario/__init__.py +++ b/qc_openscenario/__init__.py @@ -1,2 +1,3 @@ from . import constants as constants from . import checks as checks +from . import basic_preconditions as basic_preconditions diff --git a/qc_openscenario/checks/reference_checker/reference_checker_precondition.py b/qc_openscenario/basic_preconditions.py similarity index 93% rename from qc_openscenario/checks/reference_checker/reference_checker_precondition.py rename to qc_openscenario/basic_preconditions.py index 87ecdfa..cbb96ac 100644 --- a/qc_openscenario/checks/reference_checker/reference_checker_precondition.py +++ b/qc_openscenario/basic_preconditions.py @@ -7,7 +7,7 @@ from qc_openscenario.checks.schema_checker import valid_schema -PRECONDITIONS = { +CHECKER_PRECONDITIONS = { valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID, fileheader_is_present.CHECKER_ID, diff --git a/qc_openscenario/checks/basic_checker/__init__.py b/qc_openscenario/checks/basic_checker/__init__.py index 6d99129..404da2f 100644 --- a/qc_openscenario/checks/basic_checker/__init__.py +++ b/qc_openscenario/checks/basic_checker/__init__.py @@ -1,4 +1,3 @@ -from . import basic_checker as basic_checker from . import valid_xml_document as valid_xml_document from . import root_tag_is_openscenario as root_tag_is_openscenario from . import fileheader_is_present as fileheader_is_present diff --git a/qc_openscenario/checks/basic_checker/basic_checker.py b/qc_openscenario/checks/basic_checker/basic_checker.py deleted file mode 100644 index 9227674..0000000 --- a/qc_openscenario/checks/basic_checker/basic_checker.py +++ /dev/null @@ -1,63 +0,0 @@ -import logging -import os - -from lxml import etree - -from qc_baselib import Configuration, Result, StatusType - -from qc_openscenario import constants -from qc_openscenario.checks import utils, models - -from qc_openscenario.checks.basic_checker import ( - valid_xml_document, - root_tag_is_openscenario, - fileheader_is_present, - version_is_defined, -) - - -def run_checks(config: Configuration, result: Result) -> models.CheckerData: - logging.info("Executing basic checks") - - xml_file_path = config.get_config_param("InputFile") - - valid_xml_document.check_rule(xml_file_path, result) - - root = None - if result.all_checkers_completed_without_issue({valid_xml_document.CHECKER_ID}): - root = utils.get_root_without_default_namespace(xml_file_path) - - root_tag_is_openscenario.check_rule(root, result) - fileheader_is_present.check_rule(root, result) - version_is_defined.check_rule(root, result) - - checker_data = None - - if result.all_checkers_completed_without_issue( - { - valid_xml_document.CHECKER_ID, - root_tag_is_openscenario.CHECKER_ID, - fileheader_is_present.CHECKER_ID, - version_is_defined.CHECKER_ID, - } - ): - xosc_schema_version = utils.get_standard_schema_version(root) - xodr_root = utils.get_xodr_road_network(xml_file_path, root) - checker_data = models.CheckerData( - input_file_xml_root=root, - config=config, - result=result, - schema_version=xosc_schema_version, - xodr_root=xodr_root, - ) - else: - logging.info("Error found in basic rules!") - checker_data = models.CheckerData( - input_file_xml_root=None, - config=config, - result=result, - schema_version=None, - xodr_root=None, - ) - - return checker_data diff --git a/qc_openscenario/checks/basic_checker/fileheader_is_present.py b/qc_openscenario/checks/basic_checker/fileheader_is_present.py index 3b81615..8174b8a 100644 --- a/qc_openscenario/checks/basic_checker/fileheader_is_present.py +++ b/qc_openscenario/checks/basic_checker/fileheader_is_present.py @@ -1,8 +1,8 @@ import logging -from lxml import etree -from qc_baselib import IssueSeverity, Result, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants +from qc_openscenario.checks import models from qc_openscenario.checks.basic_checker import ( valid_xml_document, @@ -10,10 +10,15 @@ ) CHECKER_ID = "check_asam_xosc_xml_fileheader_is_present" -PRECONDITIONS = {valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID} +CHECKER_DESCRIPTION = "Below the root element a tag with FileHeader must be defined." +CHECKER_PRECONDITIONS = { + valid_xml_document.CHECKER_ID, + root_tag_is_openscenario.CHECKER_ID, +} +RULE_UID = "asam.net:xosc:1.0.0:xml.fileheader_is_present" -def check_rule(tree: etree._ElementTree, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ Below the root element a tag with FileHeader must be defined. @@ -22,31 +27,7 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: """ logging.info("Executing fileheader_is_present check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Below the root element a tag with FileHeader must be defined.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.fileheader_is_present", - ) - - if not result.all_checkers_completed_without_issue(PRECONDITIONS): - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - root = tree.getroot() + root = checker_data.input_file_xml_root.getroot() is_valid = False # Check if root contains a tag 'FileHeader' @@ -60,24 +41,18 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, description="Issue flagging when no FileHeader is found under root element", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_xml_location( + checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, - xpath=tree.getpath(root), + xpath=checker_data.input_file_xml_root.getpath(root), description=f'No child element "FileHeader"', ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py b/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py index cfd8ce2..fb04dc2 100644 --- a/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py +++ b/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py @@ -1,16 +1,18 @@ import logging -from lxml import etree -from qc_baselib import IssueSeverity, Result, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants +from qc_openscenario.checks import models from qc_openscenario.checks.basic_checker import valid_xml_document CHECKER_ID = "check_asam_xosc_xml_root_tag_is_openscenario" -PRECONDITIONS = {valid_xml_document.CHECKER_ID} +CHECKER_DESCRIPTION = "The root element of a valid XML document must be OpenSCENARIO." +CHECKER_PRECONDITIONS = {valid_xml_document.CHECKER_ID} +RULE_UID = "asam.net:xosc:1.0.0:xml.root_tag_is_openscenario" -def check_rule(tree: etree._ElementTree, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ The root element of a valid XML document must be OpenSCENARIO @@ -19,31 +21,7 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: """ logging.info("Executing root_tag_is_openscenario check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The root element of a valid XML document must be OpenSCENARIO.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.root_tag_is_openscenario", - ) - - if not result.all_checkers_completed_without_issue(PRECONDITIONS): - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - root = tree.getroot() + root = checker_data.input_file_xml_root.getroot() is_valid = False if root.tag == "OpenSCENARIO": @@ -55,24 +33,18 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, description="Issue flagging when root tag is not OpenSCENARIO", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_xml_location( + checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, - xpath=tree.getpath(root), + xpath=checker_data.input_file_xml_root.getpath(root), description=f"Root is not OpenSCENARIO", ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/basic_checker/valid_xml_document.py b/qc_openscenario/checks/basic_checker/valid_xml_document.py index 2f83fc7..2e2b7c3 100644 --- a/qc_openscenario/checks/basic_checker/valid_xml_document.py +++ b/qc_openscenario/checks/basic_checker/valid_xml_document.py @@ -2,10 +2,14 @@ from lxml import etree -from qc_baselib import Result, IssueSeverity, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants +from qc_openscenario.checks import models CHECKER_ID = "check_asam_xosc_xml_valid_xml_document" +CHECKER_DESCRIPTION = "The given file to check must be a valid XML document." +CHECKER_PRECONDITIONS = set() +RULE_UID = "asam.net:xosc:1.0.0:xml.valid_xml_document" def _is_xml_doc(file_path: str) -> tuple[bool, tuple[int, int]]: @@ -21,7 +25,7 @@ def _is_xml_doc(file_path: str) -> tuple[bool, tuple[int, int]]: return False, (e.lineno, e.offset) -def check_rule(input_xml_file_path: str, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ Implements a rule to check if input file is a valid xml document @@ -30,34 +34,19 @@ def check_rule(input_xml_file_path: str, result: Result) -> None: """ logging.info("Executing valid_xml_document check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The given file to check must be a valid XML document.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.valid_xml_document", - ) - - is_valid, error_location = _is_xml_doc(input_xml_file_path) + is_valid, error_location = _is_xml_doc(checker_data.xml_file_path) if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, description="The input file is not a valid xml document", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_file_location( + checker_data.result.add_file_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, @@ -65,9 +54,3 @@ def check_rule(input_xml_file_path: str, result: Result) -> None: column=error_location[1], description=f"Invalid xml file.", ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/basic_checker/version_is_defined.py b/qc_openscenario/checks/basic_checker/version_is_defined.py index 397a9ad..bf946e2 100644 --- a/qc_openscenario/checks/basic_checker/version_is_defined.py +++ b/qc_openscenario/checks/basic_checker/version_is_defined.py @@ -1,8 +1,9 @@ import logging -from lxml import etree -from qc_baselib import IssueSeverity, Result, StatusType + +from qc_baselib import IssueSeverity, StatusType from qc_openscenario import constants +from qc_openscenario.checks import models from qc_openscenario.checks.basic_checker import ( valid_xml_document, @@ -11,11 +12,13 @@ ) CHECKER_ID = "check_asam_xosc_xml_version_is_defined" -PRECONDITIONS = { +CHECKER_DESCRIPTION = "The FileHeader tag must have the attributes revMajor and revMinor and of type unsignedShort." +CHECKER_PRECONDITIONS = { valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID, fileheader_is_present.CHECKER_ID, } +RULE_UID = "asam.net:xosc:1.0.0:xml.version_is_defined" def is_unsigned_short(value: int) -> bool: @@ -27,7 +30,7 @@ def is_unsigned_short(value: int) -> bool: return False -def check_rule(tree: etree._ElementTree, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ The FileHeader tag must have the attributes revMajor and revMinor and of type unsignedShort. @@ -36,31 +39,7 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: """ logging.info("Executing version_is_defined check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The FileHeader tag must have the attributes revMajor and revMinor and of type unsignedShort.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.version_is_defined", - ) - - if not result.all_checkers_completed_without_issue(PRECONDITIONS): - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - root = tree.getroot() + root = checker_data.input_file_xml_root.getroot() is_valid = True # Check if root contains a tag 'FileHeader' @@ -91,24 +70,18 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, description="Issue flagging when revMajor revMinor attribute of FileHeader are missing or invalid", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_xml_location( + checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, - xpath=tree.getpath(file_header_tag), + xpath=checker_data.input_file_xml_root.getpath(file_header_tag), description=f'"FileHeader" tag has invalid or missing version info', ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/data_type_checker/__init__.py b/qc_openscenario/checks/data_type_checker/__init__.py index c05a5a3..7338e41 100644 --- a/qc_openscenario/checks/data_type_checker/__init__.py +++ b/qc_openscenario/checks/data_type_checker/__init__.py @@ -1,5 +1,3 @@ -from . import data_type_checker_precondition as data_type_checker_precondition -from . import data_type_checker as data_type_checker from . import allowed_operators as allowed_operators from . import ( non_negative_transition_time_in_light_state_action as non_negative_transition_time_in_light_state_action, diff --git a/qc_openscenario/checks/data_type_checker/allowed_operators.py b/qc_openscenario/checks/data_type_checker/allowed_operators.py index dd24e19..c529f57 100644 --- a/qc_openscenario/checks/data_type_checker/allowed_operators.py +++ b/qc_openscenario/checks/data_type_checker/allowed_operators.py @@ -10,13 +10,15 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.data_type_checker import data_type_checker_precondition +from qc_openscenario import basic_preconditions import re import enum CHECKER_ID = "check_asam_xosc_data_type_allowed_operators" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Expressions in OpenSCENARIO must only use the allowed operands." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:data_type.allowed_operators" ALLOWED_OPERANDS = set() ALLOWED_OPERANDS.add("-") @@ -105,45 +107,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing allowed_operators check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Expressions in OpenSCENARIO must only use the allowed operands.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="data_type.allowed_operators", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - data_type_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - tree = checker_data.input_file_xml_root root = tree.getroot() attributes = get_all_attributes(tree, root) @@ -189,7 +152,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging invalid operand is used within expression", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -198,9 +161,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Invalid operand {token} used", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/data_type_checker/data_type_checker.py b/qc_openscenario/checks/data_type_checker/data_type_checker.py deleted file mode 100644 index f6e4255..0000000 --- a/qc_openscenario/checks/data_type_checker/data_type_checker.py +++ /dev/null @@ -1,17 +0,0 @@ -import logging - -from qc_openscenario.checks import models - -from qc_openscenario.checks.data_type_checker import ( - allowed_operators, - non_negative_transition_time_in_light_state_action, - positive_duration_in_phase, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing data_type checks") - - allowed_operators.check_rule(checker_data) - non_negative_transition_time_in_light_state_action.check_rule(checker_data) - positive_duration_in_phase.check_rule(checker_data) diff --git a/qc_openscenario/checks/data_type_checker/data_type_checker_precondition.py b/qc_openscenario/checks/data_type_checker/data_type_checker_precondition.py deleted file mode 100644 index 87ecdfa..0000000 --- a/qc_openscenario/checks/data_type_checker/data_type_checker_precondition.py +++ /dev/null @@ -1,16 +0,0 @@ -from qc_openscenario.checks.basic_checker import ( - valid_xml_document, - root_tag_is_openscenario, - fileheader_is_present, - version_is_defined, -) - -from qc_openscenario.checks.schema_checker import valid_schema - -PRECONDITIONS = { - valid_xml_document.CHECKER_ID, - root_tag_is_openscenario.CHECKER_ID, - fileheader_is_present.CHECKER_ID, - version_is_defined.CHECKER_ID, - valid_schema.CHECKER_ID, -} diff --git a/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py b/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py index 0459a4c..7eb2f57 100644 --- a/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py +++ b/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py @@ -5,12 +5,16 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.data_type_checker import data_type_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = ( "check_asam_xosc_data_type_non_negative_transition_time_in_light_state_action" ) -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Expressions in OpenSCENARIO must only use the allowed operands." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = ( + "asam.net:xosc:1.2.0:data_type.non_negative_transition_time_in_light_state_action" +) def check_rule(checker_data: models.CheckerData) -> None: @@ -30,45 +34,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing non_negative_transition_time_in_light_state_action check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Expressions in OpenSCENARIO must only use the allowed operands.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="data_type.non_negative_transition_time_in_light_state_action", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - data_type_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root light_state_nodes = root.findall(".//LightStateAction") @@ -133,7 +98,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue transitionTime in LightStateAction node is negative", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -142,9 +107,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"transitionTime duration {current_numeric_value} is negative", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py b/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py index 82215be..c3aabaf 100644 --- a/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py +++ b/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py @@ -5,10 +5,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.data_type_checker import data_type_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_positive_duration_in_phase" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Expressions in OpenSCENARIO must only use the allowed operands." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:data_type.positive_duration_in_phase" def check_rule(checker_data: models.CheckerData) -> None: @@ -28,45 +30,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing positive_duration_in_phase check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Expressions in OpenSCENARIO must only use the allowed operands.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="data_type.positive_duration_in_phase", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - data_type_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root phase_nodes = root.findall(".//Phase") @@ -122,7 +85,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging when attribute “duration” in the complex type “Phase” is negative", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -131,9 +94,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Phase duration {current_numeric_value} is negative", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/models.py b/qc_openscenario/checks/models.py index b0c703c..aacd3d7 100644 --- a/qc_openscenario/checks/models.py +++ b/qc_openscenario/checks/models.py @@ -8,10 +8,11 @@ @dataclass class CheckerData: - input_file_xml_root: etree._ElementTree + xml_file_path: str + input_file_xml_root: Union[None, etree._ElementTree] config: Configuration result: Result - schema_version: str + schema_version: Union[None, str] xodr_root: Union[None, etree._ElementTree] diff --git a/qc_openscenario/checks/parameters_checker/__init__.py b/qc_openscenario/checks/parameters_checker/__init__.py index 919e248..8c8e504 100644 --- a/qc_openscenario/checks/parameters_checker/__init__.py +++ b/qc_openscenario/checks/parameters_checker/__init__.py @@ -1,5 +1,3 @@ -from . import parameters_checker as parameters_checker -from . import parameter_checker_precondition as parameter_checker_precondition from . import ( valid_parameter_declaration_in_catalogs as valid_parameter_declaration_in_catalogs, ) diff --git a/qc_openscenario/checks/parameters_checker/parameter_checker_precondition.py b/qc_openscenario/checks/parameters_checker/parameter_checker_precondition.py deleted file mode 100644 index 87ecdfa..0000000 --- a/qc_openscenario/checks/parameters_checker/parameter_checker_precondition.py +++ /dev/null @@ -1,16 +0,0 @@ -from qc_openscenario.checks.basic_checker import ( - valid_xml_document, - root_tag_is_openscenario, - fileheader_is_present, - version_is_defined, -) - -from qc_openscenario.checks.schema_checker import valid_schema - -PRECONDITIONS = { - valid_xml_document.CHECKER_ID, - root_tag_is_openscenario.CHECKER_ID, - fileheader_is_present.CHECKER_ID, - version_is_defined.CHECKER_ID, - valid_schema.CHECKER_ID, -} diff --git a/qc_openscenario/checks/parameters_checker/parameters_checker.py b/qc_openscenario/checks/parameters_checker/parameters_checker.py deleted file mode 100644 index e9d7ae6..0000000 --- a/qc_openscenario/checks/parameters_checker/parameters_checker.py +++ /dev/null @@ -1,10 +0,0 @@ -import logging -from qc_openscenario.checks import models -from qc_openscenario.checks.parameters_checker import ( - valid_parameter_declaration_in_catalogs, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing parameters checks") - valid_parameter_declaration_in_catalogs.check_rule(checker_data) diff --git a/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py b/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py index 0551e2f..afc70f7 100644 --- a/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py +++ b/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py @@ -6,10 +6,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.parameters_checker import parameter_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_parameters_valid_parameter_declaration_in_catalogs" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "All parameters used within a catalog shall be declared within their ParameterDeclaration in the same catalog, which sets a default value for each parameter." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:parameters.valid_parameter_declaration_in_catalogs" def check_rule(checker_data: models.CheckerData) -> None: @@ -30,45 +32,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing valid_parameter_declaration_in_catalogs check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="All parameters used within a catalog shall be declared within their ParameterDeclaration in the same catalog, which sets a default value for each parameter.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="parameters.valid_parameter_declaration_in_catalogs", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - parameter_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root catalogs_node = root.findall(".//Catalog") @@ -129,7 +92,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging when used parameters is not defined or has not default value within a catalog", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -138,9 +101,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Parameter value {attr_value[1:]} for attribute {attr_name} is not defined in Catalog or has no default value", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/__init__.py b/qc_openscenario/checks/reference_checker/__init__.py index 335ceca..b3abddd 100644 --- a/qc_openscenario/checks/reference_checker/__init__.py +++ b/qc_openscenario/checks/reference_checker/__init__.py @@ -1,4 +1,3 @@ -from . import reference_checker as reference_checker from . import ( uniquely_resolvable_entity_references as uniquely_resolvable_entity_references, ) @@ -17,4 +16,3 @@ resolvable_storyboard_element_reference as resolvable_storyboard_element_reference, ) from . import unique_element_names_on_same_level as unique_element_names_on_same_level -from . import reference_checker_precondition as reference_checker_precondition diff --git a/qc_openscenario/checks/reference_checker/reference_checker.py b/qc_openscenario/checks/reference_checker/reference_checker.py deleted file mode 100644 index a73b42b..0000000 --- a/qc_openscenario/checks/reference_checker/reference_checker.py +++ /dev/null @@ -1,37 +0,0 @@ -import logging - - -from qc_baselib import StatusType - -from qc_openscenario import constants -from qc_openscenario.checks import models - -from qc_openscenario.checks.schema_checker import valid_schema - -from qc_openscenario.checks.reference_checker import ( - uniquely_resolvable_entity_references, - resolvable_signal_id_in_traffic_signal_state_action, - resolvable_traffic_signal_controller_by_traffic_signal_controller_ref, - valid_actor_reference_in_private_actions, - resolvable_entity_references, - resolvable_variable_reference, - resolvable_storyboard_element_reference, - unique_element_names_on_same_level, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing reference checks") - - uniquely_resolvable_entity_references.check_rule(checker_data=checker_data) - resolvable_signal_id_in_traffic_signal_state_action.check_rule( - checker_data=checker_data - ) - resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.check_rule( - checker_data=checker_data - ) - valid_actor_reference_in_private_actions.check_rule(checker_data=checker_data) - resolvable_entity_references.check_rule(checker_data=checker_data) - resolvable_variable_reference.check_rule(checker_data=checker_data) - resolvable_storyboard_element_reference.check_rule(checker_data=checker_data) - unique_element_names_on_same_level.check_rule(checker_data=checker_data) diff --git a/qc_openscenario/checks/reference_checker/resolvable_entity_references.py b/qc_openscenario/checks/reference_checker/resolvable_entity_references.py index 2fb82c6..4a8be5a 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_entity_references.py +++ b/qc_openscenario/checks/reference_checker/resolvable_entity_references.py @@ -4,11 +4,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_entity_references" -MIN_RULE_VERSION = "1.2.0" -RULE_SEVERITY = IssueSeverity.ERROR +CHECKER_DESCRIPTION = "A named reference in the EntityRef must be resolvable." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_entity_references" def check_rule(checker_data: models.CheckerData) -> None: @@ -28,45 +29,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_entity_references check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="A named reference in the EntityRef must be resolvable.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_entity_references", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root entities_node = root.find("Entities") @@ -136,8 +98,8 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, description="Issue flagging when an entity is referred in a entityRef attribute but it is not declared among Entities", - level=RULE_SEVERITY, - rule_uid=rule_uid, + level=IssueSeverity.ERROR, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -146,9 +108,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Entity at {xpath} with id {current_entity_ref} not found among defined Entities ", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py b/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py index 86fcdc5..6fc5935 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py +++ b/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py @@ -4,10 +4,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_signal_id_in_traffic_signal_state_action" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "TrafficSignalStateAction:name -> Signal ID must exist within the given road network." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_signal_id_in_traffic_signal_state_action" def check_rule(checker_data: models.CheckerData) -> None: @@ -27,45 +29,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_signal_id_in_traffic_signal_state_action check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="TrafficSignalStateAction:name -> Signal ID must exist within the given road network.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_signal_id_in_traffic_signal_state_action", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root if checker_data.xodr_root is None: @@ -106,7 +69,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging traffic light id not present in linked xodr file", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -115,9 +78,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Traffic Light {xpath} with id {current_name} not found in xodr file", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py b/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py index 02178b6..c0ff15d 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py +++ b/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py @@ -5,10 +5,15 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_storyboard_element_reference" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "The attribute storyboardElementRef shall point to an existing element of the corresponding type and shall be uniquely resolvable." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = ( + "asam.net:xosc:1.2.0:reference_control.resolvable_storyboard_element_reference" +) + STORYBOARD_ELEMENTS = ["Act", "Action", "Event", "Maneuver", "ManeuverGroup", " Story"] @@ -30,45 +35,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_storyboard_element_reference check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The attribute storyboardElementRef shall point to an existing element of the corresponding type and shall be uniquely resolvable.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_storyboard_element_reference", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root storyboard_node = root.find("Storyboard") @@ -162,7 +128,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging when a storyboardElementRef does not point to an existing element", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) issue_description = f"Storyboard element reference {current_storyboard_el_ref} not found among Storyboard elements " checker_data.result.add_xml_location( @@ -172,9 +138,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=issue_description, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py b/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py index de890d6..4a26ec8 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py +++ b/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py @@ -5,10 +5,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_traffic_signal_controller_by_traffic_signal_controller_ref" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "The trafficSignalController according to the trafficSignalControllerRef property must exist within the scenarios RoadNetwork definition." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_traffic_signal_controller_by_traffic_signal_controller_ref" def check_rule(checker_data: models.CheckerData) -> None: @@ -30,45 +32,6 @@ def check_rule(checker_data: models.CheckerData) -> None: "Executing resolvable_traffic_signal_controller_by_traffic_signal_controller_ref check" ) - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The trafficSignalController according to the trafficSignalControllerRef property must exist within the scenarios RoadNetwork definition.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_traffic_signal_controller_by_traffic_signal_controller_ref", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root road_network = root.find("RoadNetwork") @@ -114,7 +77,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging traffic signal controller reference not present in the declared RoadNetwork", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -123,9 +86,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"trafficSignalControllerRef at {xpath} with id {current_name} not found in RoadNetwork node", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py b/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py index 5abe2b5..cc788ed 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py +++ b/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py @@ -5,11 +5,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_variable_reference" -MIN_RULE_VERSION = "1.2.0" -RULE_SEVERITY = IssueSeverity.ERROR +CHECKER_DESCRIPTION = "The VariableDeclaration according to the variableRef property must exist within the ScenarioDefinition." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_variable_reference" def check_rule(checker_data: models.CheckerData) -> None: @@ -29,45 +30,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_variable_reference check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The VariableDeclaration according to the variableRef property must exist within the ScenarioDefinition.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_variable_reference", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root parameter_declaration_nodes = root.find("ParameterDeclarations") @@ -112,8 +74,8 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, description="Issue flagging when a variable is referred in a variableRef attribute but it is not found within ScenarioDefinition", - level=RULE_SEVERITY, - rule_uid=rule_uid, + level=IssueSeverity.ERROR, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -122,9 +84,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Variable with id {current_name} not found within ScenarioDefinition", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py b/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py index cd7073b..0a18d23 100644 --- a/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py +++ b/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py @@ -10,11 +10,13 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions from collections import deque, defaultdict CHECKER_ID = "check_asam_xosc_reference_control_unique_element_names_on_same_level" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Element names at each level shall be unique at that level." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.unique_element_names_on_same_level" @dataclass @@ -79,45 +81,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing unique_element_names_on_same_level check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Element names at each level shall be unique at that level.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.unique_element_names_on_same_level", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - tree = checker_data.input_file_xml_root duplicates_found = are_names_unique_at_each_level(tree, tree.getroot()) @@ -127,7 +90,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging when a element name is not unique within its level", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) issue_description = f"Element {duplicate.name} is duplicated" checker_data.result.add_xml_location( @@ -137,9 +100,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=duplicate.xpath, description=issue_description, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py b/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py index 141c4a4..2708e48 100644 --- a/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py +++ b/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py @@ -4,15 +4,17 @@ from lxml import etree -from qc_baselib import IssueSeverity, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants -from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario.checks import models +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_uniquely_resolvable_entity_references" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Reference names must be unique" +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.uniquely_resolvable_entity_references" def get_catalogs(root: etree._ElementTree) -> List[etree._ElementTree]: @@ -37,45 +39,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing uniquely_resolvable_entity_references check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Input xml file must be valid according to the schema.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.uniquely_resolvable_entity_references", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root # List to store problematic nodes @@ -113,7 +76,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Referenced names are not unique", level=IssueSeverity.WARNING, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) for error in errors: @@ -130,9 +93,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=error_duplicate_xpath, description=error_msg, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py b/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py index dc00851..5fe3dd9 100644 --- a/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py +++ b/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py @@ -4,14 +4,18 @@ from qc_baselib import IssueSeverity, StatusType from qc_openscenario import constants -from qc_openscenario.checks import utils, models +from qc_openscenario.checks import models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = ( "check_asam_xosc_reference_control_valid_actor_reference_in_private_actions" ) -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "In a ManeuverGroup, if the defined action is a private action an actor must be defined." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = ( + "asam.net:xosc:1.2.0:reference_control.valid_actor_reference_in_private_actions" +) def check_rule(checker_data: models.CheckerData) -> None: @@ -32,45 +36,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing valid_actor_reference_in_private_actions check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="In a ManeuverGroup, if the defined action is a private action an actor must be defined.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.valid_actor_reference_in_private_actions", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root maneuver_groups = root.findall(".//ManeuverGroup") @@ -114,7 +79,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Issue flagging when no Actor is specified but a PrivateAction is used", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) private_actions_xpaths = [root.getpath(x) for x in private_actions] checker_data.result.add_xml_location( @@ -124,9 +89,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"ManeuverGroup at {xpath} uses private actions {private_actions_xpaths} but it defines no actor", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/schema_checker/__init__.py b/qc_openscenario/checks/schema_checker/__init__.py index d643e74..660fc3a 100644 --- a/qc_openscenario/checks/schema_checker/__init__.py +++ b/qc_openscenario/checks/schema_checker/__init__.py @@ -1,2 +1 @@ -from . import schema_checker as schema_checker from . import valid_schema as valid_schema diff --git a/qc_openscenario/checks/schema_checker/schema_checker.py b/qc_openscenario/checks/schema_checker/schema_checker.py deleted file mode 100644 index 9ba0682..0000000 --- a/qc_openscenario/checks/schema_checker/schema_checker.py +++ /dev/null @@ -1,13 +0,0 @@ -import logging - - -from qc_openscenario.checks import models - -from qc_openscenario.checks.schema_checker import ( - valid_schema, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing schema checks") - valid_schema.check_rule(checker_data) diff --git a/qc_openscenario/checks/schema_checker/valid_schema.py b/qc_openscenario/checks/schema_checker/valid_schema.py index 205ca7a..9373fc0 100644 --- a/qc_openscenario/checks/schema_checker/valid_schema.py +++ b/qc_openscenario/checks/schema_checker/valid_schema.py @@ -17,12 +17,14 @@ ) CHECKER_ID = "check_asam_xosc_xml_valid_schema" -PRECONDITIONS = { +CHECKER_DESCRIPTION = "Input xml file must be valid according to the schema." +CHECKER_PRECONDITIONS = { valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID, fileheader_is_present.CHECKER_ID, version_is_defined.CHECKER_ID, } +RULE_UID = "asam.net:xosc:1.0.0:xml.valid_schema" def _is_schema_compliant( @@ -62,32 +64,10 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing valid_schema check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Input xml file must be valid according to the schema.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.valid_schema", - ) - - if not checker_data.result.all_checkers_completed_without_issue(PRECONDITIONS): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - schema_version = checker_data.schema_version - if schema_version is None or schema_version not in schema_files.SCHEMA_FILES: + xsd_file = schema_files.SCHEMA_FILES.get(schema_version) + + if xsd_file is None: logging.info( f"- Schema file for version {schema_version} does not exist. Skipping check" ) @@ -100,7 +80,6 @@ def check_rule(checker_data: models.CheckerData) -> None: return - xsd_file = schema_files.SCHEMA_FILES[schema_version] xsd_file_path = str( importlib.resources.files("qc_openscenario.schema").joinpath(xsd_file) ) @@ -116,7 +95,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Input file does not follow its version schema", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_file_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -126,9 +105,3 @@ def check_rule(checker_data: models.CheckerData) -> None: column=error.column, description=error.message, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/main.py b/qc_openscenario/main.py index ad09301..a57b830 100644 --- a/qc_openscenario/main.py +++ b/qc_openscenario/main.py @@ -1,16 +1,18 @@ import argparse import logging from datetime import datetime +import types -from qc_baselib import Configuration, Result +from qc_baselib import Configuration, Result, StatusType from qc_baselib.models.common import ParamType from qc_openscenario import constants -from qc_openscenario.checks.schema_checker import schema_checker -from qc_openscenario.checks.basic_checker import basic_checker -from qc_openscenario.checks.reference_checker import reference_checker -from qc_openscenario.checks.parameters_checker import parameters_checker -from qc_openscenario.checks.data_type_checker import data_type_checker +from qc_openscenario.checks import schema_checker +from qc_openscenario.checks import basic_checker +from qc_openscenario.checks import reference_checker +from qc_openscenario.checks import parameters_checker +from qc_openscenario.checks import data_type_checker +from qc_openscenario.checks import utils, models logging.basicConfig(format="%(asctime)s - %(message)s", level=logging.INFO) @@ -30,21 +32,176 @@ def args_entrypoint() -> argparse.Namespace: return parser.parse_args() +def execute_checker( + checker: types.ModuleType, + checker_data: models.CheckerData, + required_definition_setting: bool = True, +) -> None: + # Register checker + checker_data.result.register_checker( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + description=checker.CHECKER_DESCRIPTION, + ) + + # Register rule uid + splitted_rule_uid = checker.RULE_UID.split(":") + if len(splitted_rule_uid) != 4: + raise RuntimeError(f"Invalid rule uid: {checker.RULE_UID}") + + checker_data.result.register_rule( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + emanating_entity=splitted_rule_uid[0], + standard=splitted_rule_uid[1], + definition_setting=splitted_rule_uid[2], + rule_full_name=splitted_rule_uid[3], + ) + + # Check preconditions. If not satisfied then set status as SKIPPED and return + if not checker_data.result.all_checkers_completed_without_issue( + checker.CHECKER_PRECONDITIONS + ): + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.SKIPPED, + ) + + return + + # Checker definition setting. If not satisfied then set status as SKIPPED and return + if required_definition_setting: + schema_version = checker_data.schema_version + definition_setting = splitted_rule_uid[2] + if ( + schema_version is None + or utils.compare_versions(schema_version, definition_setting) < 0 + ): + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.SKIPPED, + ) + + return + + # Execute checker + try: + checker.check_rule(checker_data) + + # If checker is not explicitly set as SKIPPED, then set it as COMPLETED + if ( + checker_data.result.get_checker_status(checker.CHECKER_ID) + != StatusType.SKIPPED + ): + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.COMPLETED, + ) + except Exception: + # If any exception occurs during the check, set the status as ERROR + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.ERROR, + ) + + def run_checks(config: Configuration, result: Result) -> None: + checker_data = models.CheckerData( + xml_file_path=config.get_config_param("InputFile"), + input_file_xml_root=None, + config=config, + result=result, + schema_version=None, + xodr_root=None, + ) + # 1. Run basic checks - checker_data = basic_checker.run_checks(config=config, result=result) + execute_checker( + basic_checker.valid_xml_document, + checker_data, + required_definition_setting=False, + ) - # 2. Run xml checks - schema_checker.run_checks(checker_data) + if result.all_checkers_completed_without_issue( + {basic_checker.valid_xml_document.CHECKER_ID} + ): + checker_data.input_file_xml_root = utils.get_root_without_default_namespace( + checker_data.xml_file_path + ) + + execute_checker( + basic_checker.root_tag_is_openscenario, + checker_data, + required_definition_setting=False, + ) + execute_checker( + basic_checker.fileheader_is_present, + checker_data, + required_definition_setting=False, + ) + execute_checker( + basic_checker.version_is_defined, + checker_data, + required_definition_setting=False, + ) + + # Get schema version and xodr road network if they exist + if result.all_checkers_completed_without_issue( + { + basic_checker.valid_xml_document.CHECKER_ID, + basic_checker.root_tag_is_openscenario.CHECKER_ID, + basic_checker.fileheader_is_present.CHECKER_ID, + basic_checker.version_is_defined.CHECKER_ID, + } + ): + checker_data.schema_version = utils.get_standard_schema_version( + checker_data.input_file_xml_root + ) + checker_data.xodr_root = utils.get_xodr_road_network( + checker_data.xml_file_path, checker_data.input_file_xml_root + ) + + # 2. Run schema check + execute_checker(schema_checker.valid_schema, checker_data) # 3. Run reference checks - reference_checker.run_checks(checker_data) + execute_checker( + reference_checker.uniquely_resolvable_entity_references, checker_data + ) + execute_checker( + reference_checker.resolvable_signal_id_in_traffic_signal_state_action, + checker_data, + ) + execute_checker( + reference_checker.resolvable_traffic_signal_controller_by_traffic_signal_controller_ref, + checker_data, + ) + execute_checker( + reference_checker.valid_actor_reference_in_private_actions, checker_data + ) + execute_checker(reference_checker.resolvable_entity_references, checker_data) + execute_checker(reference_checker.resolvable_variable_reference, checker_data) + execute_checker( + reference_checker.resolvable_storyboard_element_reference, checker_data + ) + execute_checker(reference_checker.unique_element_names_on_same_level, checker_data) # 4. Run parameters checks - parameters_checker.run_checks(checker_data) + execute_checker( + parameters_checker.valid_parameter_declaration_in_catalogs, checker_data + ) # 5. Run data_type checks - data_type_checker.run_checks(checker_data) + execute_checker(data_type_checker.allowed_operators, checker_data) + execute_checker( + data_type_checker.non_negative_transition_time_in_light_state_action, + checker_data, + ) + execute_checker(data_type_checker.positive_duration_in_phase, checker_data) def main():