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