com.zhongweixian.excel.util.PoiReflectorUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of poi-api Show documentation
Show all versions of poi-api Show documentation
poi-api project for Spring Boot
The newest version!
package com.zhongweixian.excel.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ReflectPermission;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author [email protected]
* @Date 2017/11/5:22:45
*/
public class PoiReflectorUtil {
private static final Map, PoiReflectorUtil> CACHE_REFLECTOR = new ConcurrentHashMap, PoiReflectorUtil>();
private Map getMethods = new HashMap();
private Map setMethods = new HashMap();
private List fieldList = new ArrayList();
private Class> type;
private PoiReflectorUtil(Class> clazz) {
addGetMethods(clazz);
addFields(clazz);
addSetMethods(clazz);
}
public static PoiReflectorUtil forClass(Class> clazz) {
return new PoiReflectorUtil(clazz);
}
public static PoiReflectorUtil fromCache(Class> clazz) {
if (!CACHE_REFLECTOR.containsKey(clazz)) {
CACHE_REFLECTOR.put(clazz, new PoiReflectorUtil(clazz));
}
return CACHE_REFLECTOR.get(clazz);
}
private void addGetMethods(Class> cls) {
Map> conflictingGetters = new HashMap>();
Method[] methods = getClassMethods(cls);
for (Method method : methods) {
String name = method.getName();
if (name.startsWith("get") && name.length() > 3) {
if (method.getParameterTypes().length == 0) {
name = methodToProperty(name);
addMethodConflict(conflictingGetters, name, method);
}
} else if (name.startsWith("is") && name.length() > 2) {
if (method.getParameterTypes().length == 0) {
name = methodToProperty(name);
addMethodConflict(conflictingGetters, name, method);
}
}
}
resolveGetterConflicts(conflictingGetters);
}
private void resolveGetterConflicts(Map> conflictingGetters) {
for (String propName : conflictingGetters.keySet()) {
List getters = conflictingGetters.get(propName);
Iterator iterator = getters.iterator();
Method firstMethod = iterator.next();
if (getters.size() == 1) {
addGetMethod(propName, firstMethod);
} else {
Method getter = firstMethod;
Class> getterType = firstMethod.getReturnType();
while (iterator.hasNext()) {
Method method = iterator.next();
Class> methodType = method.getReturnType();
if (methodType.equals(getterType)) {
throw new RuntimeException(
"Illegal overloaded getter method with ambiguous type for property "
+ propName + " in class "
+ firstMethod.getDeclaringClass()
+ ". This breaks the JavaBeans "
+ "specification and can cause unpredicatble results.");
} else if (methodType.isAssignableFrom(getterType)) {
// OK getter type is descendant
} else if (getterType.isAssignableFrom(methodType)) {
getter = method;
getterType = methodType;
} else {
throw new RuntimeException(
"Illegal overloaded getter method with ambiguous type for property "
+ propName + " in class "
+ firstMethod.getDeclaringClass()
+ ". This breaks the JavaBeans "
+ "specification and can cause unpredicatble results.");
}
}
addGetMethod(propName, getter);
}
}
}
private void addGetMethod(String name, Method method) {
if (isValidPropertyName(name)) {
getMethods.put(name, method);
}
}
private void addSetMethods(Class> cls) {
Map> conflictingSetters = new HashMap>();
Method[] methods = getClassMethods(cls);
for (Method method : methods) {
String name = method.getName();
if (name.startsWith("set") && name.length() > 3) {
if (method.getParameterTypes().length == 1) {
name = methodToProperty(name);
addMethodConflict(conflictingSetters, name, method);
}
}
}
resolveSetterConflicts(conflictingSetters);
}
private static String methodToProperty(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {
name = name.substring(3);
} else {
throw new RuntimeException("Error parsing property name '" + name
+ "'. Didn't start with 'is', 'get' or 'set'.");
}
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
private void addMethodConflict(Map> conflictingMethods, String name,
Method method) {
List list = conflictingMethods.get(name);
if (list == null) {
list = new ArrayList();
conflictingMethods.put(name, list);
}
list.add(method);
}
private void resolveSetterConflicts(Map> conflictingSetters) {
for (String propName : conflictingSetters.keySet()) {
List setters = conflictingSetters.get(propName);
Method firstMethod = setters.get(0);
if (setters.size() == 1) {
addSetMethod(propName, firstMethod);
} else {
Iterator methods = setters.iterator();
Method setter = null;
while (methods.hasNext()) {
Method method = methods.next();
if (method.getParameterTypes().length == 1) {
setter = method;
break;
}
}
if (setter == null) {
throw new RuntimeException(
"Illegal overloaded setter method with ambiguous type for property "
+ propName + " in class "
+ firstMethod.getDeclaringClass()
+ ". This breaks the JavaBeans "
+ "specification and can cause unpredicatble results.");
}
addSetMethod(propName, setter);
}
}
}
private void addSetMethod(String name, Method method) {
if (isValidPropertyName(name)) {
setMethods.put(name, method);
}
}
private void addFields(Class> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (canAccessPrivateMethods()) {
try {
field.setAccessible(true);
} catch (Exception e) {
// Ignored. This is only a final precaution, nothing we can do.
}
}
if (field.isAccessible() && !"serialVersionUID".equalsIgnoreCase(field.getName())) {
this.fieldList.add(field);
}
}
if (clazz.getSuperclass() != null) {
addFields(clazz.getSuperclass());
}
}
private boolean isValidPropertyName(String name) {
return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
}
/*
* This method returns an array containing all methods
* declared in this class and any superclass.
* We use this method, instead of the simpler Class.getMethods(),
* because we want to look for private methods as well.
*
* @param cls The class
* @return An array containing all methods in this class
*/
private Method[] getClassMethods(Class> cls) {
HashMap uniqueMethods = new HashMap();
Class> currentClass = cls;
while (currentClass != null) {
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
// we also need to look for interface methods -
// because the class may be abstract
Class>[] interfaces = currentClass.getInterfaces();
for (Class> anInterface : interfaces) {
addUniqueMethods(uniqueMethods, anInterface.getMethods());
}
currentClass = currentClass.getSuperclass();
}
Collection methods = uniqueMethods.values();
return methods.toArray(new Method[methods.size()]);
}
private void addUniqueMethods(HashMap uniqueMethods, Method[] methods) {
for (Method currentMethod : methods) {
if (!currentMethod.isBridge()) {
String signature = getSignature(currentMethod);
// check to see if the method is already known
// if it is known, then an extended class must have
// overridden a method
if (!uniqueMethods.containsKey(signature)) {
if (canAccessPrivateMethods()) {
try {
currentMethod.setAccessible(true);
} catch (Exception e) {
// Ignored. This is only a final precaution, nothing we can do.
}
}
uniqueMethods.put(signature, currentMethod);
}
}
}
}
private String getSignature(Method method) {
StringBuilder sb = new StringBuilder();
Class> returnType = method.getReturnType();
if (returnType != null) {
sb.append(returnType.getName()).append('#');
}
sb.append(method.getName());
Class>[] parameters = method.getParameterTypes();
for (int i = 0; i < parameters.length; i++) {
if (i == 0) {
sb.append(':');
} else {
sb.append(',');
}
sb.append(parameters[i].getName());
}
return sb.toString();
}
private boolean canAccessPrivateMethods() {
try {
SecurityManager securityManager = System.getSecurityManager();
if (null != securityManager) {
securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
} catch (SecurityException e) {
return false;
}
return true;
}
public Method getGetMethod(String propertyName) {
Method method = getMethods.get(propertyName);
if (method == null) {
throw new RuntimeException(
"There is no getter for property named '" + propertyName + "' in '" + type + "'");
}
return method;
}
public Method getSetMethod(String propertyName) {
Method method = setMethods.get(propertyName);
if (method == null) {
throw new RuntimeException(
"There is no getter for property named '" + propertyName + "' in '" + type + "'");
}
return method;
}
/**
* 获取field 值
*
* @param obj
* @param property
* @return
*/
public Object getValue(Object obj, String property) {
Object value = null;
Method m = getMethods.get(property);
if (m != null) {
try {
value = m.invoke(obj, new Object[]{});
} catch (Exception ex) {
}
}
return value;
}
/**
* 设置field值
*
* @param obj 对象
* @param property
* @param object 属性值
* @return
*/
public boolean setValue(Object obj, String property, Object object) {
Method m = setMethods.get(property);
if (m != null) {
try {
m.invoke(obj, object);
return true;
} catch (Exception ex) {
return false;
}
}
return false;
}
public Map getGetMethods() {
return getMethods;
}
public List getFieldList() {
return fieldList;
}
}