• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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