com.alibaba.excel.util.ClassUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of excel-spring-boot-starter Show documentation
Show all versions of excel-spring-boot-starter Show documentation
easy and high performance excel
package com.alibaba.excel.util;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Holder;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import lombok.extern.slf4j.Slf4j;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Class utils
*
* @author Jiaju Zhuang
**/
@Slf4j
public class ClassUtils {
static {
log.debug("======[ClassUtils] 修复版被加载了=======");
}
private static final Map> FIELD_CACHE = new ConcurrentHashMap>();
public static void declaredFields(Class clazz, Map sortedAllFiledMap,
Map indexFiledMap, Map ignoreMap, Boolean convertAllFiled,
Boolean needIgnore, Holder holder) {
FieldCache fieldCache = getFieldCache(clazz, convertAllFiled);
if (fieldCache == null) {
return;
}
if (ignoreMap != null) {
ignoreMap.putAll(fieldCache.getIgnoreMap());
}
Map tempIndexFildMap = indexFiledMap;
if (tempIndexFildMap == null) {
tempIndexFildMap = new TreeMap();
}
tempIndexFildMap.putAll(fieldCache.getIndexFiledMap());
Map originSortedAllFiledMap = fieldCache.getSortedAllFiledMap();
if (!needIgnore) {
sortedAllFiledMap.putAll(originSortedAllFiledMap);
return;
}
// 获取到属性字段的最大index
int maxIndex = -1;
for (Integer filedIndex : originSortedAllFiledMap.keySet()) {
maxIndex = Math.max(filedIndex, maxIndex);
}
// 被忽略的属性数量
int ignoreNum = 0;
// 当有属性被忽略时,需要将其后面的所有属性 index 前移
for (int index = 0; index <= maxIndex; index++) {
Field field = originSortedAllFiledMap.get(index);
String name = field == null ? null : field.getName();
if (((WriteHolder) holder).ignore(name, index)) {
if (ignoreMap != null && name != null) {
ignoreMap.put(name, field);
}
tempIndexFildMap.remove(index);
ignoreNum++;
}
else if (field != null) {
int finalIndex = index - ignoreNum;
sortedAllFiledMap.put(finalIndex, field);
}
}
}
public static void declaredFields(Class clazz, Map sortedAllFiledMap, Boolean convertAllFiled,
Boolean needIgnore, WriteHolder writeHolder) {
declaredFields(clazz, sortedAllFiledMap, null, null, convertAllFiled, needIgnore, writeHolder);
}
private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) {
if (clazz == null) {
return null;
}
SoftReference fieldCacheSoftReference = FIELD_CACHE.get(clazz);
if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) {
return fieldCacheSoftReference.get();
}
synchronized (clazz) {
fieldCacheSoftReference = FIELD_CACHE.get(clazz);
if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) {
return fieldCacheSoftReference.get();
}
declaredFields(clazz, convertAllFiled);
}
return FIELD_CACHE.get(clazz).get();
}
private static void declaredFields(Class clazz, Boolean convertAllFiled) {
List tempFieldList = new ArrayList();
Class tempClass = clazz;
// When the parent class is null, it indicates that the parent class (Object
// class) has reached the top
// level.
while (tempClass != null && tempClass != BaseRowModel.class) {
Collections.addAll(tempFieldList, tempClass.getDeclaredFields());
// Get the parent class and give it to yourself
tempClass = tempClass.getSuperclass();
}
// Screening of field
Map> orderFiledMap = new TreeMap>();
Map indexFiledMap = new TreeMap();
Map ignoreMap = new HashMap(16);
ExcelIgnoreUnannotated excelIgnoreUnannotated = (ExcelIgnoreUnannotated) clazz
.getAnnotation(ExcelIgnoreUnannotated.class);
for (Field field : tempFieldList) {
declaredOneField(field, orderFiledMap, indexFiledMap, ignoreMap, excelIgnoreUnannotated, convertAllFiled);
}
FIELD_CACHE.put(clazz, new SoftReference(
new FieldCache(buildSortedAllFiledMap(orderFiledMap, indexFiledMap), indexFiledMap, ignoreMap)));
}
private static Map buildSortedAllFiledMap(Map> orderFiledMap,
Map indexFiledMap) {
Map sortedAllFiledMap = new HashMap(
(orderFiledMap.size() + indexFiledMap.size()) * 4 / 3 + 1);
Map tempIndexFiledMap = new HashMap(indexFiledMap);
int index = 0;
for (List fieldList : orderFiledMap.values()) {
for (Field field : fieldList) {
while (tempIndexFiledMap.containsKey(index)) {
sortedAllFiledMap.put(index, tempIndexFiledMap.get(index));
tempIndexFiledMap.remove(index);
index++;
}
sortedAllFiledMap.put(index, field);
index++;
}
}
sortedAllFiledMap.putAll(tempIndexFiledMap);
return sortedAllFiledMap;
}
private static void declaredOneField(Field field, Map> orderFiledMap,
Map indexFiledMap, Map ignoreMap,
ExcelIgnoreUnannotated excelIgnoreUnannotated, Boolean convertAllFiled) {
ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
if (excelIgnore != null) {
ignoreMap.put(field.getName(), field);
return;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
boolean noExcelProperty = excelProperty == null
&& ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null);
if (noExcelProperty) {
ignoreMap.put(field.getName(), field);
return;
}
boolean isStaticFinalOrTransient = (Modifier.isStatic(field.getModifiers())
&& Modifier.isFinal(field.getModifiers())) || Modifier.isTransient(field.getModifiers());
if (excelProperty == null && isStaticFinalOrTransient) {
ignoreMap.put(field.getName(), field);
return;
}
if (excelProperty != null && excelProperty.index() >= 0) {
if (indexFiledMap.containsKey(excelProperty.index())) {
throw new ExcelCommonException("The index of '" + indexFiledMap.get(excelProperty.index()).getName()
+ "' and '" + field.getName() + "' must be inconsistent");
}
indexFiledMap.put(excelProperty.index(), field);
return;
}
int order = Integer.MAX_VALUE;
if (excelProperty != null) {
order = excelProperty.order();
}
List orderFiledList = orderFiledMap.get(order);
if (orderFiledList == null) {
orderFiledList = new ArrayList();
orderFiledMap.put(order, orderFiledList);
}
orderFiledList.add(field);
}
private static class FieldCache {
private Map sortedAllFiledMap;
private Map indexFiledMap;
private Map ignoreMap;
public FieldCache(Map sortedAllFiledMap, Map indexFiledMap,
Map ignoreMap) {
this.sortedAllFiledMap = sortedAllFiledMap;
this.indexFiledMap = indexFiledMap;
this.ignoreMap = ignoreMap;
}
public Map getSortedAllFiledMap() {
return sortedAllFiledMap;
}
public Map getIndexFiledMap() {
return indexFiledMap;
}
public Map getIgnoreMap() {
return ignoreMap;
}
}
}