View Javadoc
1   package com.github.mygreen.supercsv.cellprocessor.format;
2   
3   import java.lang.reflect.InvocationTargetException;
4   import java.lang.reflect.Method;
5   import java.time.LocalDate;
6   import java.time.chrono.JapaneseDate;
7   import java.time.format.DateTimeFormatter;
8   import java.time.format.DateTimeParseException;
9   import java.time.temporal.TemporalAccessor;
10  import java.util.HashMap;
11  import java.util.Map;
12  import java.util.Objects;
13  import java.util.Optional;
14  
15  import com.github.mygreen.supercsv.util.Utils;
16  
17  /**
18   * Date and Time APIの{@link DateTimeFormatter}をラップしたクラス。
19   *
20   * @version 2.1
21   * @since 2.0
22   * @author T.TSUCHIE
23   *
24   */
25  public class TemporalFormatWrapper<T extends TemporalAccessor> extends AbstractTextFormatter<T> {
26      
27      private final DateTimeFormatter formatter;
28      
29      private final Class<T> type;
30      
31      private final Method parseMethod;
32      
33      private String pattern;
34      
35      /**
36       * 
37       * @param formatter ラップする{@link DateTimeFormatter}を指定します。
38       * @param type {@link TemporalAccessor}の実装クラスを指定します。
39       * @throws NullPointerException {@literal if formatter or type is null.}
40       * @throws IllegalArgumentException {@literal type is not support class type.}
41       */
42      public TemporalFormatWrapper(final DateTimeFormatter formatter, final Class<T> type) {
43          Objects.requireNonNull(formatter);
44          Objects.requireNonNull(type);
45          
46          this.formatter = formatter;
47          this.type = type;
48          
49          
50          try {
51              this.parseMethod = type.getMethod("parse", CharSequence.class, DateTimeFormatter.class);
52              
53          } catch (NoSuchMethodException | SecurityException e) {
54              throw new IllegalArgumentException(String.format("Cannot suuport type : %s.", type.getName()));
55          }
56          
57      }
58      
59      /**
60       * {@inheritDoc}
61       * 
62       * サポートしていないクラスタイプの場合、例外{@link TextParseException}がスローされます。
63       */
64      @SuppressWarnings("unchecked")
65      @Override
66      public T parse(final String text) {
67          
68          try {
69              return (T) parseMethod.invoke(type, text, formatter);
70              
71          } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
72              throw new TextParseException(text, type, "Cannot suuport type.");
73              
74          } catch(DateTimeParseException e) {
75              throw new TextParseException(text, type, e);
76          }
77          
78      }
79      
80      @Override
81      public String print(final T object) {
82          
83          if(pattern.contains("G") && formatter.getLocale().getLanguage().equals("ja")) {
84              if(LocalDate.class.isAssignableFrom(type)) {
85                  JapaneseDate date = JapaneseDate.from((LocalDate)object);
86                  return formatter.format(date);
87              }
88          }
89          
90          
91          return formatter.format(object);
92      }
93      
94      @Override
95      public Optional<String> getPattern() {
96          if(Utils.isEmpty(pattern)) {
97              return Optional.empty();
98          } else {
99              return Optional.of(pattern);
100         }
101     }
102     
103     /**
104      * パースする際のエラーメッセージ中に利用する書式を指定します。
105      * @param pattern コンストラクタで指定した{@link DateTimeFormatter}に対応する書式を指定します。
106      */
107     public void setPattern(String pattern) {
108         this.pattern = pattern;
109     }
110     
111     @Override
112     public Map<String, Object> getMessageVariables() {
113         final Map<String, Object> vars = new HashMap<>();
114         getPattern().ifPresent(p -> vars.put("pattern", p));
115         
116         return vars;
117     }
118     
119 }