package com.github.mygreen.supercsv.cellprocessor; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.supercsv.cellprocessor.ift.CellProcessor; import com.github.mygreen.supercsv.annotation.conversion.CsvConversion; import com.github.mygreen.supercsv.builder.BuildCase; import com.github.mygreen.supercsv.builder.Configuration; import com.github.mygreen.supercsv.builder.FieldAccessor; import com.github.mygreen.supercsv.cellprocessor.format.TextFormatter; import com.github.mygreen.supercsv.util.Utils; /** * フィールドに設定されている変換用のアノテーションをハンドリングして、{@link CellProcessor}を作成するクラス。 * * @since 2.0 * @author T.TSUCHIE * */ public class ConversionProcessorHandler implements ProcessorFactory { private static Logger logger = LoggerFactory.getLogger(ConversionProcessorHandler.class); private final Map<Class<? extends Annotation>, ConversionProcessorFactory<?>> factoryMap = new HashMap<>(); @SuppressWarnings({"rawtypes", "unchecked"}) @Override public Optional<CellProcessor> create(final Optional<CellProcessor> processor, final FieldAccessor field, final TextFormatter<?> formatter, final Configuration config, final BuildCase buildCase, final Class<?>[] groups) { // 変換用のアノテーションを取得する final List<Annotation> annos = field.getAnnotationsByGroup(groups).stream() .filter(anno -> anno.annotationType().getAnnotation(CsvConversion.class) != null) .filter(anno -> Utils.containsBuildCase(anno, buildCase)) .collect(Collectors.toList()); Collections.reverse(annos); Optional<CellProcessor> cp = processor; for(Annotation anno : annos) { final CsvConversion conversionAnno = anno.annotationType().getAnnotation(CsvConversion.class); if(factoryMap.containsKey(anno.annotationType())) { // 登録済みのものから取得する。 final ConversionProcessorFactory factory = factoryMap.get(anno.annotationType()); cp = factory.create(anno, cp, field, formatter, config); } else if(conversionAnno.value().length > 0) { /* * アノテーション「@CsvConversion」が指定されている場合、クラスのインスタンスを作成する。 * ・定義上、複数指定可能になっているたが、先頭のクラスのみインスタンス化する。 */ for(Class<? extends ConversionProcessorFactory> factoryClass : conversionAnno.value()) { final ConversionProcessorFactory factory = (ConversionProcessorFactory) config.getBeanFactory().create(factoryClass); cp = factory.create(anno, cp, field, formatter, config); } } else { // factoryが見つからない場合 logger.warn("Not found {} with the annotation {}.", ConversionProcessorFactory.class.getSimpleName(), anno.getClass()); } } return cp; } /** * アノテーションに対する{@link ConversionProcessorFactory}を登録する。 * * @param <A> アノテーションのタイプ * @param anno 関連づけるアノテーション * @param factory 制約の{@link CellProcessor}を作成する{@link ConversionProcessorFactory}の実装。 */ public <A extends Annotation> void register(final Class<A> anno, final ConversionProcessorFactory<A> factory) { factoryMap.put(anno, factory); } /** * 登録されている{@link ConversionProcessorFactory}情報を取得する。 * @return アノテーションと対応する{@link ConversionProcessorFactory}のマップ。 */ public Set<Map.Entry<Class<? extends Annotation>, ConversionProcessorFactory<?>>> getEntrySet() { return factoryMap.entrySet(); } }