View Javadoc
1   package com.github.mygreen.supercsv.builder.time;
2   
3   import java.time.ZoneId;
4   import java.time.format.DateTimeFormatter;
5   import java.time.format.ResolverStyle;
6   import java.time.temporal.TemporalAccessor;
7   import java.util.Locale;
8   import java.util.Optional;
9   import java.util.TimeZone;
10  
11  import com.github.mygreen.supercsv.annotation.constraint.CsvDateTimeRange;
12  import com.github.mygreen.supercsv.annotation.constraint.CsvDateTimeMin;
13  import com.github.mygreen.supercsv.annotation.constraint.CsvDateTimeMax;
14  import com.github.mygreen.supercsv.annotation.format.CsvDateTimeFormat;
15  import com.github.mygreen.supercsv.builder.AbstractProcessorBuilder;
16  import com.github.mygreen.supercsv.builder.Configuration;
17  import com.github.mygreen.supercsv.builder.FieldAccessor;
18  import com.github.mygreen.supercsv.cellprocessor.constraint.DateTimeRangeFactory;
19  import com.github.mygreen.supercsv.cellprocessor.constraint.DateTimeMinFactory;
20  import com.github.mygreen.supercsv.cellprocessor.constraint.DateTimeMaxFactory;
21  import com.github.mygreen.supercsv.cellprocessor.format.TemporalFormatWrapper;
22  import com.github.mygreen.supercsv.cellprocessor.format.TextFormatter;
23  import com.github.mygreen.supercsv.util.Utils;
24  
25  
26  /**
27   * JSR-310 'Date and Time API' の{@link TemporalAccessor}のテンプレートクラス。
28   * <p>基本的に、{@link TemporalAccessor}のサブクラスのビルダは、このクラスを継承して作成する。</p>
29   * 
30   * @version 2.0
31   * @since 1.2
32   * @author T.TSUCHIE
33   *
34   */
35  public abstract class AbstractTemporalProcessorBuilder<T extends TemporalAccessor & Comparable<? super T>>
36          extends AbstractProcessorBuilder<T> {
37      
38      public AbstractTemporalProcessorBuilder() {
39          super();
40      }
41      
42      @Override
43      protected void init() {
44          super.init();
45          
46          // 制約のアノテーションの追加
47          registerForConstraint(CsvDateTimeRange.class, new DateTimeRangeFactory<>());
48          registerForConstraint(CsvDateTimeMin.class, new DateTimeMinFactory<>());
49          registerForConstraint(CsvDateTimeMax.class, new DateTimeMaxFactory<>());
50          
51      }
52      
53      /**
54       * 変換規則から、{@link DateTimeFormatter}のインスタンスを作成する。
55       * <p>アノテーション{@link CsvDateTimeFormat}が付与されていない場合は、各種タイプごとの標準の書式で作成する。</p>
56       * @param field フィールド情報
57       * @param config システム設定
58       * @return {@link DateTimeFormatter}のインスタンス。
59       */
60      protected DateTimeFormatter createFormatter(final FieldAccessor field, final Configuration config) {
61          
62          final Optional<CsvDateTimeFormat> formatAnno = field.getAnnotation(CsvDateTimeFormat.class);
63          if(!formatAnno.isPresent()) {
64              return DateTimeFormatter.ofPattern(getDefaultPattern());
65          }
66          
67          String pattern = formatAnno.get().pattern();
68          if(pattern.isEmpty()) {
69              pattern = getDefaultPattern();
70          }
71          
72          final ResolverStyle style = formatAnno.get().lenient() ? ResolverStyle.LENIENT : ResolverStyle.STRICT;
73          final Locale locale = Utils.getLocale(formatAnno.get().locale());
74          final ZoneId zone = formatAnno.get().timezone().isEmpty() ? ZoneId.systemDefault()
75                  : TimeZone.getTimeZone(formatAnno.get().timezone()).toZoneId();
76          
77          return DateTimeFormatter.ofPattern(pattern, locale)
78                  .withResolverStyle(style)
79                  .withZone(zone);
80          
81      }
82      
83      @SuppressWarnings("unchecked")
84      @Override
85      protected TextFormatter<T> getDefaultFormatter(final FieldAccessor field, final Configuration config) {
86          
87          final Optional<CsvDateTimeFormat> formatAnno = field.getAnnotation(CsvDateTimeFormat.class);
88          final String pattern = getPattern(field);
89          final DateTimeFormatter formatter = createFormatter(field, config);
90          
91          final TemporalFormatWrapper<T> wrapper = new TemporalFormatWrapper<>(formatter, (Class<T>)field.getType());
92          wrapper.setPattern(pattern);
93          formatAnno.ifPresent(a -> wrapper.setValidationMessage(a.message()));
94          return wrapper;
95          
96      }
97      
98      /**
99       * アノテーション{@link CsvDateTimeFormat}が付与されている場合は、パターンを取得する。
100      * <p>ただし、アノテーションが付与されていない場合は、{@link #getDefaultPattern()}の値を返す。</p>
101      * <p>{@link DateTimeFormatter}のインスタンスからは、元となったパターンは直接取得できないため、
102      *    別途取得して利用するために使用する。</p>
103      * @param field フィールド情報。
104      * @return 日時の書式パターン。
105      */
106     protected String getPattern(final FieldAccessor field) {
107         return field.getAnnotation(CsvDateTimeFormat.class)
108                 .map(a -> a.pattern())
109                 .filter(p -> !p.isEmpty())
110                 .orElse(getDefaultPattern());
111     }
112     
113     /**
114      * 変換規則用のアノテーションが定義されていないときの標準の書式を取得する。
115      * 
116      * @return {@link DateTimeFormatter}で解析可能な日時の書式。
117      */
118     protected abstract String getDefaultPattern();
119     
120 }