CellConverterFactorySupport.java

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

  2. import java.lang.reflect.Method;
  3. import java.util.Collections;
  4. import java.util.Optional;

  5. import com.gh.mygreen.xlsmapper.AnnotationInvalidException;
  6. import com.gh.mygreen.xlsmapper.Configuration;
  7. import com.gh.mygreen.xlsmapper.annotation.XlsCellOption;
  8. import com.gh.mygreen.xlsmapper.annotation.XlsDefaultValue;
  9. import com.gh.mygreen.xlsmapper.annotation.XlsFormula;
  10. import com.gh.mygreen.xlsmapper.annotation.XlsTrim;
  11. import com.gh.mygreen.xlsmapper.expression.ExpressionEvaluationException;
  12. import com.gh.mygreen.xlsmapper.fieldaccessor.FieldAccessor;
  13. import com.gh.mygreen.xlsmapper.localization.MessageBuilder;
  14. import com.gh.mygreen.xlsmapper.textformatter.TextFormatter;
  15. import com.gh.mygreen.xlsmapper.textformatter.TextParseException;
  16. import com.gh.mygreen.xlsmapper.util.Utils;

  17. /**
  18.  * {@link CellConverter}を作成するための抽象クラス。
  19.  *
  20.  * @since 2.0
  21.  * @author T.TSUCHIE
  22.  *
  23.  */
  24. public abstract class CellConverterFactorySupport<T>  {

  25.     /**
  26.      * 引数で指定したCellConverterに対して、トリムなどの共通の設定を行う。
  27.      * @param cellConverter 設定を行うCellConverter
  28.      * @param field フィールド情報
  29.      * @param config システム設定情報
  30.      */
  31.     protected void setupCellConverter(final BaseCellConverter<T> cellConverter, final FieldAccessor field, final Configuration config) {

  32.         final TextFormatter<T> textFormatter = createTextFormatter(field, config);
  33.         cellConverter.setTextFormatter(textFormatter);

  34.         // トリムの設定
  35.         final Optional<XlsTrim> trimAnno = field.getAnnotation(XlsTrim.class);
  36.         final boolean trimmed = trimAnno.map(anno -> true).orElse(false);

  37.         cellConverter.setTrimmed(trimmed);

  38.         // 初期値の設定
  39.         final Optional<XlsDefaultValue> defaultValueAnno = field.getAnnotation(XlsDefaultValue.class);
  40.         defaultValueAnno.ifPresent(anno -> {
  41.             String text = Utils.trim(anno.value(), trimmed);

  42.             try {
  43.                 T defaultValue = textFormatter.parse(text);
  44.                 cellConverter.setDefaultValue(defaultValue, anno.cases());

  45.             } catch(TextParseException e) {
  46.                 throw new AnnotationInvalidException(anno, MessageBuilder.create("anno.XlsDefaultValue.failParse")
  47.                         .var("property", field.getNameWithClass())
  48.                         .var("defaultValue", text)
  49.                         .varWithClass("type", field.getType())
  50.                         .format(), e);
  51.             }
  52.         });

  53.         // セルの書式の設定
  54.         final Optional<XlsCellOption> cellOptionAnno = field.getAnnotation(XlsCellOption.class);
  55.         cellOptionAnno.ifPresent(anno -> {
  56.             cellConverter.setShrinktToFit(anno.shrinkToFit());
  57.             cellConverter.setWrapText(anno.wrapText());
  58.             cellConverter.setIndent(anno.indent());
  59.             cellConverter.setHorizontalAlignment(anno.horizontalAlign().poiAlignType());
  60.             cellConverter.setVerticalAlignment(anno.verticalAlign().poiAlignType());
  61.         });

  62.         // 数式の設定
  63.         final Optional<XlsFormula> formulaAnno = field.getAnnotation(XlsFormula.class);
  64.         formulaAnno.ifPresent(anno -> {
  65.             CellFormulaHandler formulaHandler = createCellFormulaHandler(anno, field, config);
  66.             cellConverter.setFormulaHandler(formulaHandler);

  67.         });

  68.         // 各個別の設定
  69.         setupCustom(cellConverter, field, config);

  70.     }

  71.     /**
  72.      * 各個別に、Converterの設定を行う。
  73.      * @param cellConverter 組み立てるCellConverterのインスタンス
  74.      * @param field フィールド情報
  75.      * @param config システム情報
  76.      */
  77.     protected abstract void setupCustom(BaseCellConverter<T> cellConverter, FieldAccessor field, Configuration config);

  78.     /**
  79.      * {@link TextFormatter}のインスタンスを作成する。
  80.      * @param field フィールド情報
  81.      * @param config システム情報
  82.      * @return {@link TextFormatter}のインスタンス
  83.      */
  84.     protected abstract TextFormatter<T> createTextFormatter(FieldAccessor field, Configuration config);

  85.     /**
  86.      * 数式を処理する{@link CellFormulaHandler}を作成する。
  87.      * @param formulaAnno 数式のアノテーション
  88.      * @param field フィールド情報
  89.      * @param config システム情報
  90.      * @return {@link CellFormulaHandler}のインスタンス
  91.      */
  92.     protected CellFormulaHandler createCellFormulaHandler(final XlsFormula formulaAnno, final FieldAccessor field, final Configuration config) {

  93.         if(!formulaAnno.value().isEmpty()) {
  94.             final String formulaExpression = formulaAnno.value();
  95.             try {
  96.                 // EL式として正しいか検証する
  97.                 config.getFormulaFormatter().interpolate(formulaExpression, Collections.emptyMap());

  98.             } catch(ExpressionEvaluationException e) {
  99.                 throw new AnnotationInvalidException(formulaAnno, MessageBuilder.create("anno.attr.invalidEL")
  100.                         .var("property", field.getNameWithClass())
  101.                         .varWithAnno("anno", XlsFormula.class)
  102.                         .var("attrName", "value")
  103.                         .var("attrValue", formulaExpression)
  104.                         .format());
  105.             }

  106.             CellFormulaHandler handler = new CellFormulaHandler(formulaExpression);
  107.             handler.setPrimaryFormula(formulaAnno.primary());
  108.             return handler;

  109.         } else if(!formulaAnno.methodName().isEmpty()) {
  110.             // 戻り値が文字列の数式を返すメソッドを探す
  111.             final Class<?> targetClass = field.getDeclaringClass();
  112.             Method method = null;
  113.             for(Method m : targetClass.getDeclaredMethods()) {
  114.                 if(m.getName().equals(formulaAnno.methodName())
  115.                         && m.getReturnType().equals(String.class)) {
  116.                     method = m;
  117.                     break;
  118.                 }
  119.             }

  120.             if(method == null) {
  121.                 throw new AnnotationInvalidException(formulaAnno, MessageBuilder.create("anno.attr.notFoundMethod")
  122.                         .var("property", field.getNameWithClass())
  123.                         .varWithAnno("anno", XlsFormula.class)
  124.                         .var("attrName", "methodName")
  125.                         .var("attrValue", formulaAnno.methodName())
  126.                         .varWithClass("definedClass", targetClass)
  127.                         .format());
  128.             }

  129.             method.setAccessible(true);
  130.             CellFormulaHandler handler = new CellFormulaHandler(method);
  131.             handler.setPrimaryFormula(formulaAnno.primary());
  132.             return handler;

  133.         } else {
  134.             throw new AnnotationInvalidException(formulaAnno, MessageBuilder.create("anno.attr.required.any")
  135.                     .var("property", field.getNameWithClass())
  136.                     .varWithAnno("anno", XlsFormula.class)
  137.                     .varWithArrays("attrNames", "value", "methodName")
  138.                     .format());
  139.         }

  140.     }

  141. }