AbstractNumberProcessorBuilder.java
package com.github.mygreen.supercsv.builder.standard;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Currency;
import java.util.Locale;
import java.util.Optional;
import org.supercsv.cellprocessor.ift.CellProcessor;
import com.github.mygreen.supercsv.annotation.constraint.CsvNumberMax;
import com.github.mygreen.supercsv.annotation.constraint.CsvNumberMin;
import com.github.mygreen.supercsv.annotation.constraint.CsvNumberRange;
import com.github.mygreen.supercsv.annotation.format.CsvNumberFormat;
import com.github.mygreen.supercsv.builder.AbstractProcessorBuilder;
import com.github.mygreen.supercsv.builder.Configuration;
import com.github.mygreen.supercsv.builder.FieldAccessor;
import com.github.mygreen.supercsv.cellprocessor.constraint.NumberMaxFactory;
import com.github.mygreen.supercsv.cellprocessor.constraint.NumberMinFactory;
import com.github.mygreen.supercsv.cellprocessor.constraint.NumberRangeFactory;
import com.github.mygreen.supercsv.cellprocessor.format.NumberFormatWrapper;
import com.github.mygreen.supercsv.cellprocessor.format.SimpleNumberFormatter;
import com.github.mygreen.supercsv.cellprocessor.format.TextFormatter;
import com.github.mygreen.supercsv.util.Utils;
/**
* 数値型に対する{@link CellProcessor}を組み立てるクラス。
* <p>各種タイプごとに実装を行う。</p>
*
* @version 2.0
* @author T.TSUCHIE
*
*/
public abstract class AbstractNumberProcessorBuilder<N extends Number & Comparable<N>> extends AbstractProcessorBuilder<N> {
public AbstractNumberProcessorBuilder() {
super();
}
@Override
protected void init() {
super.init();
// 制約のアノテーションの追加
registerForConstraint(CsvNumberRange.class, new NumberRangeFactory<>());
registerForConstraint(CsvNumberMin.class, new NumberMinFactory<>());
registerForConstraint(CsvNumberMax.class, new NumberMaxFactory<>());
}
@Override
protected TextFormatter<N> getDefaultFormatter(final FieldAccessor field, final Configuration config) {
final Optional<NumberFormatWrapper<N>> formatter = createFormatter(field, config);
if(formatter.isPresent()) {
return formatter.get();
} else {
return createSimpleFormatter(field, config);
}
}
/**
* 数値のフォーマッタを作成する。
* <p>アノテーション{@link CsvNumberFormat}の値を元に作成します。</p>
* @param field フィールド情報
* @param config システム設定
* @return アノテーション{@link CsvNumberFormat}が付与されていない場合は、空を返す。
*/
@SuppressWarnings("unchecked")
protected Optional<NumberFormatWrapper<N>> createFormatter(final FieldAccessor field, final Configuration config) {
final Optional<CsvNumberFormat> formatAnno = field.getAnnotation(CsvNumberFormat.class);
if(!formatAnno.isPresent()) {
return Optional.empty();
}
final String pattern = formatAnno.get().pattern();
if(pattern.isEmpty()) {
return Optional.empty();
}
final boolean lenient = formatAnno.get().lenient();
final Locale locale = Utils.getLocale(formatAnno.get().locale());
final Optional<Currency> currency = formatAnno.get().currency().isEmpty() ? Optional.empty()
: Optional.of(Currency.getInstance(formatAnno.get().currency()));
final RoundingMode roundingMode = formatAnno.get().rounding();
final DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
final DecimalFormat formatter = new DecimalFormat(pattern, symbols);
formatter.setParseBigDecimal(true);
formatter.setRoundingMode(roundingMode);
currency.ifPresent(c -> formatter.setCurrency(c));
final NumberFormatWrapper<N> wrapper = new NumberFormatWrapper<>(formatter, (Class<N>)field.getType(), lenient);
wrapper.setValidationMessage(formatAnno.get().message());
return Optional.of(wrapper);
}
/**
* アノテーション{@link CsvNumberFormat}の指定がないときなどの書式のない数値のフォーマッタの作成。
* <p>{@link #createFormatter(FieldAccessor, Configuration)}で結果が空の時に使用する。</p>
*
* @param field フィールド情報
* @param config システム設定
* @return
*/
@SuppressWarnings("unchecked")
protected SimpleNumberFormatter<N> createSimpleFormatter(final FieldAccessor field, final Configuration config) {
final Optional<CsvNumberFormat> formatAnno = field.getAnnotation(CsvNumberFormat.class);
if(!formatAnno.isPresent()) {
return new SimpleNumberFormatter<>((Class<N>)field.getType(), false);
}
final boolean lenient = formatAnno.get().lenient();
final RoundingMode roundingMode = formatAnno.get().rounding();
final int precision = formatAnno.get().precision();
final SimpleNumberFormatter<N> formatter;
if(precision >= 0) {
formatter = new SimpleNumberFormatter<>((Class<N>)field.getType(), lenient, new MathContext(precision, roundingMode));
} else {
formatter = new SimpleNumberFormatter<>((Class<N>)field.getType(), lenient);
}
formatter.setValidationMessage(formatAnno.get().message());
return formatter;
}
}