/**
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.toolkit;
import com.baomidou.mybatisplus.entity.TableFieldInfo;
import com.baomidou.mybatisplus.entity.TableInfo;
import com.baomidou.mybatisplus.enums.FieldStrategy;
import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import java.lang.reflect.*;
import java.util.*;
/**
* <p>
* 反射工具类
* </p>
*
* @author Caratacus
* @Date 2016-09-22
*/
public class ReflectionKit {
private static final Log logger = LogFactory.getLog(ReflectionKit.class);
/**
* <p>
* 反射 method 方法名,例如 getId
* </p>
*
* @param field
* @param str 属性字符串内容
* @return
*/
public static String getMethodCapitalize(Field field, final String str) {
Class<?> fieldType = field.getType();
// fix #176
return StringUtils.concatCapitalize(boolean.class.equals(fieldType) ? "is" : "get", str);
}
/**
* 获取 public get方法的值
*
* @param cls
* @param entity 实体
* @param str 属性字符串内容
* @return Object
*/
public static Object getMethodValue(Class<?> cls, Object entity, String str) {
Map<String, Field> fieldMaps = getFieldMap(cls);
try {
if (MapUtils.isEmpty(fieldMaps)) {
throw new MybatisPlusException(
String.format("Error: NoSuchField in %s for %s. Cause:", cls.getSimpleName(), str));
}
Method method = cls.getMethod(getMethodCapitalize(fieldMaps.get(str), str));
return method.invoke(entity);
} catch (NoSuchMethodException e) {
throw new MybatisPlusException(String.format("Error: NoSuchMethod in %s. Cause:", cls.getSimpleName()) + e);
} catch (IllegalAccessException e) {
throw new MybatisPlusException(String.format("Error: Cannot execute a private method. in %s. Cause:",
cls.getSimpleName())
+ e);
} catch (InvocationTargetException e) {
throw new MybatisPlusException("Error: InvocationTargetException on getMethodValue. Cause:" + e);
}
}
/**
* 获取 public get方法的值
*
* @param entity 实体
* @param str 属性字符串内容
* @return Object
*/
public static Object getMethodValue(Object entity, String str) {
if (null == entity) {
return null;
}
return getMethodValue(entity.getClass(), entity, str);
}
/**
* 调用对象的get方法检查对象所有属性是否为null
*
* @param bean 检查对象
* @return boolean true对象所有属性不为null,false对象所有属性为null
*/
public static boolean checkFieldValueNotNull(Object bean) {
if (null == bean) {
return false;
}
Class<?> cls = bean.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
if (null == tableInfo) {
throw new MybatisPlusException(String.format("Error: Could Not find %s in TableInfo Cache. ", cls.getSimpleName()));
}
boolean result = false;
List<TableFieldInfo> fieldList = tableInfo.getFieldList();
for (TableFieldInfo tableFieldInfo : fieldList) {
FieldStrategy fieldStrategy = tableFieldInfo.getFieldStrategy();
Object val = getMethodValue(cls, bean, tableFieldInfo.getProperty());
if (FieldStrategy.NOT_EMPTY.equals(fieldStrategy)) {
if (StringUtils.checkValNotNull(val)) {
result = true;
break;
}
} else {
if (null != val) {
result = true;
break;
}
}
}
return result;
}
/**
* 反射对象获取泛型
*
* @param clazz 对象
* @param index 泛型所在位置
* @return Class
*/
@SuppressWarnings("rawtypes")
public static Class getSuperClassGenricType(final Class clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName()));
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index, clazz.getSimpleName(),
params.length));
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(String.format("Warn: %s not set the actual class on superclass generic parameter", clazz.getSimpleName()));
return Object.class;
}
return (Class) params[index];
}
/**
* 获取该类的所有属性列表
*
* @param clazz 反射类
* @return
*/
public static Map<String, Field> getFieldMap(Class<?> clazz) {
List<Field> fieldList = getFieldList(clazz);
Map<String, Field> fieldMap = Collections.emptyMap();
if (CollectionUtils.isNotEmpty(fieldList)) {
fieldMap = new LinkedHashMap<>();
for (Field field : fieldList) {
fieldMap.put(field.getName(), field);
}
}
return fieldMap;
}
/**
* 获取该类的所有属性列表
*
* @param clazz 反射类
* @return
*/
public static List<Field> getFieldList(Class<?> clazz) {
if (null == clazz) {
return null;
}
List<Field> fieldList = new LinkedList<>();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
/* 过滤静态属性 */
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
/* 过滤 transient关键字修饰的属性 */
if (Modifier.isTransient(field.getModifiers())) {
continue;
}
fieldList.add(field);
}
/* 处理父类字段 */
Class<?> superClass = clazz.getSuperclass();
if (superClass.equals(Object.class)) {
return fieldList;
}
/* 排除重载属性 */
return excludeOverrideSuperField(fieldList, getFieldList(superClass));
}
/**
* <p>
* 排序重置父类属性
* </p>
*
* @param fieldList 子类属性
* @param superFieldList 父类属性
*/
public static List<Field> excludeOverrideSuperField(List<Field> fieldList, List<Field> superFieldList) {
// 子类属性
Map<String, Field> fieldMap = new HashMap<>();
for (Field field : fieldList) {
fieldMap.put(field.getName(), field);
}
for (Field superField : superFieldList) {
if (null == fieldMap.get(superField.getName())) {
// 加入重置父类属性
fieldList.add(superField);
}
}
return fieldList;
}
}