10. 独自のProcessorBuilderの作成

10.1. CellProcessorを直接組み立てる場合

本ライブラリでは、アノテーションを元にCellProcessorを作成しますが、従来の方法で直接作成することもできます。 その場合は、 ProcessorBuilder [ JavaDoc ]を実装します。

Integer型に対するCellProcessorをSuper CSVの既存のCellProcessorを使って組み立てる例を示します。

 1import java.text.DecimalFormat;
 2import java.util.List;
 3import java.util.Optional;
 4
 5import org.supercsv.cellprocessor.FmtNumber;
 6import org.supercsv.cellprocessor.ParseInt;
 7import org.supercsv.cellprocessor.Trim;
 8import org.supercsv.cellprocessor.constraint.NotNull;
 9import org.supercsv.cellprocessor.ift.CellProcessor;
10
11import com.github.mygreen.supercsv.builder.ProcessorBuilder
12
13
14public class CustomProcessorBuilder implements ProcessorBuilder<Integer> {
15
16    // 読み込み時用のCellProcessorの組み立て
17    @Override
18    public Optional<CellProcessor> buildForReading(Class<Integer> type, FieldAccessor field,
19            Configuration config, Class<?>[] groups) {
20
21        CellProcessor processor = new NotNull(new Trim(new ParseInt()));
22        return Optional.of(processor);
23    }
24
25    // 書き込み時用のCellProcessorの組み立て
26    @Override
27    public Optional<CellProcessor> buildForWriting(Class<Integer> type, FieldAccessor field,
28            Class<?>[] groups, Configuration config) {
29
30        CellProcessor processor = new NotNull(new FmtNumber(new DecimalFormat("#,##0")));
31        return Optional.of(processor);
32    }
33
34}

作成したProcessorBuilderを使用する際には、アノテーション @CsvColumn(builder=<ビルダクラス>) で指定します。

 1import com.github.mygreen.supercsv.annotation.CsvBean;
 2import com.github.mygreen.supercsv.annotation.CsvColumn;
 3
 4@CsvBean
 5public class SampleCsv {
 6
 7    @CsvColumn(number=1, label="数値", builder=CustomProcessorBuilder.class)
 8    private Integer number;
 9
10}

10.2. エラー処理

Super CSVの既存のCellProcessorでは、値が不正な場合は、 例外 SuperCsvCellProcessorException または、その子クラス SuperCsvConstraintViolationException が スローされます。

  • スローされた例外は、 CsvExceptionConverter でメッセージに変換することができます。

  • CsvExceptionConverter は、 CsvAnnotationBeanReader/CsvAnnotationBeanWriter に組み込まれており、 例外発生後に変換したメッセージを取得できます。

 1import java.nio.charset.Charset;
 2import java.nio.file.Files;
 3import java.io.File;
 4import java.util.ArrayList;
 5import java.util.List;
 6
 7import org.supercsv.prefs.CsvPreference;
 8import org.supercsv.exception.SuperCsvCellProcessorException;
 9
10import com.github.mygreen.supercsv.io.CsvAnnotationBeanReader;
11import com.github.mygreen.supercsv.validation.CsvExceptionConverter;
12
13
14public class Sample {
15
16    public void sampleRead() {
17
18        CsvAnnotationBeanReader<UserCsv> csvReader;
19        try {
20            csvReader = new CsvAnnotationBeanReader<>(
21                UserCsv.class,
22                Files.newBufferedReader(new File("sample.csv").toPath(), Charset.forName("Windows-31j")),
23                CsvPreference.STANDARD_PREFERENCE);
24
25            // ファイルの読み込み
26            List<UserCsv> list = csvReader.readAll();
27
28        } catch(SuperCsvCellProcessorException e) {
29
30            // 変換されたエラーメッセージの取得
31            List<String> messages = csvReader.getErrorMessages();
32
33        } finally {
34            if(csvReader != null) {
35                csvReader.close();
36            }
37        }
38    }
39
40}

クラスパスのルートに、プロパティファイル SuperCsvMessages.properties を配置しておくと、自動的に読み込まれます。

  • プロパティファイルは、UTF-8、ASCIIコード変換なしで作成します。 [ver.2.2]

  • メッセージキーは、例外がスローされた「CellProcessorのクラス名」「クラス名」「フィールド名」「フィールドのクラスタイプ」を組み合わせて、優先順位の高いものに一致した物が採用されます。

  • メッセージ中では変数が利用可能で、予め利用可能な変数は下記が登録されています。

    • メッセージ変数は、{key} で参照可能です。

  • さらに、${式} の形式だと、式言語として JEXL が利用可能です。

  • ただし、 Spring Frameworkと連携してエラーメッセージの取得方法を変更 している場合は、定義する箇所は異なります。

表 - 10.2.1 メッセージキーの候補

優先度

形式

1

<CellProcessorのクラス名>.<Beanのクラス名>.<フィールド名>

ParseInt.SampleCsv.number

2

<CellProcessorのクラス名>.<フィールド名>

ParseInt.number

3

<CellProcessorのクラス名>.<フィールドのクラスパス>

ParseInt.java.lang.Integer

4

<CellProcessorのクラス名>.<フィールドのクラスタイプの親のクラスパス>
※数値型と列挙型のみ
ParseInt.java.lang.Number
ParseInt.java.lang.Enum

5

<CellProcessorのクラス名>

ParseInt

表 - 10.2.2 メッセージ中で利用可能な変数

変数名

説明

lineNumber

CSVの実ファイル上の行番号。
カラムの値に改行が含まれている場合を考慮した実際の行番号なります。
1から始まります。

rowNumber

CSVの論理上の行番号です。
1から始まります。

columnNumber

CSVの列番号です。
1から始まります。

label

@CsvColumn(label="<見出し>") 出指定したカラムの見出し名です。
label属性を指定していない場合は、フィールド名になります。

validatedValue

不正となった値です。

formatter

java.util.Formatter のインスタンスです。
パース済みのオブジェクトをフォーマットするのに利用します。
コード - 10.2.1 SuperCsvMessage.propertiesの定義例
 1###################################################
 2# 独自のエラーメッセージの定義
 3###################################################
 4# 定義したキーは、再帰的に{キー名}で参照可能
 5
 6csvContext=[{rowNumber}行, {columnNumber}列]
 7
 8# CellProcessorに対するエラーメッセージ
 9NotNull={csvContext} : 項目「{label}」の値は必須です。
10ParseInt={csvContext} : 項目「{label}」の値({validatedValue})は、整数として不正です。
11
12Unique.java.util.Date={csvContext} : 項目「{label}」の値(${formatter.format('%tF', validatedValue)})は、ユニークではありません。