Interface EntityValidator

All Known Implementing Classes:
DefaultEntityValidator

public interface EntityValidator
Responsible for providing validation for entities.

Entity validators enforce business rules and data integrity constraints beyond basic database constraints. They validate entity values before insert/update operations and can provide context-aware validation that considers the entity's current state and relationships.

Custom validators can be implemented for complex business logic:

// Custom validator for Customer entity
public class CustomerValidator implements EntityValidator {

    @Override
    public boolean valid(Entity customer) {
        try {
            validate(customer);
            return true;
        } catch (ValidationException e) {
            return false;
        }
    }

    @Override
    public void validate(Entity customer) throws ValidationException {
        // Validate email format
        String email = customer.get(Customer.EMAIL);
        if (email != null && !isValidEmail(email)) {
            throw new ValidationException("Invalid email format: " + email);
        }

        // Business rule: Active customers must have email
        Boolean active = customer.get(Customer.ACTIVE);
        if (Boolean.TRUE.equals(active) &&
            (email == null || email.trim().isEmpty())) {
            throw new ValidationException("Active customers must have an email address");
        }

        // Age validation
        LocalDate birthDate = customer.get(Customer.BIRTH_DATE);
        if (birthDate != null && birthDate.isAfter(LocalDate.now().minusYears(13))) {
            throw new ValidationException("Customer must be at least 13 years old");
        }
    }

    @Override
    public <T> void validate(Entity customer, Attribute<T> attribute)
            throws ValidationException {
        T value = customer.get(attribute);

        if (attribute.equals(Customer.EMAIL)) {
            String email = (String) value;
            if (email != null && !isValidEmail(email)) {
                throw new ValidationException("Invalid email format");
            }
        }
        // Additional attribute-specific validation...
    }

    private boolean isValidEmail(String email) {
        return email.contains("@") && email.contains(".");
    }
}

// Usage in domain definition
Customer.TYPE.define(
        Customer.EMAIL.define()
            .column(),
        Customer.ACTIVE.define()
            .column(),
        Customer.BIRTH_DATE.define()
            .column())
    .validator(new CustomerValidator())
    .build();
See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final PropertyValue<Boolean>
    Specifies whether the default validator performs strict validation or not.
  • Method Summary

    Modifier and Type
    Method
    Description
    <T> boolean
    nullable(Entity entity, Attribute<T> attribute)
    Returns true if the value based on the given attribute accepts a null value for the given entity, by default this method simply returns the nullable state of the underlying attribute.
    boolean
    valid(Entity entity)
    Returns true if the given entity contains only valid values.
    void
    validate(Entity entity)
    Checks if the values in the given entity are valid.
    <T> void
    validate(Entity entity, Attribute<T> attribute)
    Checks if the value associated with the give attribute is valid, throws a ValidationException if not
  • Field Details

    • STRICT_VALIDATION

      static final PropertyValue<Boolean> STRICT_VALIDATION
      Specifies whether the default validator performs strict validation or not. By default, all non-read-only attribute values are validated if the entity is being inserted (as in, when it does not exist according to Entity.exists()). If the entity exists, only modified values are validated. With strict validation enabled all values are validated, regardless of whether the entity exists or not
      • Value type: Boolean
      • Default value: false
  • Method Details

    • nullable

      <T> boolean nullable(Entity entity, Attribute<T> attribute)
      Returns true if the value based on the given attribute accepts a null value for the given entity, by default this method simply returns the nullable state of the underlying attribute.
      // Context-aware nullable validation
      public class OrderValidator implements EntityValidator {
      
          @Override
          public <T> boolean nullable(Entity order, Attribute<T> attribute) {
              // Normally nullable, but not for shipped orders
              if (attribute.equals(Order.TRACKING_NUMBER)) {
                  String status = order.get(Order.STATUS);
                  return !"SHIPPED".equals(status); // Tracking number required when shipped
              }
      
              // Use default nullable behavior for other attributes
              return attribute.nullable();
          }
      }
      
      // Usage during validation
      Entity order = entities.builder(Order.TYPE)
          .with(Order.STATUS, "SHIPPED")
          .build(); // No tracking number
      
      boolean canBeNull = validator.nullable(order, Order.TRACKING_NUMBER); // false
      
      Type Parameters:
      T - the value type
      Parameters:
      entity - the entity being validated
      attribute - the attribute
      Returns:
      true if the attribute accepts a null value
    • valid

      boolean valid(Entity entity)
      Returns true if the given entity contains only valid values.
      Parameters:
      entity - the entity
      Returns:
      true if the given entity contains only valid values
    • validate

      void validate(Entity entity) throws ValidationException
      Checks if the values in the given entity are valid. Note that by default, if the entity instance does not exist according to Entity.exists() all values are validated, otherwise only modified values are validated. Use the STRICT_VALIDATION configuration value to change the default behaviour.
      // Validation during entity lifecycle
      Entity customer = entities.builder(Customer.TYPE)
          .with(Customer.NAME, "John Doe")
          .with(Customer.EMAIL, "invalid-email") // Invalid format
          .with(Customer.ACTIVE, true)
          .build();
      
      EntityValidator validator = entities.definition(Customer.TYPE).validator();
      
      try {
          validator.validate(customer);
          // Validation passed
          connection.insert(customer);
      } catch (ValidationException e) {
          // Handle validation error
          System.err.println("Validation failed: " + e.getMessage());
          // e.getMessage() might be: "Invalid email format: invalid-email"
      }
      
      // Check if entity is valid without throwing exception
      if (validator.valid(customer)) {
          connection.insert(customer);
      } else {
          // Handle invalid entity
      }
      
      Parameters:
      entity - the entity
      Throws:
      ValidationException - in case of an invalid value
      See Also:
    • validate

      <T> void validate(Entity entity, Attribute<T> attribute) throws ValidationException
      Checks if the value associated with the give attribute is valid, throws a ValidationException if not
      Type Parameters:
      T - the value type
      Parameters:
      entity - the entity to validate
      attribute - the attribute the value is associated with
      Throws:
      ValidationException - if the given value is not valid for the given attribute