AbstractTemporalCellConverterFactory.java
package com.gh.mygreen.xlsmapper.cellconverter.impl;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.time.temporal.TemporalAccessor;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.TimeZone;
import com.gh.mygreen.xlsmapper.Configuration;
import com.gh.mygreen.xlsmapper.annotation.XlsDateTimeConverter;
import com.gh.mygreen.xlsmapper.cellconverter.BaseCellConverter;
import com.gh.mygreen.xlsmapper.cellconverter.CellConverterFactorySupport;
import com.gh.mygreen.xlsmapper.cellconverter.CellConverterFactory;
import com.gh.mygreen.xlsmapper.fieldaccessor.FieldAccessor;
import com.gh.mygreen.xlsmapper.textformatter.TextFormatter;
import com.gh.mygreen.xlsmapper.textformatter.TextParseException;
import com.gh.mygreen.xlsmapper.util.ArgUtils;
import com.gh.mygreen.xlsmapper.util.Utils;
/**
* {@link TemporalAccessor}の子クラスに対する{@link CellConverterFactory}のベースクラス。
*
* @since 2.0
* @author T.TSUCHIE
*
*/
public abstract class AbstractTemporalCellConverterFactory<T extends TemporalAccessor & Comparable<? super T>>
extends CellConverterFactorySupport<T> implements CellConverterFactory<T> {
@Override
protected void setupCustom(final BaseCellConverter<T> cellConverter, final FieldAccessor field, final Configuration config) {
ArgUtils.instanceOf(cellConverter, AbstractTemporalCellConverter.class, "cellConverter");
if(cellConverter instanceof AbstractTemporalCellConverter) {
final AbstractTemporalCellConverter<T> temporalCellConverter = (AbstractTemporalCellConverter<T>)cellConverter;
// 書き込み時のセルの書式を設定する
Optional<XlsDateTimeConverter> converterAnno = field.getAnnotation(XlsDateTimeConverter.class);
temporalCellConverter.setDefaultExcelPattern(getDefaultExcelPattern());
converterAnno.ifPresent(ca -> temporalCellConverter.setSettingExcelPattern(ca.excelPattern()));
}
}
@Override
protected TextFormatter<T> createTextFormatter(final FieldAccessor field, final Configuration config) {
final Optional<XlsDateTimeConverter> converterAnno = field.getAnnotation(XlsDateTimeConverter.class);
DateTimeFormatter formatter = createFormatter(converterAnno);
return new TextFormatter<T>() {
@Override
public T parse(final String text) {
try {
return parseTemporal(text, formatter);
} catch(DateTimeParseException e) {
final Map<String, Object> vars = new HashMap<>();
vars.put("javaPattern", getJavaPattern(converterAnno));
vars.put("excelPattern", getExcelPattern(converterAnno));
throw new TextParseException(text, field.getType(), e, vars);
}
}
@Override
public String format(final T value) {
return formatter.format(value);
}
};
}
/**
* アノテーションを元にフォーマッタを作成する。
* @param converterAnno 変換用のアノテーション。
* @return フォーマッタ
*/
protected DateTimeFormatter createFormatter(final Optional<XlsDateTimeConverter> converterAnno) {
final boolean lenient = converterAnno.map(a -> a.lenient()).orElse(false);
final ResolverStyle style = lenient ? ResolverStyle.LENIENT : ResolverStyle.STRICT;
if(!converterAnno.isPresent()) {
return DateTimeFormatter.ofPattern(getDefaultJavaPattern())
.withResolverStyle(style);
}
String pattern = converterAnno.get().javaPattern();
if(pattern.isEmpty()) {
pattern = getDefaultJavaPattern();
}
final Locale locale = Utils.getLocale(converterAnno.get().locale());
final ZoneId zone = converterAnno.get().timezone().isEmpty() ? ZoneId.systemDefault()
: TimeZone.getTimeZone(converterAnno.get().timezone()).toZoneId();
return DateTimeFormatter.ofPattern(pattern, locale)
.withResolverStyle(style)
.withZone(zone);
}
private String getJavaPattern(final Optional<XlsDateTimeConverter> converterAnno) {
if(!converterAnno.isPresent()) {
return getDefaultJavaPattern();
}
String pattern = converterAnno.get().javaPattern();
if(pattern.isEmpty()) {
pattern = getDefaultJavaPattern();
}
return pattern;
}
private String getExcelPattern(final Optional<XlsDateTimeConverter> converterAnno) {
if(!converterAnno.isPresent()) {
return getDefaultExcelPattern();
}
String pattern = converterAnno.get().excelPattern();
if(pattern.isEmpty()) {
pattern = getDefaultExcelPattern();
}
return pattern;
}
/**
* 文字列を解析してJavaオブジェクトに変換します。
* @param str 解析対象の文字列
* @param formatter フォーマッタ
* @return パースした結果
* @throws DateTimeParseException パースに失敗した場合
*/
protected abstract T parseTemporal(String str, DateTimeFormatter formatter) throws DateTimeParseException;
/**
* その型における標準のJavaの書式を返す。
* @return {@link SimpleDateFormat}で処理可能な形式。
*/
protected abstract String getDefaultJavaPattern();
/**
* その型における標準のExcelの書式を返す。
* @return Excelの書式
*/
protected abstract String getDefaultExcelPattern();
}