1 package com.github.mygreen.supercsv.io;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.Reader;
6 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.Objects;
9
10 import org.supercsv.exception.SuperCsvException;
11 import org.supercsv.io.ITokenizer;
12 import org.supercsv.prefs.CsvPreference;
13
14 import com.github.mygreen.supercsv.builder.BeanMapping;
15 import com.github.mygreen.supercsv.builder.BeanMappingFactory;
16 import com.github.mygreen.supercsv.exception.SuperCsvBindingException;
17 import com.github.mygreen.supercsv.exception.SuperCsvNoMatchColumnSizeException;
18 import com.github.mygreen.supercsv.exception.SuperCsvNoMatchHeaderException;
19
20 /**
21 * アノテーションを元にCSVファイルを読み込むためのクラス。
22 *
23 * @param <T> マッピング対象のBeanのクラスタイプ
24 * @version 2.1
25 * @author T.TSUCHIE
26 *
27 */
28 public class CsvAnnotationBeanReader<T> extends AbstractCsvAnnotationBeanReader<T> {
29
30 /**
31 * Beanのクラスタイプを指定して、{@link CsvAnnotationBeanReader}を作成するコンストラクタ。
32 * <p>{@link BufferedReader}にラップして実行されるため、ラップする必要はありません。</p>
33 *
34 * @param beanType Beanのクラスタイプ。
35 * @param reader the Reader。
36 * @param preference the CSV preferences.
37 * @param groups グループ情報。適用するアノテーションを切り替える際に指定します。
38 * @throws NullPointerException {@literal if beanType or reader or preferences are null.}
39 */
40 public CsvAnnotationBeanReader(final Class<T> beanType, final Reader reader, final CsvPreference preference,
41 final Class<?>... groups) {
42 super(reader, preference);
43
44 Objects.requireNonNull(beanType, "beanType should not be null.");
45
46 BeanMappingFactoryanMappingFactory.html#BeanMappingFactory">BeanMappingFactory factory = new BeanMappingFactory();
47 this.beanMappingCache = BeanMappingCache.create(factory.create(beanType, groups));
48 this.validators.addAll(beanMappingCache.getOriginal().getValidators());
49 }
50
51 /**
52 * Beanのマッピング情報を指定して、{@link CsvAnnotationBeanReader}を作成するコンストラクタ。
53 * <p>{@link BufferedReader}にラップして実行されるため、ラップする必要はありません。</p>
54 * <p>Beanのマッピング情報を独自にカスタマイズして、{@link BeanMappingFactory}から作成する場合に利用します。</p>
55 *
56 * @param beanMapping Beanのマッピング情報。
57 * @param reader the Reader。
58 * @param preference the CSV preferences.
59 * @throws NullPointerException {@literal if beanMapping or reader or preferences are null.}
60 */
61 public CsvAnnotationBeanReader(final BeanMapping<T> beanMapping, final Reader reader, final CsvPreference preference) {
62 super(reader, preference);
63
64 Objects.requireNonNull(beanMapping, "beanMapping should not be null.");
65
66 this.beanMappingCache = BeanMappingCache.create(beanMapping);
67 this.validators.addAll(beanMapping.getValidators());
68 }
69
70 /**
71 * Beanのクラスタイプを指定して、{@link CsvAnnotationBeanReader}を作成するコンストラクタ。
72 * <p>{@link BufferedReader}にラップして実行されるため、ラップする必要はありません。</p>
73 *
74 * @param beanType Beanのクラスタイプ。
75 * @param tokenizer the tokenizer.
76 * @param preference the CSV preferences.
77 * @param groups グループ情報。適用するアノテーションを切り替える際に指定します。
78 * @throws NullPointerException {@literal if beanType or tokenizer or preferences are null.}
79 */
80 public CsvAnnotationBeanReader(final Class<T> beanType, final ITokenizer tokenizer, final CsvPreference preference,
81 final Class<?>... groups) {
82 super(tokenizer, preference);
83
84 Objects.requireNonNull(beanType, "beanType should not be null.");
85
86 BeanMappingFactoryanMappingFactory.html#BeanMappingFactory">BeanMappingFactory factory = new BeanMappingFactory();
87 this.beanMappingCache = BeanMappingCache.create(factory.create(beanType, groups));
88 this.validators.addAll(beanMappingCache.getOriginal().getValidators());
89 }
90
91 /**
92 * Beanのマッピング情報を指定して、{@link CsvAnnotationBeanReader}を作成するコンストラクタ。
93 * <p>{@link BufferedReader}にラップして実行されるため、ラップする必要はありません。</p>
94 * <p>Beanのマッピング情報を独自にカスタマイズして、{@link BeanMappingFactory}から作成する場合に利用します。</p>
95 *
96 * @param beanMapping Beanのマッピング情報。
97 * @param tokenizer the tokenizer.
98 * @param preferences the CSV preferences.
99 * @throws NullPointerException {@literal if beanMapping or tokenizer or preferences are null.}
100 */
101 public CsvAnnotationBeanReader(final BeanMapping<T> beanMapping, final ITokenizer tokenizer, final CsvPreference preferences) {
102 super(tokenizer, preferences);
103
104 Objects.requireNonNull(beanMapping, "beanMapping should not be null.");
105
106 this.beanMappingCache = BeanMappingCache.create(beanMapping);
107 this.validators.addAll(beanMapping.getValidators());
108 }
109
110 /**
111 * {@inheritDoc}
112 *
113 * @param firstLineCheck 1行目の読み込み時に呼ばれるかチェックします。
114 * trueのとき、1行目の読み込み時以外に呼ばれた場合、例外{@link SuperCsvException}をスローします。
115 * @return ヘッダー行の値を配列で返します。
116 * @throws SuperCsvNoMatchColumnSizeException ヘッダーのサイズ(カラム数)がBean定義と一致しない場合。
117 * @throws SuperCsvNoMatchHeaderException ヘッダーの値がBean定義と一致しない場合。
118 * @throws SuperCsvException 引数firstLineCheck=trueのとき、このメソッドが1行目以外の読み込み時に呼ばれた場合。
119 * @throws IOException ファイルの読み込みに失敗した場合。
120 */
121 @Override
122 public String[] getHeader(boolean firstLineCheck) throws IOException {
123
124 final String[] header = super.getHeader(firstLineCheck);
125 if(beanMappingCache.getOriginal().isValidateHeader()) {
126 try {
127 validateHeader(header, beanMappingCache.getHeader());
128
129 } catch(SuperCsvNoMatchColumnSizeException | SuperCsvNoMatchHeaderException e) {
130 // convert exception and format to message.
131 errorMessages.addAll(exceptionConverter.convertAndFormat(e, beanMappingCache.getOriginal()));
132 throw e;
133 }
134 }
135
136 return header;
137
138 }
139
140 /**
141 * レコードを全て読み込みます。
142 * <p>ヘッダー行も自動的に処理されます。</p>
143 * <p>レコード処理中に例外が発生した場合、その時点で処理を終了します。</p>
144 *
145 * @return 読み込んだレコード情報。
146 *
147 * @throws IOException レコードの読み込みに失敗した場合。
148 * @throws SuperCsvNoMatchColumnSizeException レコードのカラムサイズに問題がある場合
149 * @throws SuperCsvBindingException セルの値に問題がある場合
150 * @throws SuperCsvException 設定など、その他に問題がある場合
151 */
152 public List<T> readAll() throws IOException {
153 return readAll(false);
154 }
155
156 /**
157 * レコードを全て読み込みます。
158 * <p>ヘッダー行も自動的に処理されます。</p>
159 *
160 * @param continueOnError レコードの処理中に、
161 * 例外{@link SuperCsvNoMatchColumnSizeException}、{@link SuperCsvNoMatchColumnSizeException}、{@link SuperCsvBindingException}
162 * が発生しても続行するかどう指定します。
163 * trueの場合、例外が発生しても、次の処理を行います。
164 * @return 読み込んだレコード情報。
165 *
166 * @throws IOException レコードの読み込みに失敗した場合。
167 * @throws SuperCsvNoMatchColumnSizeException レコードのカラムサイズに問題がある場合
168 * @throws SuperCsvBindingException セルの値に問題がある場合
169 * @throws SuperCsvException 設定など、その他に問題がある場合
170 */
171 public List<T> readAll(final boolean continueOnError) throws IOException {
172
173 if(beanMappingCache.getOriginal().isHeader()) {
174 try {
175 getHeader(true);
176 } catch(SuperCsvNoMatchColumnSizeException | SuperCsvNoMatchHeaderException e) {
177 if(!continueOnError) {
178 throw e;
179 }
180 }
181 }
182
183 final List<T> list = new ArrayList<>();
184
185 while(true) {
186 try {
187 final T record = read();
188 if(record == null) {
189 break;
190 }
191 list.add(record);
192
193 } catch(SuperCsvNoMatchColumnSizeException | SuperCsvBindingException e) {
194 if(!continueOnError) {
195 throw e;
196 }
197 }
198 }
199
200 return list;
201 }
202
203 }