git_brcal/src/server/BreCal/validators/input_validation.py

166 lines
7.0 KiB
Python

####################################### InputValidation #######################################
from abc import ABC, abstractmethod
from BreCal.schemas.model import Ship, Shipcall, Berth, User, Participant
class InputValidation():
def __init__(self):
self.build_supported_models_dictionary()
return
def build_supported_models_dictionary(self):
self.supported_models = {
Ship:ShipValidation(),
Shipcall:ShipcallValidation(),
Berth:BerthValidation(),
User:UserValidation(),
Participant:ParticipantValidation(),
}
return
def assert_if_not_supported(self, dataclass_object):
assert type(dataclass_object) in self.supported_models, f"unsupported model. Found: {type(dataclass_object)}"
return
def verify(self, dataclass_object):
self.assert_if_not_supported(dataclass_object)
# determine the type of the dataclass object. The internal dictionary 'supported_models' matches the dataclass object
# to the respective validation protocol
validator = self.supported_models.get(type(dataclass_object))
# check the object based on the rules within the matched validator
input_validation_state = validator.check(dataclass_object)
return input_validation_state
class DataclassValidation(ABC):
"""parent class of dataclas validators, which determines the outline of every object"""
def __init__(self):
return
def check(self, dataclass_object) -> (list, bool):
"""
the 'check' method provides a default style, how each dataclass object is validated. It returns a list of violations
and a boolean, which determines, whether the check is passed successfully
"""
all_rules = self.apply_all_rules(dataclass_object)
violations = self.filter_violations(all_rules)
input_validation_state = self.evaluate(violations)
return (violations, input_validation_state)
@abstractmethod
def apply_all_rules(self, dataclass_object) -> list:
"""
the 'apply_all_rules' method is mandatory for any dataclass validation object. It should execute all validation rules and
return a list of tuples, where each element is (output_boolean, validation_name)
"""
all_rules = [(True, 'blank_validation_rule')]
return all_rules
def filter_violations(self, all_rules):
"""input: all_rules, a list of tuples, where each element is (output, validation_name), which are (bool, str). """
# if output is False, a violation is observed
violations = [result[1] for result in all_rules if not result[0]]
return violations
def evaluate(self, violations) -> bool:
input_validation_state = len(violations)==0
return input_validation_state
class ShipcallValidation(DataclassValidation):
"""an object that validates a Shipcall dataclass object"""
def __init__(self):
super().__init__()
return
def apply_all_rules(self, dataclass_object) -> list:
"""apply all input validation rules to determine, whether there are violations. returns a list of tuples (output, validation_name)"""
raise NotImplementedError()
return all_rules
from BreCal.validators.schema_validation import ship_bollard_pull_is_defined_or_is_not_tug, ship_bollard_pull_is_none_or_in_range, ship_callsign_len_is_seven_at_maximum, ship_eni_len_is_eight, ship_imo_len_is_seven, ship_length_in_range, ship_participant_id_is_defined_or_is_not_tug, ship_participant_id_is_none_or_int, ship_width_in_range
# skip: ship_max_draft_is_defined_or_is_not_tug, ship_max_draft_is_none_or_in_range,
class ShipValidation(DataclassValidation):
"""an object that validates a Ship dataclass object"""
def __init__(self):
super().__init__()
return
def apply_all_rules(self, dataclass_object) -> list:
"""apply all input validation rules to determine, whether there are violations. returns a list of tuples (output, validation_name)"""
# skip: ship_max_draft_is_defined_or_is_not_tug, ship_max_draft_is_none_or_in_range,
"""
#TODO_ship_max_draft
with pytest.raises(AttributeError, match="'Ship' object has no attribute 'max_draft'"):
assert ship_max_draft_in_range(ship)[0], f"max draft of a ship must be between 0 and 20 meters"
assert ship_max_draft_is_none_or_in_range(ship)[0], f"the max_draft should either be undefined or between 0 and 20 meters"
"""
# list comprehension: every function becomes part of the loop and will be executed. Each function is wrapped and provides (output, validation_name)
all_rules = [
# tuple: (output, validation_name)
check_rule(dataclass_object)
for check_rule in [
ship_bollard_pull_is_defined_or_is_not_tug,
ship_bollard_pull_is_none_or_in_range,
ship_callsign_len_is_seven_at_maximum,
ship_eni_len_is_eight,
ship_imo_len_is_seven,
ship_length_in_range,
ship_participant_id_is_defined_or_is_not_tug,
ship_participant_id_is_none_or_int,
ship_width_in_range
]
]
return all_rules
class BerthValidation(DataclassValidation):
"""an object that validates a Berth dataclass object"""
def __init__(self):
super().__init__()
return
def apply_all_rules(self, dataclass_object) -> list:
"""apply all input validation rules to determine, whether there are violations. returns a list of tuples (output, validation_name)"""
raise NotImplementedError()
return all_rules
class UserValidation(DataclassValidation):
"""an object that validates a User dataclass object"""
def __init__(self):
super().__init__()
return
def apply_all_rules(self, dataclass_object) -> list:
"""apply all input validation rules to determine, whether there are violations. returns a list of tuples (output, validation_name)"""
raise NotImplementedError()
return all_rules
from BreCal.validators.schema_validation import participant_postal_code_len_is_five
class ParticipantValidation(DataclassValidation):
"""an object that validates a Participant dataclass object"""
def __init__(self):
super().__init__()
return
def apply_all_rules(self, dataclass_object) -> list:
"""apply all input validation rules to determine, whether there are violations. returns a list of tuples (output, validation_name)"""
# list comprehension: every function becomes part of the loop and will be executed. Each function is wrapped and provides (output, validation_name)
all_rules = [
# tuple: (output, validation_name)
check_rule(dataclass_object)
for check_rule in [
participant_postal_code_len_is_five,
]
]
return all_rules