package com.gh.mygreen.xlsmapper.cellconvert.converter; import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; 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.XlsBooleanConverter; 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.TypeBindException; import com.gh.mygreen.xlsmapper.fieldprocessor.FieldAdaptor; /** * Boolean/boolean型を処理するConverter. * * @version 1.5 * @author T.TSUCHIE * */ public class BooleanCellConverter extends AbstractCellConverter<Boolean> { @Override public Boolean toObject(final Cell cell, final FieldAdaptor adaptor, final XlsMapperConfig config) throws TypeBindException { final XlsConverter converterAnno = adaptor.getLoadingAnnotation(XlsConverter.class); final XlsBooleanConverter anno = getLoadingAnnotation(adaptor); if(cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { return cell.getBooleanCellValue(); } else { String cellValue = POIUtils.getCellContents(cell, config.getCellFormatter()); cellValue = Utils.trim(cellValue, converterAnno); cellValue = Utils.getDefaultValueIfEmpty(cellValue, converterAnno); final Boolean result = convertFromString(cellValue, anno); if(result == null && Utils.isNotEmpty(cellValue)) { // 値が入っていて変換できない場合 throw newTypeBindException(cell, adaptor, cellValue) .addAllMessageVars(createTypeErrorMessageVars(anno)); } if(result != null) { return result; } } if(adaptor.getTargetClass().isPrimitive()) { return Boolean.FALSE; } return null; } /** * 型変換エラー時のメッセージ変数の作成 */ private Map<String, Object> createTypeErrorMessageVars(final XlsBooleanConverter anno) { final Map<String, Object> vars = new LinkedHashMap<>(); vars.put("candidateValues", Utils.join(getLoadingAvailableValue(anno), ", ")); vars.put("loadForTrue", Utils.join(anno.loadForTrue(), ", ")); vars.put("loadForFalse", Utils.join(anno.loadForFalse(), ", ")); vars.put("saveAsTrue", anno.saveAsTrue()); vars.put("saveAsFalse", anno.saveAsFalse()); vars.put("ignoreCase", anno.ignoreCase()); vars.put("failToFalse", anno.failToFalse()); return vars; } private XlsBooleanConverter getDefaultBooleanConverterAnnotation() { return new XlsBooleanConverter() { @Override public Class<? extends Annotation> annotationType() { return XlsBooleanConverter.class; } @Override public String saveAsTrue() { return "true"; } @Override public String saveAsFalse() { return "false"; } @Override public boolean ignoreCase() { return true; } @Override public String[] loadForTrue() { return new String[]{"true", "1", "yes", "on", "y", "t"}; } @Override public String[] loadForFalse() { return new String[]{"false", "0", "no", "off", "f", "n"}; } @Override public boolean failToFalse() { return false; } }; } private XlsBooleanConverter getLoadingAnnotation(final FieldAdaptor adaptor) { XlsBooleanConverter anno = adaptor.getLoadingAnnotation(XlsBooleanConverter.class); if(anno == null) { anno = getDefaultBooleanConverterAnnotation(); } return anno; } private XlsBooleanConverter getSavingAnnotation(final FieldAdaptor adaptor) { XlsBooleanConverter anno = adaptor.getSavingAnnotation(XlsBooleanConverter.class); if(anno == null) { anno = getDefaultBooleanConverterAnnotation(); } return anno; } /** * 読み込み時の入力の候補となる値を取得する * @param anno * @return */ private Collection<String> getLoadingAvailableValue(final XlsBooleanConverter anno) { final Set<String> values = new LinkedHashSet<String>(); values.addAll(Arrays.asList(anno.loadForTrue())); values.addAll(Arrays.asList(anno.loadForFalse())); return values; } private Boolean convertFromString(final String value, final XlsBooleanConverter anno) { for(String trueValues : anno.loadForTrue()) { if(anno.ignoreCase() && value.equalsIgnoreCase(trueValues)) { return Boolean.TRUE; } else if(!anno.ignoreCase() && value.equals(trueValues)) { return Boolean.TRUE; } } for(String falseValues : anno.loadForFalse()) { if(anno.ignoreCase() && value.equalsIgnoreCase(falseValues)) { return Boolean.FALSE; } else if(!anno.ignoreCase() && value.equals(falseValues)) { return Boolean.FALSE; } } // 変換できない場合に強制的にエラーとする場合 if(anno.failToFalse()) { return Boolean.FALSE; } return null; } @Override public Cell toCell(final FieldAdaptor adaptor, final Boolean 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 XlsBooleanConverter anno = getSavingAnnotation(adaptor); final XlsFormula formulaAnno = adaptor.getSavingAnnotation(XlsFormula.class); final boolean primaryFormula = formulaAnno == null ? false : formulaAnno.primary(); final Cell cell = POIUtils.getCell(sheet, column, row); // セルの書式設定 if(converterAnno != null) { POIUtils.wrapCellText(cell, converterAnno.wrapText()); POIUtils.shrinkToFit(cell, converterAnno.shrinkToFit()); } Boolean value = targetValue; // デフォルト値から値を設定する if(value == null && Utils.hasDefaultValue(converterAnno)) { value = convertFromString(Utils.getDefaultValue(converterAnno), anno); // 初期値が設定されているが、変換できないような時はエラーとする if(value == null) { throw newTypeBindException(cell, adaptor, Utils.getDefaultValue(converterAnno)) .addAllMessageVars(createTypeErrorMessageVars(anno)); } } if(value != null && !primaryFormula) { if(anno.saveAsTrue().equalsIgnoreCase("true") && anno.saveAsTrue().equalsIgnoreCase("false") && cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { // テンプレートのセルの書式がbooleanの場合はそのまま設定する cell.setCellValue(value); } else if(value) { cell.setCellValue(anno.saveAsTrue()); } else { cell.setCellValue(anno.saveAsFalse()); } } else if(formulaAnno != null) { Utils.setupCellFormula(adaptor, formulaAnno, config, cell, targetBean); } else { cell.setCellType(Cell.CELL_TYPE_BLANK); } return cell; } }