1 package com.opencsv.validators;
2
3 import com.opencsv.exceptions.CsvValidationException;
4
5 import java.util.ArrayList;
6 import java.util.List;
7
8 /**
9 * The aggregator's purpose is to collect multiple {@link RowValidator}s and
10 * run them against a single array of strings.
11 * This way complex validations can be performed.
12 *
13 * @author Scott Conway
14 * @since 5.0
15 */
16 public class RowValidatorAggregator {
17 private static final int CAPACITY = 512;
18 private static final int MULTIPLIER = 3;
19 private List<RowValidator> validators = new ArrayList<>();
20
21 /**
22 * Default constructor.
23 */
24 public RowValidatorAggregator() {
25 }
26
27 /**
28 * Add a validator to the aggregator.
29 *
30 * @param validator Validator to be added.
31 */
32 public void addValidator(RowValidator validator) {
33 if (validator != null) {
34 validators.add(validator);
35 }
36 }
37
38 /**
39 * Runs all {@link RowValidator}s' {@link RowValidator#isValid(String[])}
40 * method against the line.
41 * This is a short circuit: as soon as one validator returns {@code false}
42 * then {@code false} is returned.
43 *
44 * @param row Array of strings to be validated.
45 * @return {@code true} if all validators'
46 * {@link RowValidator#isValid(String[])} methods return {@code true},
47 * {@code false} otherwise.
48 */
49 public boolean isValid(final String[] row) {
50 return validators.stream().allMatch(v -> v.isValid(row));
51 }
52
53 /**
54 * Runs all {@link RowValidator}s' {@link RowValidator#validate(String[])}
55 * methods and if the string array is invalid, then it combines all the
56 * validation error messages in a single CsvValidationException.
57 *
58 * @param row Array of Strings to be validation.
59 * @throws CsvValidationException Thrown if the string is invalid.
60 */
61 public void validate(String[] row) throws CsvValidationException {
62 if (validators.isEmpty()) {
63 return;
64 }
65
66 StringBuilder combinedExceptionMessage = null;
67
68 for (RowValidator validator : validators) {
69 try {
70 validator.validate(row);
71 } catch (CsvValidationException ex) {
72 if (combinedExceptionMessage == null) {
73 int length = (ex.getMessage().length() + 2) * MULTIPLIER;
74 combinedExceptionMessage = new StringBuilder(Math.max(length, CAPACITY));
75 }
76 combinedExceptionMessage.append(ex.getMessage()).append("\n");
77 }
78 }
79
80 if (combinedExceptionMessage != null && combinedExceptionMessage.length() > 0) {
81 throw new CsvValidationException(combinedExceptionMessage.toString());
82 }
83 }
84
85 /**
86 * Setter created for unit test.
87 *
88 * @param validators - list of validators to use.
89 */
90 void setValidators(List<RowValidator> validators) {
91 this.validators = validators;
92 }
93 }