1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# 5# Copyright (c) 2025 Northeastern University 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19from typing import List 20from typing import Tuple, Any, Callable 21 22# Type alias for field-level validation: (field_name, field_value, is_required_predicate) 23FieldRequirement = Tuple[str, Any, Callable[[], bool]] 24 25 26class Validator: 27 """A utility class for performing field-level and object-level validations.""" 28 29 @staticmethod 30 def has_value(value: Any) -> bool: 31 """ 32 Checks if a value exists and is non-empty. 33 34 Args: 35 value: The value to check 36 37 Returns: 38 bool: False if the value is None, empty string, or empty collection; True otherwise 39 """ 40 if value is None: 41 return False 42 if isinstance(value, str): 43 return value.strip() != "" 44 if isinstance(value, (list, tuple, dict, set)): 45 return len(value) > 0 46 return True 47 48 @staticmethod 49 def validate_fields(requirements: List[FieldRequirement]) -> None: 50 """ 51 Validates that all required fields have values. 52 53 Args: 54 requirements: List of field requirements where each element is a tuple of: 55 (field_name, field_value, is_required_predicate) 56 57 Raises: 58 ValueError: If any required field is missing or empty 59 60 Example: 61 requirements = [ 62 ("serial_number", serial_number, lambda: True), # required 63 ("lifecycles", lifecycles, lambda: False) # optional 64 ] 65 Validator.validate_fields(requirements) 66 """ 67 missing = [name 68 for name, value, is_required in requirements 69 if is_required() and not Validator.has_value(value)] 70 if missing: 71 raise ValueError(f"Missing required fields: {', '.join(missing)}") 72