package com.gh.mygreen.xlsmapper.cellconvert.converter;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import com.gh.mygreen.xlsmapper.POIUtils;
import com.gh.mygreen.xlsmapper.Utils;
import com.gh.mygreen.xlsmapper.XlsMapperConfig;
import com.gh.mygreen.xlsmapper.XlsMapperException;
import com.gh.mygreen.xlsmapper.annotation.XlsArrayConverter;
import com.gh.mygreen.xlsmapper.annotation.XlsConverter;
import com.gh.mygreen.xlsmapper.annotation.XlsFormula;
import com.gh.mygreen.xlsmapper.cellconvert.AbstractCellConverter;
import com.gh.mygreen.xlsmapper.cellconvert.ConversionException;
import com.gh.mygreen.xlsmapper.cellconvert.DefaultItemConverter;
import com.gh.mygreen.xlsmapper.cellconvert.ItemConverter;
import com.gh.mygreen.xlsmapper.fieldprocessor.FieldAdaptor;
/**
* {@link List}型のConverter。
*
* @version 1.5
* @author T.TSUCHIE
*
*/
@SuppressWarnings("rawtypes")
public class ListCellConverter extends AbstractCellConverter<List> {
@Override
public List toObject(final Cell cell, final FieldAdaptor adaptor, final XlsMapperConfig config)
throws XlsMapperException {
final XlsConverter converterAnno = adaptor.getLoadingAnnotation(XlsConverter.class);
final XlsArrayConverter anno = getLoadingAnnotation(adaptor);
String cellValue = POIUtils.getCellContents(cell, config.getCellFormatter());
cellValue = Utils.getDefaultValueIfEmpty(cellValue, converterAnno);
Class<?> fieldClass = adaptor.getTargetClass();
Class<?> itemClass = anno.itemClass();
if(itemClass == Object.class) {
itemClass = adaptor.getLoadingGenericClassType();
}
try {
List list = convertList(cellValue, itemClass, converterAnno, anno, config);
if(List.class.isAssignableFrom(fieldClass)) {
list = (List) Utils.convertListToCollection(list, (Class<Collection>)fieldClass, config.getBeanFactory());
}
return list;
} catch(NumberFormatException e) {
throw newTypeBindException(e, cell, adaptor, cellValue)
.addAllMessageVars(createTypeErrorMessageVars(anno));
}
}
@SuppressWarnings("unchecked")
protected List<?> convertList(final String value, Class<?> itemClass, final XlsConverter converterAnno,
final XlsArrayConverter anno, final XlsMapperConfig config) throws ConversionException {
final String[] split = value.split(anno.separator());
final List list = new ArrayList<>();
if(split.length == 0 || value.isEmpty()) {
return list;
}
final ItemConverter itemConverter = getItemConverter(anno.itemConverterClass(), config);
for(String item : split) {
String strVal = Utils.trim(item, converterAnno);
if(anno.ignoreEmptyItem() && Utils.isEmpty(strVal)) {
continue;
}
list.add(itemConverter.convertToObject(strVal, itemClass));
}
return list;
}
/**
* リストの要素の値を変換するクラスを取得する。
* @param converterClass
* @param config
* @return
*/
ItemConverter getItemConverter(Class<? extends ItemConverter> converterClass, final XlsMapperConfig config) {
if(converterClass.isAssignableFrom(DefaultItemConverter.class)) {
return config.getItemConverter();
} else {
return (ItemConverter) config.getBeanFactory().create(converterClass);
}
}
protected XlsArrayConverter getDefaultArrayConverterAnnotation() {
return new XlsArrayConverter() {
@Override
public Class<? extends Annotation> annotationType() {
return XlsArrayConverter.class;
}
@Override
public String separator() {
return ",";
}
@Override
public Class<?> itemClass() {
return Object.class;
}
@Override
public boolean ignoreEmptyItem() {
return false;
}
@Override
public Class<? extends ItemConverter> itemConverterClass() {
return DefaultItemConverter.class;
}
};
}
/**
* 型変換エラー時のメッセージ変数の作成
*/
private Map<String, Object> createTypeErrorMessageVars(final XlsArrayConverter anno) {
final Map<String, Object> vars = new LinkedHashMap<>();
vars.put("separator", anno.separator());
vars.put("ignoreEmptyItem", anno.ignoreEmptyItem());
vars.put("itemConverter", Utils.convertToString(anno.itemConverterClass()));
return vars;
}
protected XlsArrayConverter getLoadingAnnotation(final FieldAdaptor adaptor) {
XlsArrayConverter anno = adaptor.getLoadingAnnotation(XlsArrayConverter.class);
if(anno == null) {
anno = getDefaultArrayConverterAnnotation();
}
return anno;
}
protected XlsArrayConverter getSavingAnnotation(final FieldAdaptor adaptor) {
XlsArrayConverter anno = adaptor.getSavingAnnotation(XlsArrayConverter.class);
if(anno == null) {
anno = getDefaultArrayConverterAnnotation();
}
return anno;
}
@Override
public Cell toCell(final FieldAdaptor adaptor, final List targetValue, final Object targetBean,
final Sheet sheet, final int column, final int row,
final XlsMapperConfig config) throws XlsMapperException {
final XlsConverter converterAnno = adaptor.getSavingAnnotation(XlsConverter.class);
final XlsArrayConverter anno = getSavingAnnotation(adaptor);
final XlsFormula formulaAnno = adaptor.getSavingAnnotation(XlsFormula.class);
final boolean primaryFormula = formulaAnno == null ? false : formulaAnno.primary();
Class<?> itemClass = anno.itemClass();
if(itemClass == Object.class) {
itemClass = adaptor.getSavingGenericClassType();
}
final Cell cell = POIUtils.getCell(sheet, column, row);
// セルの書式設定
if(converterAnno != null) {
POIUtils.wrapCellText(cell, converterAnno.wrapText());
POIUtils.shrinkToFit(cell, converterAnno.shrinkToFit());
}
List value = targetValue;
// デフォルト値から値を設定する
if(Utils.isEmpty(value) && Utils.hasDefaultValue(converterAnno)) {
value = convertList(Utils.getDefaultValue(converterAnno), itemClass, converterAnno, anno, config);
}
if(Utils.isNotEmpty(value) && !primaryFormula) {
final boolean trim = (converterAnno == null ? false : converterAnno.trim());
final ItemConverter itemConverter = getItemConverter(anno.itemConverterClass(), config);
final String cellValue = Utils.join(value, anno.separator(), anno.ignoreEmptyItem(), trim, itemConverter);
cell.setCellValue(cellValue);
} else if(formulaAnno != null) {
Utils.setupCellFormula(adaptor, formulaAnno, config, cell, targetBean);
} else {
cell.setCellType(Cell.CELL_TYPE_BLANK);
}
return cell;
}
}