|
1 | 1 | # tosan-validation |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +Tosan Validation is a Java library for field validation using Hibernate Validator. It extends Jakarta Validation with custom validators for Iranian-specific validations (national codes, IBAN, mobile numbers, Jalali dates) and advanced validation features. |
| 6 | + |
| 7 | +**Key Dependencies:** |
| 8 | +- Java 17 |
| 9 | +- Hibernate Validator |
| 10 | +- Jakarta Validation API |
| 11 | +- jalali-calendar (for Persian date support) |
| 12 | + |
| 13 | +## Architecture |
| 14 | + |
| 15 | +### Core Validation Framework |
| 16 | + |
| 17 | +The library builds on top of Jakarta Validation/Hibernate Validator with three key architectural patterns: |
| 18 | + |
| 19 | +1. **Parameter Injection via Properties File**: Validators can reference dynamic values from a `validation-key-value.properties` file. This allows validation rules to be configurable without code changes. |
| 20 | + |
| 21 | +2. **ValidatorBuilder Pattern**: Entry point for creating validator instances. Located in `com.tosan.validation.core.ValidatorBuilder`, it: |
| 22 | + - Loads parameters from properties files or maps |
| 23 | + - Configures a custom `CustomMessageInterpolator` for parameter substitution |
| 24 | + - Sets up `MapAwareValidatorFactory` to inject parameters into validators |
| 25 | + - Returns a fully configured Jakarta `Validator` instance |
| 26 | + |
| 27 | +3. **Map-Aware Validation**: Support for validating Map structures dynamically using `@FieldDescriptor` annotations. The `MapAwareValidatorFactory` and `MapAwareValidator` base class enable validators to access external parameters and validator context. |
| 28 | + |
| 29 | +### Package Structure |
| 30 | + |
| 31 | +- **`com.tosan.validation.constraints`**: Annotation definitions for all custom validators |
| 32 | + - Iranian-specific: `@NationalCode`, `@Iban`, `@MobileNumber`, `@Pervasive` |
| 33 | + - Date validations: `@ValidateJalaliDate`, `@PastJalaliDate`, `@FutureJalaliDate`, `@DateDifference` |
| 34 | + - Advanced: `@Expression`, `@Compare`, `@ConditionalNotEmpty`, `@Group` |
| 35 | + |
| 36 | +- **`com.tosan.validation.constraints.impl`**: Validator implementations |
| 37 | + - All validators extend either `BaseValidator` or implement standard Jakarta validation interfaces |
| 38 | + - Many validators inherit from `MapAwareValidator` to access external parameters |
| 39 | + |
| 40 | +- **`com.tosan.validation.core`**: Core framework classes |
| 41 | + - `ValidatorBuilder`: Main entry point for creating validators |
| 42 | + - `MapAwareValidatorFactory`: Custom factory for injecting parameters |
| 43 | + - `FieldDescriptorExtractor*`: Classes for extracting validation metadata from Map structures |
| 44 | + - `CustomMessageInterpolator`: Substitutes parameter placeholders in error messages |
| 45 | + |
| 46 | +- **`com.tosan.validation.util`**: Utilities |
| 47 | + - `ValidationConstraintViolationInfoTreeGenerator`: Generates hierarchical validation error structures |
| 48 | + - `ExpressionUtil`: SPEL expression evaluation for `@Expression` validators |
| 49 | + - `date/`: Date comparison utilities supporting multiple temporal types and Jalali dates |
| 50 | + |
| 51 | +### Key Validation Features |
| 52 | + |
| 53 | +1. **Expression-Based Validation**: `@Expression` and `@Expressions` use Spring Expression Language (SPEL) to evaluate complex conditional validation rules referencing other fields in the object. |
| 54 | + |
| 55 | +2. **Field Comparison**: `@Compare` validates relationships between fields (e.g., endDate > startDate). |
| 56 | + |
| 57 | +3. **Conditional Validation**: `@ConditionalNotEmpty` makes fields required based on conditions. |
| 58 | + |
| 59 | +4. **Map Validation**: `@ValidMap` and `@ValidCollection` with `@FieldDescriptor` enable validation of dynamic Map/Collection structures where field names aren't known at compile time. |
| 60 | + |
| 61 | +5. **Date Difference Validation**: `@DateDifference` validates time spans between two date fields with configurable units (days, months, years). |
| 62 | + |
| 63 | +6. **Group Sequencing**: `@Group` allows conditional validation group execution based on field values. |
| 64 | + |
| 65 | +## Testing |
| 66 | + |
| 67 | +- Tests use TestNG framework (not JUnit) |
| 68 | +- Test files are in `src/test/java/com/tosan/validation/` |
| 69 | +- Test resources (including sample properties) are in `src/test/resource/` |
| 70 | +- Most tests validate constraint violations using the standard Jakarta Validation API pattern |
| 71 | + |
| 72 | +## Release Process |
| 73 | + |
| 74 | +The project uses maven-release-plugin with: |
| 75 | +- Tag format: `v{version}` (e.g., v5.2.5) |
| 76 | +- Release profile for GitHub Packages deployment |
| 77 | +- Build profile for Maven Central with GPG signing |
| 78 | + |
| 79 | +## Important Notes |
| 80 | + |
| 81 | +- Resources are in `src/main/resource` and `src/test/resource` (not the standard `resources` naming) |
| 82 | +- The library expects a `validation-key-value.properties` file in the classpath for parameterized validations (optional, but enables key features) |
| 83 | +- When creating new validators that need external parameters, extend `BaseValidator` or `MapAwareValidator` |
| 84 | +- Custom validators requiring validator context should implement `ValidatorContextAwareConstraintValidator` |
0 commit comments