You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
8.3 KiB

package com.alibaba.excel.metadata.property;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.converters.AutoConverter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.StringUtils;
/**
* Define the header attribute of excel
*
* @author jipengfei
*/
public class ExcelHeadProperty {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelHeadProperty.class);
/**
* Custom class
*/
private Class headClazz;
/**
* The types of head
*/
private HeadKindEnum headKind;
/**
* The number of rows in the line with the most rows
*/
private int headRowNumber;
/**
* Configuration header information
*/
private Map<Integer, Head> headMap;
/**
* Configuration column information
*/
private Map<Integer, ExcelContentProperty> contentPropertyMap;
public ExcelHeadProperty(Class headClazz, List<List<String>> head, Boolean convertAllFiled) {
this.headClazz = headClazz;
headMap = new TreeMap<Integer, Head>();
contentPropertyMap = new TreeMap<Integer, ExcelContentProperty>();
headKind = HeadKindEnum.NONE;
headRowNumber = 0;
if (head != null && !head.isEmpty()) {
for (int i = 0; i < head.size(); i++) {
headMap.put(i, new Head(i, null, head.get(i), Boolean.FALSE));
contentPropertyMap.put(i, null);
}
headKind = HeadKindEnum.STRING;
} else {
// convert headClazz to head
initColumnProperties(convertAllFiled);
}
initHeadRowNumber();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is {}", headKind);
}
if (!hasHead()) {
LOGGER.warn(
"The table has no header set and all annotations will not be read.If you want to use annotations, please use set head class in ExcelWriterBuilder/ExcelWriterSheetBuilder/ExcelWriterTableBuilder");
}
}
private void initHeadRowNumber() {
headRowNumber = 0;
for (Head head : headMap.values()) {
List<String> list = head.getHeadNameList();
if (list != null && list.size() > headRowNumber) {
headRowNumber = list.size();
}
}
for (Head head : headMap.values()) {
List<String> list = head.getHeadNameList();
if (list != null && !list.isEmpty() && list.size() < headRowNumber) {
int lack = headRowNumber - list.size();
int last = list.size() - 1;
for (int i = 0; i < lack; i++) {
list.add(list.get(last));
}
}
}
}
private void initColumnProperties(Boolean convertAllFiled) {
if (headClazz == null) {
return;
}
List<Field> fieldList = new ArrayList<Field>();
Class tempClass = headClazz;
// When the parent class is null, it indicates that the parent class (Object class) has reached the top
// level.
while (tempClass != null) {
fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
// Get the parent class and give it to yourself
tempClass = tempClass.getSuperclass();
}
// Screening of field
List<Field> defaultFieldList = new ArrayList<Field>();
Map<Integer, Field> customFiledMap = new TreeMap<Integer, Field>();
for (Field field : fieldList) {
ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
if (excelIgnore != null) {
continue;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelProperty == null && convertAllFiled != null && !convertAllFiled) {
continue;
}
if (excelProperty == null || excelProperty.index() < 0) {
defaultFieldList.add(field);
continue;
}
if (customFiledMap.containsKey(excelProperty.index())) {
throw new ExcelGenerateException("The index of " + customFiledMap.get(excelProperty.index()).getName()
+ " and " + field.getName() + " must be inconsistent");
}
customFiledMap.put(excelProperty.index(), field);
}
int index = 0;
for (Field field : defaultFieldList) {
while (customFiledMap.containsKey(index)) {
initOneColumnProperty(index, customFiledMap.get(index), Boolean.TRUE);
customFiledMap.remove(index);
index++;
}
initOneColumnProperty(index, field, Boolean.FALSE);
index++;
}
for (Map.Entry<Integer, Field> entry : customFiledMap.entrySet()) {
initOneColumnProperty(index, entry.getValue(), Boolean.FALSE);
index++;
}
headKind = HeadKindEnum.CLASS;
}
private void initOneColumnProperty(int index, Field field, Boolean forceIndex) {
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
List<String> tmpHeadList = new ArrayList<String>();
if (excelProperty != null) {
tmpHeadList = Arrays.asList(excelProperty.value());
} else {
tmpHeadList.add(field.getName());
}
if (tmpHeadList.isEmpty() || StringUtils.isEmpty(tmpHeadList.get(0))) {
tmpHeadList.add(field.getName());
}
Head head = new Head(index, field.getName(), tmpHeadList, forceIndex);
ExcelContentProperty excelContentProperty = new ExcelContentProperty();
if (excelProperty != null && excelProperty.converter() != null) {
Class<? extends Converter> convertClazz = excelProperty.converter();
if (convertClazz != AutoConverter.class) {
try {
Converter converter = convertClazz.newInstance();
excelContentProperty.setConverter(converter);
} catch (Exception e) {
throw new ExcelCommonException("Can not instance custom converter:" + convertClazz.getName());
}
}
}
excelContentProperty.setHead(head);
excelContentProperty.setField(field);
excelContentProperty
.setDateTimeFormatProperty(DateTimeFormatProperty.build(field.getAnnotation(DateTimeFormat.class)));
excelContentProperty
.setNumberFormatProperty(NumberFormatProperty.build(field.getAnnotation(NumberFormat.class)));
headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty);
}
public Class getHeadClazz() {
return headClazz;
}
public void setHeadClazz(Class headClazz) {
this.headClazz = headClazz;
}
public HeadKindEnum getHeadKind() {
return headKind;
}
public void setHeadKind(HeadKindEnum headKind) {
this.headKind = headKind;
}
public boolean hasHead() {
return headKind != HeadKindEnum.NONE;
}
public int getHeadRowNumber() {
return headRowNumber;
}
public void setHeadRowNumber(int headRowNumber) {
this.headRowNumber = headRowNumber;
}
public Map<Integer, Head> getHeadMap() {
return headMap;
}
public void setHeadMap(Map<Integer, Head> headMap) {
this.headMap = headMap;
}
public Map<Integer, ExcelContentProperty> getContentPropertyMap() {
return contentPropertyMap;
}
public void setContentPropertyMap(Map<Integer, ExcelContentProperty> contentPropertyMap) {
this.contentPropertyMap = contentPropertyMap;
}
}