com.supwisdom.spreadsheet.mapper.w2o.DefaultSheet2ObjectComposer Maven / Gradle / Ivy
package com.supwisdom.spreadsheet.mapper.w2o;
import com.supwisdom.spreadsheet.mapper.model.core.Cell;
import com.supwisdom.spreadsheet.mapper.model.core.Row;
import com.supwisdom.spreadsheet.mapper.model.core.Sheet;
import com.supwisdom.spreadsheet.mapper.model.meta.FieldMeta;
import com.supwisdom.spreadsheet.mapper.model.meta.SheetMeta;
import com.supwisdom.spreadsheet.mapper.w2o.listener.*;
import com.supwisdom.spreadsheet.mapper.w2o.setter.DefaultPropertySetter;
import com.supwisdom.spreadsheet.mapper.w2o.setter.PropertySetter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* 默认的{@link Sheet2ObjectComposer}
* Created by hanwen on 15-12-16.
*/
public class DefaultSheet2ObjectComposer implements Sheet2ObjectComposer {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSheet2ObjectComposer.class);
private ObjectFactory objectFactory;
private SheetProcessListener sheetProcessListener = new NoopSheetProcessListener<>();
private RowProcessListener rowProcessListener = new NoopRowProcessListener<>();
private CellProcessListener cellProcessListener = new NoopCellProcessListener<>();
private LinkedHashMap> field2PropertySetter = new LinkedHashMap<>();
private DefaultPropertySetter defaultPropertySetter = new DefaultPropertySetter();
private Set ignoreFields = new HashSet<>();
@Override
public void ignoreFields(String field, String... otherFields) {
ignoreFields.add(field);
for (String otherField : otherFields) {
ignoreFields.add(otherField);
}
}
@Override
public Sheet2ObjectComposer addPropertySetter(PropertySetter propertySetter) {
if (propertySetter == null) {
throw new IllegalArgumentException("PropertySetter can not be null");
}
String matchField = propertySetter.getMatchField();
if (StringUtils.isBlank(matchField)) {
throw new IllegalArgumentException("PropertySetter's matchField can not be blank");
}
if (field2PropertySetter.containsKey(matchField)) {
throw new IllegalArgumentException("Already has PropertySetter for field[" + matchField + "]");
}
field2PropertySetter.put(matchField, propertySetter);
return this;
}
@Override
public Sheet2ObjectComposer setObjectFactory(ObjectFactory objectFactory) {
if (objectFactory == null) {
throw new IllegalArgumentException("Object factory can not be null");
}
this.objectFactory = objectFactory;
return this;
}
@Override
public Sheet2ObjectComposer setSheetProcessorListener(SheetProcessListener sheetProcessListener) {
if (sheetProcessListener == null) {
throw new IllegalArgumentException("Sheet process listener can not be null");
}
this.sheetProcessListener = sheetProcessListener;
return this;
}
@Override
public Sheet2ObjectComposer setRowProcessorListener(RowProcessListener rowProcessListener) {
if (rowProcessListener == null) {
throw new IllegalArgumentException("Row process listener can not be null");
}
this.rowProcessListener = rowProcessListener;
return this;
}
@Override
public Sheet2ObjectComposer setCellProcessorListener(CellProcessListener cellProcessListener) {
if (cellProcessListener == null) {
throw new IllegalArgumentException("Cell process listener can not be null");
}
this.cellProcessListener = cellProcessListener;
return this;
}
/**
* 执行顺序是这样的:
*
* - 通知{@link SheetProcessListener}开始
* - 开始遍历Row
* - 调用{@link ObjectFactory}获得要被设置值的Object
* - 通知{@link RowProcessListener}开始
* - 开始遍历Cell
* - 找到对应的FieldMeta
* - 通知{@link CellProcessListener}开始
* - 调用{@link PropertySetter}给Object的某个field设置值
* - 通知{@link CellProcessListener}结束
* - 结束遍历Cell
* - 结束遍历Row,通知{@link RowProcessListener}结束
* - 通知{@link SheetProcessListener}结束
*
*/
@Override
public List compose(Sheet sheet, SheetMeta sheetMeta) {
if (objectFactory == null) {
throw new Workbook2ObjectComposeException("ObjectFactory not provided");
}
assertNoDuplicatedFieldMeta(sheetMeta);
List fieldMetas = sheetMeta.getFieldMetas();
Map columnIndex2fieldMeta = buildFieldMetaMap(fieldMetas);
List dataOfSheet = new ArrayList<>();
sheetProcessListener.before(sheet, sheetMeta);
for (int i = sheetMeta.getDataStartRowIndex(); i <= sheet.sizeOfRows(); i++) {
Row row = sheet.getRow(i);
T object = objectFactory.create(row, sheetMeta);
rowProcessListener.before(object, row, sheetMeta);
for (Cell cell : row.getCells()) {
FieldMeta fieldMeta = columnIndex2fieldMeta.get(cell.getIndex());
if (fieldMeta == null) {
// if missing field meta skip the cell(same column index with field meta)
LOGGER.debug(
"No field meta at row index:[" + cell.getIndex() + "], cell value:[" + cell.getValue() + "] ignored");
continue;
}
if (ignoreFields.contains(fieldMeta.getName())) {
// 当前fieldMeta在ignore field范围内
continue;
}
cellProcessListener.before(object, cell, fieldMeta);
PropertySetter propertySetter = field2PropertySetter.get(fieldMeta.getName());
if (propertySetter != null) {
propertySetter.setProperty(object, cell, fieldMeta);
} else {
defaultPropertySetter.setProperty(object, cell, fieldMeta);
}
cellProcessListener.after(object, cell, fieldMeta);
}
rowProcessListener.after(object, row, sheetMeta);
dataOfSheet.add(object);
}
sheetProcessListener.after(dataOfSheet, sheet, sheetMeta);
return dataOfSheet;
}
private Map buildFieldMetaMap(List fieldMetas) {
Map columnIndex2fieldMeta = new HashMap<>();
for (FieldMeta fieldMeta : fieldMetas) {
columnIndex2fieldMeta.put(fieldMeta.getColumnIndex(), fieldMeta);
}
return columnIndex2fieldMeta;
}
/**
* 检查不存在相同name的FieldMeta
*
* @param sheetMeta
*/
private void assertNoDuplicatedFieldMeta(SheetMeta sheetMeta) {
List fieldMetas = sheetMeta.getFieldMetas();
Set fieldNames = new HashSet<>(fieldMetas.size());
for (FieldMeta fieldMeta : fieldMetas) {
if (!fieldNames.add(fieldMeta.getName())) {
throw new Workbook2ObjectComposeException("SheetMeta contains duplicate FieldMeta [" + fieldMeta.getName() + "]");
}
}
}
}