package com.github.mygreen.supercsv.validation; import java.util.ArrayList; import java.util.List; import java.util.Objects; import com.github.mygreen.supercsv.annotation.CsvColumn; import com.github.mygreen.supercsv.builder.ColumnMapping; import com.github.mygreen.supercsv.util.ArgUtils; /** * 独自にフィールドの値を検証する機能を実装する際のヘルパクラス。 * * @param <T> フィールドのクラスタイプ。 * @since 2.0 * @author T.TSUCHIE * */ public class CsvField<T> { private final String name; private final T value; private final ColumnMapping columnMapping; private final ValidationContext<?> validationContext; private final List<CsvFieldValidator<T>> validators = new ArrayList<>(); /** * * @param <R> レコードのクラスタイプ。 * @param validationContext 入力値検証の情報 * @param record レコードオブジェクト * @param fieldName フィールド名 * @throws NullPointerException {@literal bindingErrors or validationContext or record is null.} * @throws IllegalArgumentException 指定したフィールドがレコードに存在しない場合。 */ @SuppressWarnings("unchecked") public <R> CsvField(final ValidationContext<R> validationContext, final R record, final String fieldName) { Objects.requireNonNull(validationContext); Objects.requireNonNull(record); ArgUtils.notEmpty(fieldName, "fieldName"); this.columnMapping = validationContext.getBeanMapping().getColumnMapping(fieldName) .orElseThrow(() -> new IllegalArgumentException( String.format("not found field '%s' in record '%s'", fieldName, record.getClass().getName()))); this.validationContext = validationContext; this.name = fieldName; this.value = (T)columnMapping.getField().getValue(record); } /** * フィールドの名称を取得します。 * @return コンストラクタで指定したフィールドの名称。 */ public String getName() { return name; } /** * フィールドのークラスタイプを取得します。 * @return クラス情報を返す。 */ @SuppressWarnings("unchecked") public Class<T> getType() { return (Class<T>) columnMapping.getField().getType(); } /** * フィールドのラベルを取得します。 * @return アノテーションの属性{@link CsvColumn#label()}の値を取得します。 */ public String getLabel() { return columnMapping.getLabel(); } /** * フィールドの列番号を取得します。 * @return アノテーションの属性{@link CsvColumn#number()}の値を取得します。 */ public int getColumnNumber() { return columnMapping.getNumber(); } /** * フィールドに対するエラーがあるか検査します。 * @param bindingErrors エラー情報 * @return trueの場合、エラーがあると判定します。 * @throws NullPointerException {@literal bindingErrors is null.} */ public boolean hasError(final CsvBindingErrors bindingErrors) { Objects.requireNonNull(bindingErrors); return bindingErrors.hasFieldErrors(name); } /** * フィールドに対するエラーがないか検査します。 * @see #hasError(CsvBindingErrors) * @param bindingErrors エラー情報 * @return trueの場合、エラーがないと判定します。 * @throws NullPointerException {@literal bindingErrors is null.} */ public boolean hasNotError(final CsvBindingErrors bindingErrors) { return !hasError(bindingErrors); } /** * 値が空かどうか判定します。 * <p>基本的に、nullかどうかで判定しますが、文字列型の場合は空文字かどうかでも判定します。 * @return trueの場合、空と判定します。 */ public boolean isEmpty() { if(value == null) { return true; } if(value instanceof String) { return ((String)value).isEmpty(); } return false; } /** * 値が空でないかどうか判定します。 * @since {@link #isEmpty()} * @return trueの場合、非空と判定します。 */ public boolean isNotEmpty() { return !isEmpty(); } /** * フィールドのバリデータを追加する。 * @param validator バリデータ。 * @return 自身のインスタンス。 * @throws NullPointerException {@literal validator is null.} */ public CsvField<T> add(final CsvFieldValidator<T> validator) { Objects.requireNonNull(validator); validators.add(validator); return this; } /** * フィールドの値の検証を行う。 * <p>既にエラーがある場合や検証後エラーとなる場合は、その時点で検証を中止する。</p> * @param bindingErrors エラー情報。 * @return 自身のインスタンス。 * @throws NullPointerException {@literal bindingErrors is null.} */ public CsvField<T> validate(final CsvBindingErrors bindingErrors) { Objects.requireNonNull(bindingErrors); for(CsvFieldValidator<T> validator : getValidators()) { if(hasError(bindingErrors)) { return this; } validator.validate(bindingErrors, this); } return this; } /** * フィールドのエラー情報を取得する。 * @param bindingErrors エラー情報 * @return エラーがない場合は空のリストを返します。 * @throws NullPointerException {@literal bindingErrors is null.} */ public List<CsvFieldError> getFieldErrors(final CsvBindingErrors bindingErrors) { Objects.requireNonNull(bindingErrors); return bindingErrors.getFieldErrors(getName()); } /** * フィールドの値を取得します。 * @return CellProcessorでエラーが発生した場合、値はなくnullを返します。 */ public T getValue() { return value; } /** * カラムのマッピング情報 * @return CsvBeanに定義したカラムのマッピング情報 */ public ColumnMapping getColumnMapping() { return columnMapping; } /** * 入力値検証の情報 * @return コンストラクタで渡した */ public ValidationContext<?> getValidationContext() { return validationContext; } /** * フィールドのValidatorの一覧を取得する。 * @return 設定されている{@link CsvFieldValidator}のリストを取得する。 */ public List<CsvFieldValidator<T>> getValidators() { return validators; } }