@@ -1143,6 +1143,32 @@ def __get_requirement_loader__(cls, profile: Profile, requirement_path: Path) ->
11431143 setattr (profile , loader_instance_name , loader_instance )
11441144 return loader_instance
11451145
1146+ @staticmethod
1147+ def __get_requirement_classes__ () -> list [Type [Requirement ]]:
1148+
1149+ # Ensure known requirement modules are imported so subclasses are registered.
1150+ for requirement_type in ("python" , "shacl" ):
1151+ module_name = f"rocrate_validator.requirements.{ requirement_type } "
1152+ try :
1153+ importlib .import_module (module_name )
1154+ except Exception :
1155+ logger .debug (
1156+ "Unable to import requirement module: %s" ,
1157+ module_name ,
1158+ exc_info = True ,
1159+ )
1160+
1161+ def all_subclasses (
1162+ base_class : Type [Requirement ],
1163+ ) -> list [Type [Requirement ]]:
1164+ result : list [Type [Requirement ]] = []
1165+ for subcls in base_class .__subclasses__ ():
1166+ result .append (subcls )
1167+ result .extend (all_subclasses (subcls ))
1168+ return result
1169+
1170+ return all_subclasses (Requirement )
1171+
11461172 @staticmethod
11471173 def load_requirements (profile : Profile , severity : Severity = None ) -> list [Requirement ]:
11481174 """
@@ -2682,7 +2708,8 @@ def __do_validate__(self,
26822708 # register the current context
26832709 self .__current_context__ = context
26842710
2685- try :
2711+ # initialize the requirement types
2712+ self .__invoke_pre_validation_hooks__ (context )
26862713
26872714 # set the profiles to validate against
26882715 profiles = context .profiles
@@ -2720,14 +2747,31 @@ def __do_validate__(self,
27202747 self .notify (ProfileValidationEvent (EventType .PROFILE_VALIDATION_END , profile = profile ))
27212748 if terminate :
27222749 break
2723- self .notify (ValidationEvent (EventType .VALIDATION_END ,
2724- validation_result = context .result ))
27252750
2751+ # finalize the requirement types
2752+ self .__invoke_post_validation_hooks__ (context )
2753+ # notify the end of the validation
2754+ self .notify (ValidationEvent (EventType .VALIDATION_END , validation_result = context .result ))
2755+ # return the validation result
27262756 return context .result
27272757 finally :
27282758 # clear the current context
27292759 self .__current_context__ = None
27302760
2761+ def __invoke_pre_validation_hooks__ (self , context : ValidationContext ):
2762+ logger .debug ("Initializing requirement types: starting..." )
2763+ requirements_types = RequirementLoader .__get_requirement_classes__ ()
2764+ for requirement_type in requirements_types :
2765+ requirement_type .initialize (context )
2766+ logger .debug ("Initializing requirement types: completed" )
2767+
2768+ def __invoke_post_validation_hooks__ (self , context : ValidationContext ):
2769+ logger .debug ("Finalizing requirement types: starting..." )
2770+ requirements_types = RequirementLoader .__get_requirement_classes__ ()
2771+ for requirement_type in requirements_types :
2772+ requirement_type .finalize (context )
2773+ logger .debug ("Finalizing requirement types: completed" )
2774+
27312775 def notify (self , event : Union [Event , EventType ]):
27322776 """ Override notify to update statistics """
27332777 assert self .__current_context__ is not None , "No current validation context"
0 commit comments