View Javadoc
1   package com.github.mygreen.supercsv.builder;
2   
3   import java.lang.annotation.Annotation;
4   import java.util.ArrayList;
5   import java.util.Collections;
6   import java.util.List;
7   import java.util.Map;
8   import java.util.Optional;
9   import java.util.Set;
10  
11  import org.supercsv.cellprocessor.ift.CellProcessor;
12  
13  import com.github.mygreen.supercsv.annotation.constraint.CsvEquals;
14  import com.github.mygreen.supercsv.annotation.constraint.CsvRequire;
15  import com.github.mygreen.supercsv.annotation.constraint.CsvUnique;
16  import com.github.mygreen.supercsv.annotation.constraint.CsvUniqueHashCode;
17  import com.github.mygreen.supercsv.annotation.conversion.CsvDefaultValue;
18  import com.github.mygreen.supercsv.annotation.conversion.CsvFullChar;
19  import com.github.mygreen.supercsv.annotation.conversion.CsvHalfChar;
20  import com.github.mygreen.supercsv.annotation.conversion.CsvLeftPad;
21  import com.github.mygreen.supercsv.annotation.conversion.CsvLower;
22  import com.github.mygreen.supercsv.annotation.conversion.CsvMultiPad;
23  import com.github.mygreen.supercsv.annotation.conversion.CsvNullConvert;
24  import com.github.mygreen.supercsv.annotation.conversion.CsvOneSideTrim;
25  import com.github.mygreen.supercsv.annotation.conversion.CsvRegexReplace;
26  import com.github.mygreen.supercsv.annotation.conversion.CsvRightPad;
27  import com.github.mygreen.supercsv.annotation.conversion.CsvTrim;
28  import com.github.mygreen.supercsv.annotation.conversion.CsvUpper;
29  import com.github.mygreen.supercsv.annotation.conversion.CsvWordReplace;
30  import com.github.mygreen.supercsv.annotation.format.CsvFormat;
31  import com.github.mygreen.supercsv.cellprocessor.ConstraintProcessorFactory;
32  import com.github.mygreen.supercsv.cellprocessor.ConstraintProcessorHandler;
33  import com.github.mygreen.supercsv.cellprocessor.ConversionProcessorFactory;
34  import com.github.mygreen.supercsv.cellprocessor.ConversionProcessorHandler;
35  import com.github.mygreen.supercsv.cellprocessor.ProcessorFactory;
36  import com.github.mygreen.supercsv.cellprocessor.constraint.EqualsFactory;
37  import com.github.mygreen.supercsv.cellprocessor.constraint.RequireFactory;
38  import com.github.mygreen.supercsv.cellprocessor.constraint.UniqueFactory;
39  import com.github.mygreen.supercsv.cellprocessor.constraint.UniqueHashCodeFactory;
40  import com.github.mygreen.supercsv.cellprocessor.conversion.DefaultValueFactory;
41  import com.github.mygreen.supercsv.cellprocessor.conversion.FullCharFactory;
42  import com.github.mygreen.supercsv.cellprocessor.conversion.HalfCharFactory;
43  import com.github.mygreen.supercsv.cellprocessor.conversion.LeftPadFactory;
44  import com.github.mygreen.supercsv.cellprocessor.conversion.LowerFactory;
45  import com.github.mygreen.supercsv.cellprocessor.conversion.MultiPadFactory;
46  import com.github.mygreen.supercsv.cellprocessor.conversion.NullConvertFactory;
47  import com.github.mygreen.supercsv.cellprocessor.conversion.OneSideTrimFactory;
48  import com.github.mygreen.supercsv.cellprocessor.conversion.RegexReplaceFactory;
49  import com.github.mygreen.supercsv.cellprocessor.conversion.RightPadFactory;
50  import com.github.mygreen.supercsv.cellprocessor.conversion.TrimFactory;
51  import com.github.mygreen.supercsv.cellprocessor.conversion.UpperFactory;
52  import com.github.mygreen.supercsv.cellprocessor.conversion.WordReplaceFactory;
53  import com.github.mygreen.supercsv.cellprocessor.format.ParseProcessorFactory;
54  import com.github.mygreen.supercsv.cellprocessor.format.PrintProcessorFactory;
55  import com.github.mygreen.supercsv.cellprocessor.format.TextFormatter;
56  
57  /**
58   * アノテーションによる{@link CellProcessor}を組み立てるベースとなるクラス。
59   * <p>共通の{@link CellProcessor}などを追加する処理を定義します。
60   *
61   * @param <T> 処理対象のクラスタイプ。
62   * @version 2.0
63   * @author T.TSUCHIE
64   *
65   */
66  public abstract class AbstractProcessorBuilder<T> implements ProcessorBuilder<T> {
67  
68      /**
69       * 読み込み時の変換用のCellProcessorを作成する。
70       */
71      protected List<ProcessorFactory> readingFactory = new ArrayList<>();
72  
73      /**
74       * 書き込み時の変換用のCellProcessorを作成する。
75       */
76      protected List<ProcessorFactory> writingFactory = new ArrayList<>();
77  
78      /**
79       * 変換のCellProcessorを作成する
80       */
81      protected ConversionProcessorHandleressorHandler.html#ConversionProcessorHandler">ConversionProcessorHandler conversionHandler = new ConversionProcessorHandler();
82  
83      /**
84       * 制約のCellProcessorを作成する
85       */
86      protected ConstraintProcessorHandleressorHandler.html#ConstraintProcessorHandler">ConstraintProcessorHandler constraintHandler = new ConstraintProcessorHandler();
87  
88      /**
89       * デフォルトコンストラクタ。
90       * <p>{@link #init()}メソッドが呼ばれる。
91       */
92      public AbstractProcessorBuilder() {
93          init();
94      }
95  
96      /**
97       * デフォルトの{@link ProcessorFactory}などの登録を行い、初期化を行う。
98       *
99       */
100     protected void init() {
101 
102         // 読み込み用の登録
103         registerForReading(conversionHandler);
104         registerForReading(new ParseProcessorFactory<>());
105         registerForReading(constraintHandler);
106 
107         // 書き込み用の登録
108         registerForWriting(constraintHandler);
109         registerForWriting(new PrintProcessorFactory<>());
110         registerForWriting(conversionHandler);
111 
112         // 変換用の登録
113         registerForConversion(CsvNullConvert.class, new NullConvertFactory());
114         registerForConversion(CsvDefaultValue.class, new DefaultValueFactory());
115         registerForConversion(CsvTrim.class, new TrimFactory());
116         registerForConversion(CsvUpper.class, new UpperFactory());
117         registerForConversion(CsvLower.class, new LowerFactory());
118         registerForConversion(CsvRegexReplace.class, new RegexReplaceFactory());
119         registerForConversion(CsvWordReplace.class, new WordReplaceFactory());
120         registerForConversion(CsvFullChar.class, new FullCharFactory());
121         registerForConversion(CsvHalfChar.class, new HalfCharFactory());
122         registerForConversion(CsvLeftPad.class, new LeftPadFactory());
123         registerForConversion(CsvRightPad.class, new RightPadFactory());
124         registerForConversion(CsvMultiPad.class, new MultiPadFactory());
125         registerForConversion(CsvOneSideTrim.class, new OneSideTrimFactory());
126 
127         // 制約用の登録
128         registerForConstraint(CsvRequire.class, new RequireFactory());
129         registerForConstraint(CsvUnique.class, new UniqueFactory<>());
130         registerForConstraint(CsvUniqueHashCode.class, new UniqueHashCodeFactory<>());
131         registerForConstraint(CsvEquals.class, new EqualsFactory<>());
132 
133     }
134 
135     @Override
136     public Optional<CellProcessor> buildForReading(final Class<T> type, final FieldAccessor field,
137             final Configuration config, final Class<?>[] groups) {
138 
139         // 登録時とは逆順に処理する
140         final List<ProcessorFactory> factories = new ArrayList<>(readingFactory);
141         Collections.reverse(factories);
142 
143         final TextFormatter<T> formatter = getFormatter(field, config);
144 
145         Optional<CellProcessor> processor = Optional.empty();
146         for(ProcessorFactory factory : factories) {
147             processor = factory.create(processor, field, formatter, config, BuildCase.Read, groups);
148         }
149 
150         return processor;
151 
152     }
153 
154     @Override
155     public Optional<CellProcessor> buildForWriting(final Class<T> type, final FieldAccessor field,
156             final Configuration config, final Class<?>[] groups) {
157 
158         // 登録時とは逆順に処理する
159         final List<ProcessorFactory> factories = new ArrayList<>(writingFactory);
160         Collections.reverse(factories);
161 
162         final TextFormatter<T> formatter = getFormatter(field, config);
163 
164         Optional<CellProcessor> processor = Optional.empty();
165         for(ProcessorFactory factory : factories) {
166 
167             //制約のProcessorの実行有無の判定
168             if(config.isSkipValidationOnWrite()
169                     && factory instanceof ConstraintProcessorHandler) {
170                 continue;
171             }
172 
173             processor = factory.create(processor, field, formatter, config, BuildCase.Write, groups);
174         }
175 
176         return processor;
177     }
178 
179     /**
180      * 読み込み用のCellProcessorを作成するクラスを登録する。
181      * <p>実行時は、登録された順に処理される。
182      * @param factory {@link ProcessorFactory}の実装クラス。
183      */
184     public void registerForReading(final ProcessorFactory factory) {
185         this.readingFactory.add(factory);
186     }
187 
188     /**
189      * 書き込み用のCellProcessorを作成するクラスを登録する。
190      * <p>実行時は、登録された順に処理される。
191      * @param factory {@link ProcessorFactory}の実装クラス。
192      */
193     public void registerForWriting(final ProcessorFactory factory) {
194         this.writingFactory.add(factory);
195     }
196 
197     /**
198      * 変換のCellProcessorを作成するクラスを登録する。読み込み時と書き込み時は共通です。
199      *
200      * @param <A> アノテーションのクラス
201      * @param anno 関連づけるアノテーション
202      * @param factory アノテーションを処理する{@link ConversionProcessorFactory}の実装。
203      */
204     public <A extends Annotation> void registerForConversion(final Class<A> anno, final ConversionProcessorFactory<A> factory) {
205         this.conversionHandler.register(anno, factory);
206     }
207 
208     /**
209      * 制約のCellProcessorを作成するクラスを登録する。読み込み時と書き込み時は共通です。
210      *
211      * @param <A> アノテーションのクラス
212      * @param anno 関連づけるアノテーション
213      * @param factory アノテーションを処理する{@link ConstraintProcessorFactory}の実装。
214      */
215     public <A extends Annotation> void registerForConstraint(final Class<A> anno, final ConstraintProcessorFactory<A> factory) {
216         this.constraintHandler.register(anno, factory);
217     }
218 
219     /**
220      * 文字列とオブジェクトを相互変換するフォーマッタを取得します。
221      * <p>アノテーション{@link CsvFormat}が指定されている場合は、そちらを優先します。</p>
222      * @param field フィールド情報
223      * @param config システム設定
224      * @return フォーマッタを取得します。
225      */
226     @SuppressWarnings("unchecked")
227     public TextFormatter<T> getFormatter(final FieldAccessor field, final Configuration config) {
228 
229         if(field.hasAnnotation(CsvFormat.class)) {
230             CsvFormat formatAnno = field.getAnnotation(CsvFormat.class).get();
231 
232             final TextFormatter<T> formatter = (TextFormatter<T>) config.getBeanFactory().create(formatAnno.formatter());
233             if(!formatAnno.message().isEmpty()) {
234                 formatter.setValidationMessage(formatAnno.message());
235             }
236             return formatter;
237 
238         } else {
239             return getDefaultFormatter(field, config);
240 
241         }
242     }
243 
244     /**
245      * 文字列とオブジェクトを相互変換する標準のフォーマッタを取得します。
246      * <p>書式が設定されている場合は、書式に沿って処理を行います。</p>
247      * @param field フィールド情報
248      * @param config システム設定
249      * @return 標準のフォーマッタを取得します。
250      */
251     protected abstract TextFormatter<T> getDefaultFormatter(FieldAccessor field, Configuration config);
252 
253     /**
254      * 登録している変換用のアノテーションとそのファクトリクラスの情報を取得します。
255      * @return アノテーションと対応する{@link ConversionProcessorFactory}のマップ。
256      */
257     public Set<Map.Entry<Class<? extends Annotation>, ConversionProcessorFactory<?>>>  getEntrySetForConversion() {
258         return conversionHandler.getEntrySet();
259     }
260 
261     /**
262      * 登録している検証用のアノテーションとそのファクトリクラスの情報を取得します。
263      * @return アノテーションと対応する{@link ConstraintProcessorFactory}のマップ。
264      */
265     public Set<Map.Entry<Class<? extends Annotation>, ConstraintProcessorFactory<?>>>  getEntrySetForConsraint() {
266         return constraintHandler.getEntrySet();
267     }
268 
269 }