View Javadoc
1   package com.github.mygreen.supercsv.validation;
2   
3   import java.io.Serializable;
4   import java.util.ArrayList;
5   import java.util.Collection;
6   import java.util.Collections;
7   import java.util.List;
8   import java.util.Map;
9   import java.util.Objects;
10  
11  import com.github.mygreen.supercsv.util.ArgUtils;
12  import com.github.mygreen.supercsv.util.Utils;
13  
14  /**
15   * CSVのエラー情報を管理するためのクラス。
16   * <p>SpringFrameworkのBindingResultを参考。</p>
17   * <p>現状、ネストしたフィールドはサポートしていないため、パスの機能を省略して実装する。</p>
18   *
19   * @version 2.2
20   * @since 2.0
21   * @author T.TSUCHIE
22   *
23   */
24  public class CsvBindingErrors implements Serializable {
25      
26      /** serialVersionUID */
27      private static final long serialVersionUID = -9014484172903397334L;
28      
29      /** パスの区切り文字 */
30      public static final String PATH_SEPARATOR = ".";
31      
32      /** オブジェクト名 */
33      private final String objectName;
34      
35      /** エラーオブジェクト */
36      private final List<CsvError> errors = new ArrayList<>();
37      
38      /** エラーコードの候補を生成するクラス */
39      private MessageCodeGeneratorerator.html#MessageCodeGenerator">MessageCodeGenerator messageCodeGenerator = new MessageCodeGenerator();
40      
41      /**
42       * オブジェクト名を指定するコンストラクタ。
43       * @param objectName メッセージオブジェクトを構成する際に、自動的に付与する名称。
44       * @throws NullPointerException {@link objectName is null.}
45       */
46      public CsvBindingErrors(final String objectName) {
47          Objects.requireNonNull(objectName);
48          this.objectName = objectName;
49      }
50      
51      /**
52       * クラス名を元にオブジェクト名を設定するコンストラクタ。
53       * @param clazz 検証対象のBeanのクラスタイプ。
54       */
55      public CsvBindingErrors(final Class<?> clazz) {
56          this(clazz.getSimpleName());
57      }
58      
59      /**
60       * オブジェクト名の取得
61       * @return コンストラクタで設定したオブジェクト名を取得する。
62       */
63      public String getObjectName() {
64          return objectName;
65      }
66      
67      /**
68       * 全てのエラー情報を取得する。
69       * @return 現在のエラー情報
70       */
71      public List<CsvError> getAllErrors() {
72          return new ArrayList<>(errors);
73      }
74      
75      /**
76       * エラーを追加する
77       * @param error
78       */
79      public void addError(final CsvError error) {
80          this.errors.add(error);
81      }
82      
83      /**
84       * 全てのエラー情報を追加する。
85       * @param errors 追加するエラー情報。
86       */
87      public void addAllErrors(Collection<CsvError> errors) {
88          this.errors.addAll(errors);
89      }
90      
91      /**
92       * 全てのエラー情報を削除する。
93       */
94      public void clearAllErrors() {
95          this.errors.clear();
96      }
97      
98      /**
99       * エラー情報が存在するかどうか確かめる。
100      * @return trueの場合、エラー情報が存在する。
101      */
102     public boolean hasErrors() {
103         return !errors.isEmpty();
104     }
105     
106     /**
107      * グローバルエラーを取得する
108      * @return エラーがない場合は空のリストを返す
109      */
110     public List<CsvError> getGlobalErrors() {
111         final List<CsvError> list = new ArrayList<CsvError>();
112         for(CsvError item : this.errors) {
113             if(!(item instanceof CsvFieldError)) {
114                 list.add(item);
115             }
116         }
117         
118         return list;
119     }
120     
121     /**
122      * 先頭のグローバルエラーを取得する。
123      * @return 存在しない場合は、nullを返す。
124      */
125     public CsvError getFirstGlobalError() {
126         for(CsvError item : this.errors) {
127             if(!(item instanceof CsvFieldError)) {
128                 return item;
129             }
130         }
131         
132         return null;
133     }
134     
135     /**
136      * グローバルエラーがあるか確かめる。
137      * @return
138      */
139     public boolean hasGlobalErrors() {
140         return !getGlobalErrors().isEmpty();
141     }
142     
143     /**
144      * グローバルエラーの件数を取得する
145      * @return
146      */
147     public int getGlobalErrorCount() {
148         return getGlobalErrors().size();
149     }
150     
151     /**
152      * フィールドエラーを取得する
153      * @return エラーがない場合は空のリストを返す
154      */
155     public List<CsvFieldError> getFieldErrors() {
156         final List<CsvFieldError> list = new ArrayList<CsvFieldError>();
157         for(CsvError item : this.errors) {
158             if(item instanceof CsvFieldError) {
159                 list.add((CsvFieldError) item);
160             }
161         }
162         
163         return list;
164     }
165     
166     /**
167      * 先頭のフィールドエラーを取得する
168      * @return エラーがない場合は空のリストを返す
169      */
170     public CsvFieldError getFirstFieldError() {
171         for(CsvError item : this.errors) {
172             if(item instanceof CsvFieldError) {
173                 return (CsvFieldError) item;
174             }
175         }
176         
177         return null;
178     }
179     
180     /**
181      * フィールドエラーが存在するか確かめる。
182      * @return true:フィールドエラーを持つ。
183      */
184     public boolean hasFieldErrors() {
185         return !getFieldErrors().isEmpty();
186     }
187     
188     /**
189      * フィールドエラーの件数を取得する。
190      * @return
191      */
192     public int getFieldErrorCount() {
193         return getFieldErrors().size();
194     }
195     
196     /**
197      * パスを指定してフィールドエラーを取得する
198      * @param path 最後に'*'を付けるとワイルドカードが指定可能。
199      * @return
200      * @throws IllegalArgumentException {@literal if path is empty.}
201      */
202     public List<CsvFieldError> getFieldErrors(final String path) {
203         ArgUtils.notEmpty(path, "path");
204         
205         final List<CsvFieldError> list = new ArrayList<CsvFieldError>();
206         for(CsvError item : this.errors) {
207             if(item instanceof CsvFieldErrorpercsv/validation/CsvFieldError.html#CsvFieldError">CsvFieldError && isMatchingFieldError(path, (CsvFieldError) item)) {
208                 list.add((CsvFieldError) item);
209             }
210         }
211         
212         return list;
213     }
214     
215     /**
216      * パスを指定して先頭のフィールドエラーを取得する
217      * @param path 最後に'*'を付けるとワイルドカードが指定可能。
218      * @return エラーがない場合は空のリストを返す
219      */
220     public CsvFieldError getFirstFieldError(final String path) {
221         ArgUtils.notEmpty(path, "path");
222         
223         for(CsvError item : this.errors) {
224             if(item instanceof CsvFieldErrorpercsv/validation/CsvFieldError.html#CsvFieldError">CsvFieldError && isMatchingFieldError(path, (CsvFieldError) item)) {
225                 return (CsvFieldError) item;
226             }
227         }
228         
229         return null;
230     }
231     
232     /**
233      * 指定したパスのフィィールドエラーが存在するか確かめる。
234      * @param path 最後に'*'を付けるとワイルドカードが指定可能。
235      * @return true:エラーがある場合。
236      */
237     public boolean hasFieldErrors(final String path) {
238         return !getFieldErrors(path).isEmpty();
239     }
240     
241     /**
242      * 指定したパスのフィィールドエラーの件数を取得する。
243      * @param path 最後に'*'を付けるとワイルドカードが指定可能。
244      * @return
245      */
246     public int getFieldErrorCount(final String path) {
247         return getFieldErrors(path).size();
248     }
249     
250     /**
251      * 指定したパスがフィールドエラーのパスと一致するかチェックするかどうか。
252      * @param path 
253      * @param fieldError
254      * @return true: 一致する場合。
255      */
256     private boolean isMatchingFieldError(final String path, final CsvFieldError fieldError) {
257         
258         if (fieldError.getField().equals(path)) {
259             return true;
260         }
261         
262         if(path.endsWith("*")) {
263             String subPath = path.substring(0, path.length()-1);
264             return fieldError.getField().startsWith(subPath);
265         }
266         
267         return false;
268     }
269     
270     /**
271      * グローバルエラーを登録する。
272      * @param errorCode エラーコード
273      */
274     public void reject(final String errorCode) {
275         reject(errorCode, Collections.emptyMap(), null);
276     }
277     
278     /**
279      * グローバルエラーを登録する。
280      * @param errorCode エラーコード
281      * @param defaultMessage 指定したエラーコードに対するメッセージが見つからないときに使用するメッセージです。指定しない場合はnullを設定します。
282      */
283     public void reject(final String errorCode, final String defaultMessage) {
284         reject(errorCode, Collections.emptyMap(), defaultMessage);
285     }
286     
287     /**
288      * グローバルエラーを登録する。
289      * @param errorCode エラーコード
290      * @param messageVariables メッセージ中の変数。
291      */
292     public void reject(final String errorCode, final Map<String, Object> messageVariables) {
293         reject(errorCode, messageVariables, null);
294     }
295     
296     /**
297      * グローバルエラーを登録する。
298      * @param errorCode エラーコード
299      * @param messageVariables メッセージ中の変数。
300      * @param defaultMessage 指定したエラーコードに対するメッセージが見つからないときに使用するメッセージです。指定しない場合はnullを設定します。
301      */
302     public void reject(final String errorCode, final Map<String, Object> messageVariables, final String defaultMessage) {
303         reject(new String[]{errorCode}, messageVariables, defaultMessage);
304     }
305     
306     /**
307      * グローバルエラーを登録する。
308      * @since 2.2
309      * @param errorCodes エラーコード
310      * @param messageVariables メッセージ中の変数。
311      * @param defaultMessage 指定したエラーコードに対するメッセージが見つからないときに使用するメッセージです。指定しない場合はnullを設定します。
312      */
313     public void reject(final String[] errorCodes, final Map<String, Object> messageVariables, final String defaultMessage) {
314         
315         String[] codes = new String[0];
316         for(String errorCode : errorCodes) {
317             codes = Utils.concat(codes, messageCodeGenerator.generateCodes(errorCode, getObjectName()));
318         }
319         addError(new CsvError(getObjectName(), codes, messageVariables, defaultMessage));
320     }
321     
322     /**
323      * フィールドエラーを登録します。
324      * @param field フィールドパス。
325      * @param errorCode エラーコード。
326      */
327     public void rejectValue(final String field, final String errorCode) {
328         rejectValue(field, null, errorCode, Collections.emptyMap(), null);
329         
330     }
331     
332     /**
333      * フィールドエラーを登録します。
334      * @param field フィールドパス。
335      * @param errorCode エラーコード。
336      * @param defaultMessage 指定したエラーコードに対するメッセージが見つからないときに使用するメッセージです。指定しない場合はnullを設定します。
337      */
338     public void rejectValue(final String field, final String errorCode, final String defaultMessage) {
339         rejectValue(field, null, errorCode, Collections.emptyMap(), defaultMessage);
340         
341     }
342     
343     /**
344      * フィールドエラーを登録します。
345      * @param field フィールドパス。
346      * @param errorCode エラーコード。
347      * @param messageVariables メッセージ中の変数。
348      * @param defaultMessage 指定したエラーコードに対するメッセージが見つからないときに使用するメッセージです。指定しない場合はnullを設定します。
349      */
350     public void rejectValue(final String field, final String errorCode, 
351             final Map<String, Object> messageVariables, final String defaultMessage) {
352         
353         rejectValue(field, null, errorCode, Collections.emptyMap(), defaultMessage);
354         
355     }
356     
357     /**
358      * フィールドエラーを登録します。
359      * @param field フィールドパス。
360      * @param fieldType フィールドのタイプ
361      * @param errorCode エラーコード。
362      * @param messageVariables メッセージ中の変数。
363      */
364     public void rejectValue(final String field, final Class<?> fieldType, final String errorCode, 
365             final Map<String, Object> messageVariables) {
366         
367         rejectValue(field, fieldType, errorCode, messageVariables, null);
368         
369     }
370     
371     /**
372      * フィールドエラーを登録します。
373      * @param field フィールドパス。
374      * @param fieldType フィールドのタイプ
375      * @param errorCode エラーコード。
376      * @param messageVariables メッセージ中の変数。
377      * @param defaultMessage 指定したエラーコードに対するメッセージが見つからないときに使用するメッセージです。指定しない場合はnullを設定します。
378      */
379     public void rejectValue(final String field, final Class<?> fieldType, final String errorCode, 
380             final Map<String, Object> messageVariables, final String defaultMessage) {
381         
382         rejectValue(field, fieldType, new String[]{errorCode}, messageVariables, defaultMessage);
383     }
384     
385     /**
386      * フィールドエラーを登録します。
387      * @since 2.2
388      * @param field フィールドパス。
389      * @param fieldType フィールドのタイプ
390      * @param errorCodes エラーコード。
391      * @param messageVariables メッセージ中の変数。
392      * @param defaultMessage 指定したエラーコードに対するメッセージが見つからないときに使用するメッセージです。指定しない場合はnullを設定します。
393      */
394     public void rejectValue(final String field, final Class<?> fieldType, final String[] errorCodes, 
395             final Map<String, Object> messageVariables, final String defaultMessage) {
396         
397         String[] codes = new String[0];
398         for(String errorCode : errorCodes) {
399             codes = Utils.concat(codes, messageCodeGenerator.generateCodes(errorCode, getObjectName(), field, fieldType));
400         }
401         
402         addError(new CsvFieldError(getObjectName(), field, false, codes, messageVariables, defaultMessage));
403         
404     }
405     
406     public MessageCodeGenerator getMessageCodeGenerator() {
407         return messageCodeGenerator;
408     }
409     
410     public void setMessageCodeGenerator(MessageCodeGenerator messageCodeGenerator) {
411         this.messageCodeGenerator = messageCodeGenerator;
412     }
413     
414     
415 }