View Javadoc
1   package com.opencsv.validators;
2   
3   import com.opencsv.exceptions.CsvValidationException;
4   
5   import java.util.function.Function;
6   
7   /**
8    * This validator is best used to validate a specific property of the row - either about a specific
9    * element or information about the array itself.
10   * <p>An empty or null first row is considered invalid.</p>
11   * <p>As with all row validators the assumption is you have control of the data and have skipped any initial
12   * empty lines AND that your validator checks the size or handles the IndexOutOfBoundsException.</p>
13   * <p>There are several examples coded in the RowFunctionValidatorTest but here are a couple to give you the
14   * idea of the flexibility this validator offers.</p>
15   *
16   * <pre>{@code
17   *     private static final String[] GOOD_ROW = {"8675309", "Firstname", "M", "Lastname", "Dec 06, 1951"};
18   *     private static final String[] BAD_ROW = {"not a number", "not capitialized", "not an initial", "Not Single word", "12/06/51"};
19   *     private static final String[] LONG_ROW = {"8675309", "Firstname", "M", "Lastname", "Dec 06, 1951", "More data"};
20   *     private static final String[] SHORT_ROW = {"8675309", "Firstname", "Lastname", "Dec 06, 1951"};
21   *
22   *     private static final Function<String[], Boolean> THIRD_ELEMENT_IS_MIDDLE_INITIAL = (x) -> {
23   *         return x.length > 2 && x[2].matches("^[A-Z]$");
24   *     };
25   *
26   *     private static final Function<String[], Boolean> ROW_MUST_HAVE_FIVE_ELEMENTS = (x) -> {
27   *         return (x.length == 5);
28   *     };
29   * }
30   * {@code    @Test}
31   * {@code    @DisplayName("Simple test to show checking an middle initial")}
32   * {@code    public void thirdElementIsMiddleInitial() {
33   *         validator = new RowFunctionValidator(THIRD_ELEMENT_IS_MIDDLE_INITIAL, "The third element must be the middle initial.");
34   *
35   *         assertTrue(validator.isValid(GOOD_ROW));
36   *         assertFalse(validator.isValid(BAD_ROW));
37   *     }
38   * }
39   * {@code    @Test}
40   * {@code    @DisplayName("The row must have a specific number of elements in order to be valid.")}
41   * {@code    public void numberOfElementsInARow() {
42   *         validator = new RowFunctionValidator(ROW_MUST_HAVE_FIVE_ELEMENTS, "A Row can have only five elements.");
43   *
44   *         assertTrue(validator.isValid(GOOD_ROW));
45   *         assertFalse(validator.isValid(LONG_ROW));
46   *         assertFalse(validator.isValid(SHORT_ROW));
47   *     }
48   * }</pre>
49   *
50   * @author Scott Conway
51   * @since 5.0
52   */
53  
54  public class RowFunctionValidator implements RowValidator {
55      private Function<String[], Boolean> testFunction;
56      private String failureMessage;
57  
58      /**
59       * Default Constructor.
60       *
61       * @param testFunction   - function to run against the Array of Strings.
62       * @param failureMessage - message to be included in the CsvValidationException error message.
63       */
64      public RowFunctionValidator(Function<String[], Boolean> testFunction, String failureMessage) {
65          this.testFunction = testFunction;
66          this.failureMessage = failureMessage;
67      }
68  
69      @Override
70      public boolean isValid(String[] row) {
71          if (row == null || row.length == 0) {
72              return false;
73          }
74          return testFunction.apply(row);
75      }
76  
77      @Override
78      public void validate(String[] row) throws CsvValidationException {
79          if (!isValid(row)) {
80              throw new CsvValidationException(failureMessage);
81          }
82      }
83  }