AbstractTemporalCellConverterFactory.java

  1. package com.gh.mygreen.xlsmapper.cellconverter.impl;

  2. import java.text.SimpleDateFormat;
  3. import java.time.ZoneId;
  4. import java.time.format.DateTimeFormatter;
  5. import java.time.format.DateTimeParseException;
  6. import java.time.format.ResolverStyle;
  7. import java.time.temporal.TemporalAccessor;
  8. import java.util.HashMap;
  9. import java.util.Locale;
  10. import java.util.Map;
  11. import java.util.Optional;
  12. import java.util.TimeZone;

  13. import com.gh.mygreen.xlsmapper.Configuration;
  14. import com.gh.mygreen.xlsmapper.annotation.XlsDateTimeConverter;
  15. import com.gh.mygreen.xlsmapper.cellconverter.BaseCellConverter;
  16. import com.gh.mygreen.xlsmapper.cellconverter.CellConverterFactorySupport;
  17. import com.gh.mygreen.xlsmapper.cellconverter.CellConverterFactory;
  18. import com.gh.mygreen.xlsmapper.fieldaccessor.FieldAccessor;
  19. import com.gh.mygreen.xlsmapper.textformatter.TextFormatter;
  20. import com.gh.mygreen.xlsmapper.textformatter.TextParseException;
  21. import com.gh.mygreen.xlsmapper.util.ArgUtils;
  22. import com.gh.mygreen.xlsmapper.util.Utils;

  23. /**
  24.  * {@link TemporalAccessor}の子クラスに対する{@link CellConverterFactory}のベースクラス。
  25.  *
  26.  * @since 2.0
  27.  * @author T.TSUCHIE
  28.  *
  29.  */
  30. public abstract class AbstractTemporalCellConverterFactory<T extends TemporalAccessor & Comparable<? super T>>
  31.         extends CellConverterFactorySupport<T> implements CellConverterFactory<T> {

  32.     @Override
  33.     protected void setupCustom(final BaseCellConverter<T> cellConverter, final FieldAccessor field, final Configuration config) {

  34.         ArgUtils.instanceOf(cellConverter, AbstractTemporalCellConverter.class, "cellConverter");

  35.         if(cellConverter instanceof AbstractTemporalCellConverter) {

  36.             final AbstractTemporalCellConverter<T> temporalCellConverter = (AbstractTemporalCellConverter<T>)cellConverter;

  37.             // 書き込み時のセルの書式を設定する
  38.             Optional<XlsDateTimeConverter> converterAnno = field.getAnnotation(XlsDateTimeConverter.class);

  39.             temporalCellConverter.setDefaultExcelPattern(getDefaultExcelPattern());
  40.             converterAnno.ifPresent(ca -> temporalCellConverter.setSettingExcelPattern(ca.excelPattern()));

  41.         }

  42.     }

  43.     @Override
  44.     protected TextFormatter<T> createTextFormatter(final FieldAccessor field, final Configuration config) {

  45.         final Optional<XlsDateTimeConverter> converterAnno = field.getAnnotation(XlsDateTimeConverter.class);
  46.         DateTimeFormatter formatter = createFormatter(converterAnno);

  47.         return new TextFormatter<T>() {

  48.             @Override
  49.             public T parse(final String text) {
  50.                 try {
  51.                     return parseTemporal(text, formatter);

  52.                 } catch(DateTimeParseException e) {
  53.                     final Map<String, Object> vars = new HashMap<>();
  54.                     vars.put("javaPattern", getJavaPattern(converterAnno));
  55.                     vars.put("excelPattern", getExcelPattern(converterAnno));

  56.                     throw new TextParseException(text, field.getType(), e, vars);
  57.                 }
  58.             }

  59.             @Override
  60.             public String format(final T value) {
  61.                 return formatter.format(value);
  62.             }
  63.         };

  64.     }

  65.     /**
  66.      * アノテーションを元にフォーマッタを作成する。
  67.      * @param converterAnno 変換用のアノテーション。
  68.      * @return フォーマッタ
  69.      */
  70.     protected DateTimeFormatter createFormatter(final Optional<XlsDateTimeConverter> converterAnno) {

  71.         final boolean lenient = converterAnno.map(a -> a.lenient()).orElse(false);
  72.         final ResolverStyle style = lenient ? ResolverStyle.LENIENT : ResolverStyle.STRICT;
  73.         if(!converterAnno.isPresent()) {
  74.             return DateTimeFormatter.ofPattern(getDefaultJavaPattern())
  75.                     .withResolverStyle(style);
  76.         }

  77.         String pattern = converterAnno.get().javaPattern();
  78.         if(pattern.isEmpty()) {
  79.             pattern = getDefaultJavaPattern();
  80.         }

  81.         final Locale locale = Utils.getLocale(converterAnno.get().locale());
  82.         final ZoneId zone = converterAnno.get().timezone().isEmpty() ? ZoneId.systemDefault()
  83.                 : TimeZone.getTimeZone(converterAnno.get().timezone()).toZoneId();

  84.         return DateTimeFormatter.ofPattern(pattern, locale)
  85.                 .withResolverStyle(style)
  86.                 .withZone(zone);

  87.     }

  88.     private String getJavaPattern(final Optional<XlsDateTimeConverter> converterAnno) {
  89.         if(!converterAnno.isPresent()) {
  90.             return getDefaultJavaPattern();
  91.         }

  92.         String pattern = converterAnno.get().javaPattern();
  93.         if(pattern.isEmpty()) {
  94.             pattern = getDefaultJavaPattern();
  95.         }

  96.         return pattern;
  97.     }

  98.     private String getExcelPattern(final Optional<XlsDateTimeConverter> converterAnno) {
  99.         if(!converterAnno.isPresent()) {
  100.             return getDefaultExcelPattern();
  101.         }

  102.         String pattern = converterAnno.get().excelPattern();
  103.         if(pattern.isEmpty()) {
  104.             pattern = getDefaultExcelPattern();
  105.         }

  106.         return pattern;
  107.     }

  108.     /**
  109.      * 文字列を解析してJavaオブジェクトに変換します。
  110.      * @param str 解析対象の文字列
  111.      * @param formatter フォーマッタ
  112.      * @return パースした結果
  113.      * @throws DateTimeParseException パースに失敗した場合
  114.      */
  115.     protected abstract T parseTemporal(String str, DateTimeFormatter formatter) throws DateTimeParseException;

  116.     /**
  117.      * その型における標準のJavaの書式を返す。
  118.      * @return {@link SimpleDateFormat}で処理可能な形式。
  119.      */
  120.     protected abstract String getDefaultJavaPattern();

  121.     /**
  122.      * その型における標準のExcelの書式を返す。
  123.      * @return Excelの書式
  124.      */
  125.     protected abstract String getDefaultExcelPattern();

  126. }