View Javadoc
1   package com.github.mygreen.supercsv.validation;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import java.util.Objects;
6   
7   import com.github.mygreen.supercsv.annotation.CsvColumn;
8   import com.github.mygreen.supercsv.builder.ColumnMapping;
9   import com.github.mygreen.supercsv.util.ArgUtils;
10  
11  /**
12   * 独自にフィールドの値を検証する機能を実装する際のヘルパクラス。
13   *
14   * @param <T> フィールドのクラスタイプ。
15   * @since 2.0
16   * @author T.TSUCHIE
17   *
18   */
19  public class CsvField<T> {
20      
21      private final String name;
22      
23      private final T value;
24      
25      private final ColumnMapping columnMapping;
26      
27      private final ValidationContext<?> validationContext;
28      
29      private final List<CsvFieldValidator<T>> validators = new ArrayList<>();
30      
31      /**
32       * 
33       * @param <R> レコードのクラスタイプ。
34       * @param validationContext 入力値検証の情報
35       * @param record レコードオブジェクト
36       * @param fieldName フィールド名
37       * @throws NullPointerException {@literal bindingErrors or validationContext or record is null.}
38       * @throws IllegalArgumentException 指定したフィールドがレコードに存在しない場合。
39       */
40      @SuppressWarnings("unchecked")
41      public <R> CsvField(final ValidationContext<R> validationContext, final R record, final String fieldName) {
42          Objects.requireNonNull(validationContext);
43          Objects.requireNonNull(record);
44          ArgUtils.notEmpty(fieldName, "fieldName");
45          
46          this.columnMapping = validationContext.getBeanMapping().getColumnMapping(fieldName)
47                  .orElseThrow(() -> new IllegalArgumentException(
48                          String.format("not found field '%s' in record '%s'", fieldName, record.getClass().getName())));
49          
50          this.validationContext = validationContext;
51          this.name = fieldName;
52          this.value = (T)columnMapping.getField().getValue(record);
53          
54      }
55      
56      /**
57       * フィールドの名称を取得します。
58       * @return コンストラクタで指定したフィールドの名称。
59       */
60      public String getName() {
61          return name;
62      }
63      
64      /**
65       * フィールドのークラスタイプを取得します。
66       * @return クラス情報を返す。
67       */
68      @SuppressWarnings("unchecked")
69      public Class<T> getType() {
70          return (Class<T>) columnMapping.getField().getType();
71      }
72      
73      /**
74       * フィールドのラベルを取得します。
75       * @return アノテーションの属性{@link CsvColumn#label()}の値を取得します。
76       */
77      public String getLabel() {
78          return columnMapping.getLabel();
79      }
80      
81      /**
82       * フィールドの列番号を取得します。
83       * @return アノテーションの属性{@link CsvColumn#number()}の値を取得します。
84       */
85      public int getColumnNumber() {
86          return columnMapping.getNumber();
87      }
88      
89      /**
90       * フィールドに対するエラーがあるか検査します。
91       * @param bindingErrors エラー情報
92       * @return trueの場合、エラーがあると判定します。
93       * @throws NullPointerException {@literal bindingErrors is null.}
94       */
95      public boolean hasError(final CsvBindingErrors bindingErrors) {
96          Objects.requireNonNull(bindingErrors);
97          return bindingErrors.hasFieldErrors(name);
98      }
99      
100     /**
101      * フィールドに対するエラーがないか検査します。
102      * @see #hasError(CsvBindingErrors)
103      * @param bindingErrors エラー情報
104      * @return trueの場合、エラーがないと判定します。
105      * @throws NullPointerException {@literal bindingErrors is null.}
106      */
107     public boolean hasNotError(final CsvBindingErrors bindingErrors) {
108         return !hasError(bindingErrors);
109     }
110     
111     /**
112      * 値が空かどうか判定します。
113      * <p>基本的に、nullかどうかで判定しますが、文字列型の場合は空文字かどうかでも判定します。
114      * @return trueの場合、空と判定します。
115      */
116     public boolean isEmpty() {
117         if(value == null) {
118             return true;
119         }
120         
121         if(value instanceof String) {
122             return ((String)value).isEmpty();
123         }
124         
125         return false;
126     }
127     
128     /**
129      * 値が空でないかどうか判定します。
130      * @since {@link #isEmpty()}
131      * @return trueの場合、非空と判定します。
132      */
133     public boolean isNotEmpty() {
134         return !isEmpty();
135         
136     }
137     
138     /**
139      * フィールドのバリデータを追加する。
140      * @param validator バリデータ。
141      * @return 自身のインスタンス。
142      * @throws NullPointerException {@literal validator is null.}
143      */
144     public CsvField<T> add(final CsvFieldValidator<T> validator) {
145         Objects.requireNonNull(validator);
146         
147         validators.add(validator);
148         return this;
149     }
150     
151     /**
152      * フィールドの値の検証を行う。
153      * <p>既にエラーがある場合や検証後エラーとなる場合は、その時点で検証を中止する。</p>
154      * @param bindingErrors エラー情報。
155      * @return 自身のインスタンス。
156      * @throws NullPointerException {@literal bindingErrors is null.}
157      */
158     public CsvField<T> validate(final CsvBindingErrors bindingErrors) {
159         Objects.requireNonNull(bindingErrors);
160         
161         for(CsvFieldValidator<T> validator : getValidators()) {
162             if(hasError(bindingErrors)) {
163                 return this;
164             }
165             
166             validator.validate(bindingErrors, this);
167         }
168         
169         return this;
170         
171     }
172     
173     /**
174      * フィールドのエラー情報を取得する。
175      * @param bindingErrors エラー情報
176      * @return エラーがない場合は空のリストを返します。
177      * @throws NullPointerException {@literal bindingErrors is null.}
178      */
179     public List<CsvFieldError> getFieldErrors(final CsvBindingErrors bindingErrors) {
180         Objects.requireNonNull(bindingErrors);
181         return bindingErrors.getFieldErrors(getName());
182     }
183     
184     /**
185      * フィールドの値を取得します。
186      * @return CellProcessorでエラーが発生した場合、値はなくnullを返します。
187      */
188     public T getValue() {
189         return value;
190     }
191     
192     /**
193      * カラムのマッピング情報
194      * @return CsvBeanに定義したカラムのマッピング情報
195      */
196     public ColumnMapping getColumnMapping() {
197         return columnMapping;
198     }
199     
200     /**
201      * 入力値検証の情報
202      * @return コンストラクタで渡した
203      */
204     public ValidationContext<?> getValidationContext() {
205         return validationContext;
206     }
207     
208     /**
209      * フィールドのValidatorの一覧を取得する。
210      * @return 設定されている{@link CsvFieldValidator}のリストを取得する。
211      */
212     public List<CsvFieldValidator<T>> getValidators() {
213         return validators;
214     }
215     
216 }