3535import br .com .fluentvalidator .rule .RuleProcessorStrategy ;
3636import br .com .fluentvalidator .transform .ValidationResultTransform ;
3737
38+ /**
39+ * Abstract base class for implementing fluent validators.
40+ * <p>
41+ * This class provides the core functionality for building and executing validation rules
42+ * in a fluent, chainable manner. It supports both single object and collection validation,
43+ * with configurable processing strategies including fail-fast behavior.
44+ * </p>
45+ * <p>
46+ * Subclasses should implement the {@link Validator#rules()} method to define
47+ * validation rules using the fluent API provided by {@link #ruleFor(Function)} and
48+ * {@link #ruleForEach(Function)} methods.
49+ * </p>
50+ * <p>
51+ * Thread Safety: This class is thread-safe for validation operations. Rule initialization
52+ * is performed using double-checked locking with atomic references to prevent race conditions.
53+ * </p>
54+ *
55+ * @param <T> the type of object being validated
56+ */
3857public abstract class AbstractValidator <T > implements Validator <T > {
3958
59+ /**
60+ * List of validation rules to be applied to instances of type T.
61+ * Rules are executed in the order they were added.
62+ */
4063 private final List <Rule <T >> rules = new LinkedList <>();
4164
65+ /**
66+ * Initializer responsible for thread-safe rule initialization.
67+ */
4268 private final Initializer <T > initialize ;
4369
70+ /**
71+ * Property name to be set in the validation context during validation.
72+ */
4473 private String property ;
4574
75+ /**
76+ * Strategy for processing validation rules. Defaults to standard processing,
77+ * but can be changed to fail-fast mode.
78+ */
4679 private RuleProcessorStrategy ruleProcessor = RuleProcessorStrategy .getDefault ();
4780
81+ /**
82+ * Thread-safe initializer for validation rules.
83+ * <p>
84+ * This inner class ensures that validation rules are initialized exactly once
85+ * per validator instance, even in multi-threaded environments. It uses
86+ * Compare-And-Swap (CAS) operations with double-checked locking to prevent
87+ * race conditions during initialization.
88+ * </p>
89+ *
90+ * @param <T> the type of object being validated
91+ */
4892 private static class Initializer <T > {
49-
93+ /**
94+ * Atomic reference to track initialization state.
95+ * FALSE indicates not initialized, TRUE indicates initialized.
96+ */
5097 private final AtomicReference <Boolean > atomicReference = new AtomicReference <>(Boolean .FALSE );
5198
99+ /**
100+ * Reference to the validator instance being initialized.
101+ */
52102 private final Validator <T > validator ;
53103
104+ /**
105+ * Constructs a new initializer for the given validator.
106+ *
107+ * @param validator the validator instance to initialize
108+ */
54109 Initializer (final Validator <T > validator ) {
55110 this .validator = validator ;
56111 }
57112
58113 /**
59- * This method cause Race Condition. We are using Compare And Swap (CAS)
114+ * Initializes the validator rules in a thread-safe manner.
115+ * <p>
116+ * This method uses double-checked locking with atomic operations to ensure
117+ * that the validator's rules are initialized exactly once, even when called
118+ * concurrently from multiple threads. This prevents race conditions that
119+ * could occur during rule initialization.
120+ * </p>
60121 * <p>
61- * {@link https://en.wikipedia.org/wiki/Race_condition}
62- * {@link https://en.wikipedia.org/wiki/Compare-and-swap}
122+ * The implementation follows the Compare-And-Swap (CAS) pattern for
123+ * lock-free programming where possible, falling back to synchronized
124+ * blocks only when necessary.
125+ * </p>
126+ *
127+ * @see <a href="https://en.wikipedia.org/wiki/Race_condition">Race Condition</a>
128+ * @see <a href="https://en.wikipedia.org/wiki/Compare-and-swap">Compare-and-swap</a>
63129 */
64130 public void init () {
65131 if (isNotInitialized ()) {
@@ -74,50 +140,102 @@ public void init() {
74140 }
75141 }
76142
143+ /**
144+ * Checks if the validator has not been initialized yet.
145+ *
146+ * @return true if the validator is not initialized, false otherwise
147+ */
77148 private boolean isNotInitialized () {
78149 return Boolean .FALSE .equals (atomicReference .get ());
79150 }
80151
81152 }
82153
154+ /**
155+ * Constructs a new AbstractValidator instance.
156+ * <p>
157+ * Initializes the validator with default settings and creates
158+ * the thread-safe initializer for rule setup.
159+ * </p>
160+ */
83161 protected AbstractValidator () {
84162 this .initialize = new Initializer <>(this );
85163 }
86164
87165 /**
88- * {@link #failFastRule() AbstractValidator}
166+ * Configures the validator to use fail-fast rule processing.
167+ * <p>
168+ * When fail-fast mode is enabled, validation will stop at the first
169+ * rule failure instead of continuing to evaluate all rules. This can
170+ * improve performance when early validation failure is acceptable.
171+ * </p>
172+ *
173+ * @see RuleProcessorStrategy#getFailFast()
89174 */
90175 @ Override
91176 public void failFastRule () {
92177 this .ruleProcessor = RuleProcessorStrategy .getFailFast ();
93178 }
94179
95180 /**
96- * {@link #getCounter() AbstractValidator}
181+ * Gets the current validation counter from the processor context.
182+ * <p>
183+ * The counter tracks the number of validation operations or rules
184+ * that have been processed. This can be useful for debugging,
185+ * monitoring, or performance analysis.
186+ * </p>
187+ *
188+ * @return the current counter value, or null if no counter is available
97189 */
98190 @ Override
99191 public Integer getCounter () {
100192 return ProcessorContext .get ().get ();
101193 }
102194
103195 /**
104- * {@link #setPropertyOnContext(String) AbstractValidator }
196+ * Sets a property name to be used in the validation context.
197+ * <p>
198+ * This property name will be associated with the validated object
199+ * in the validation context, allowing rules to access contextual
200+ * information during validation.
201+ * </p>
202+ *
203+ * @param property the property name to set in the validation context
105204 */
106205 @ Override
107206 public void setPropertyOnContext (final String property ) {
108207 this .property = property ;
109208 }
110209
111210 /**
112- * {@link #getPropertyOnContext(String, Class) AbstractValidator }
211+ * Retrieves a property value from the validation context.
212+ * <p>
213+ * This method allows access to contextual information that was
214+ * previously stored in the validation context, enabling rules
215+ * to make decisions based on broader validation state.
216+ * </p>
217+ *
218+ * @param <P> the type of the property value
219+ * @param property the name of the property to retrieve
220+ * @param clazz the class type of the property value
221+ * @return the property value cast to the specified type, or null if not found
113222 */
114223 @ Override
115224 public <P > P getPropertyOnContext (final String property , final Class <P > clazz ) {
116225 return ValidationContext .get ().getProperty (property , clazz );
117226 }
118227
119228 /**
120- * {@link #validate(Object) AbstractValidator }
229+ * Validates a single instance and returns the validation result.
230+ * <p>
231+ * This method processes the given instance through all configured
232+ * validation rules and returns a comprehensive result containing
233+ * any validation errors or success indicators.
234+ * </p>
235+ *
236+ * @param instance the object instance to validate
237+ * @return a ValidationResult containing the outcome of validation
238+ * @throws IllegalArgumentException if the instance is null and null values are not supported
121239 */
122240 @ Override
123241 public ValidationResult validate (final T instance ) {
@@ -126,31 +244,69 @@ public ValidationResult validate(final T instance) {
126244 }
127245
128246 /**
129- * {@link #validate(Object, ValidationResultTransform) AbstractValidator}
247+ * Validates a single instance and transforms the result using the provided transformer.
248+ * <p>
249+ * This method combines validation with result transformation in a single operation,
250+ * allowing for custom result formats or processing without intermediate objects.
251+ * </p>
252+ *
253+ * @param <E> the type of the transformed result
254+ * @param instance the object instance to validate
255+ * @param resultTransform the transformer to apply to the validation result
256+ * @return the transformed validation result
257+ * @throws IllegalArgumentException if the instance is null and null values are not supported
258+ * @throws NullPointerException if resultTransform is null
130259 */
131260 @ Override
132261 public <E > E validate (final T instance , final ValidationResultTransform <E > resultTransform ) {
133262 return resultTransform .transform (validate (instance ));
134263 }
135264
136265 /**
137- * {@link #validate(Collection) AbstractValidator}
266+ * Validates a collection of instances and returns a list of validation results.
267+ * <p>
268+ * Each instance in the collection is validated independently, and the results
269+ * are collected into an unmodifiable list. The order of results corresponds
270+ * to the order of instances in the input collection.
271+ * </p>
272+ *
273+ * @param instances the collection of instances to validate
274+ * @return an unmodifiable list of ValidationResult objects, one for each input instance
275+ * @throws NullPointerException if the instances collection is null
138276 */
139277 @ Override
140278 public List <ValidationResult > validate (final Collection <T > instances ) {
141279 return Collections .unmodifiableList (instances .stream ().map (this ::validate ).collect (Collectors .toList ()));
142280 }
143281
144282 /**
145- * {@link #validate(Collection, ValidationResultTransform) AbstractValidator}
283+ * Validates a collection of instances and transforms each result using the provided transformer.
284+ * <p>
285+ * This method combines collection validation with result transformation,
286+ * applying the transformer to each individual validation result.
287+ * </p>
288+ *
289+ * @param <E> the type of the transformed results
290+ * @param instances the collection of instances to validate
291+ * @param resultTransform the transformer to apply to each validation result
292+ * @return an unmodifiable list of transformed validation results
293+ * @throws NullPointerException if instances or resultTransform is null
146294 */
147295 @ Override
148296 public <E > List <E > validate (final Collection <T > instances , final ValidationResultTransform <E > resultTransform ) {
149297 return Collections .unmodifiableList (instances .stream ().map (instance -> this .validate (instance , resultTransform )).collect (Collectors .toList ()));
150298 }
151299
152300 /**
153- * {@link #apply(Object) AbstractValidator}
301+ * Applies validation rules to an instance and returns a boolean result.
302+ * <p>
303+ * This method is typically called internally during the validation process.
304+ * It ensures rules are initialized, sets up the validation context, and
305+ * processes all rules against the given instance.
306+ * </p>
307+ *
308+ * @param instance the object instance to validate
309+ * @return true if all validation rules pass, false if any rule fails
154310 */
155311 @ Override
156312 public boolean apply (final T instance ) {
@@ -160,7 +316,17 @@ public boolean apply(final T instance) {
160316 }
161317
162318 /**
163- * {@link #ruleFor(Function) AbstractValidator}
319+ * Creates a validation rule for a specific property of the validated object.
320+ * <p>
321+ * This method starts a fluent chain for defining validation rules that apply
322+ * to a property extracted from the validated object using the provided function.
323+ * The property name will be automatically derived from the function if possible.
324+ * </p>
325+ *
326+ * @param <P> the type of the property being validated
327+ * @param function a function that extracts the property value from the validated object
328+ * @return a RuleBuilderProperty for chaining additional validation constraints
329+ * @throws NullPointerException if function is null
164330 */
165331 @ Override
166332 public <P > RuleBuilderProperty <T , P > ruleFor (final Function <T , P > function ) {
@@ -170,7 +336,19 @@ public <P> RuleBuilderProperty<T, P> ruleFor(final Function<T, P> function) {
170336 }
171337
172338 /**
173- * {@link #ruleFor(String, Function) AbstractValidator}
339+ * Creates a validation rule for a named property of the validated object.
340+ * <p>
341+ * This method starts a fluent chain for defining validation rules that apply
342+ * to a property extracted from the validated object. The field name is explicitly
343+ * provided and will be used in error messages and validation context.
344+ * </p>
345+ *
346+ * @param <P> the type of the property being validated
347+ * @param fieldName the name of the field being validated (used in error messages)
348+ * @param function a function that extracts the property value from the validated object
349+ * @return a RuleBuilderProperty for chaining additional validation constraints
350+ * @throws NullPointerException if fieldName or function is null
351+ * @throws IllegalArgumentException if fieldName is empty
174352 */
175353 @ Override
176354 public <P > RuleBuilderProperty <T , P > ruleFor (final String fieldName , final Function <T , P > function ) {
@@ -180,7 +358,19 @@ public <P> RuleBuilderProperty<T, P> ruleFor(final String fieldName, final Funct
180358 }
181359
182360 /**
183- * {@link #ruleForEach(String, Function) AbstractValidator}
361+ * Creates validation rules for each element in a collection property.
362+ * <p>
363+ * This method starts a fluent chain for defining validation rules that apply
364+ * to each element of a collection extracted from the validated object.
365+ * The field name is explicitly provided for error reporting.
366+ * </p>
367+ *
368+ * @param <P> the type of elements in the collection being validated
369+ * @param fieldName the name of the collection field being validated
370+ * @param function a function that extracts the collection from the validated object
371+ * @return a RuleBuilderCollection for chaining additional validation constraints
372+ * @throws NullPointerException if fieldName or function is null
373+ * @throws IllegalArgumentException if fieldName is empty
184374 */
185375 @ Override
186376 public <P > RuleBuilderCollection <T , P > ruleForEach (final String fieldName , final Function <T , Collection <P >> function ) {
@@ -190,7 +380,17 @@ public <P> RuleBuilderCollection<T, P> ruleForEach(final String fieldName, final
190380 }
191381
192382 /**
193- * {@link #ruleForEach(Function) AbstractValidator}
383+ * Creates validation rules for each element in a collection property.
384+ * <p>
385+ * This method starts a fluent chain for defining validation rules that apply
386+ * to each element of a collection extracted from the validated object.
387+ * The field name will be automatically derived from the function if possible.
388+ * </p>
389+ *
390+ * @param <P> the type of elements in the collection being validated
391+ * @param function a function that extracts the collection from the validated object
392+ * @return a RuleBuilderCollection for chaining additional validation constraints
393+ * @throws NullPointerException if function is null
194394 */
195395 @ Override
196396 public <P > RuleBuilderCollection <T , P > ruleForEach (final Function <T , Collection <P >> function ) {
0 commit comments