net.dongliu.commons.reflect.Beans Maven / Gradle / Ivy
package net.dongliu.commons.reflect;
import net.dongliu.commons.collection.Lists;
import net.dongliu.commons.collection.Maps;
import net.dongliu.commons.collection.Pair;
import net.dongliu.commons.concurrent.WeakLoader;
import net.dongliu.commons.exception.ReflectException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* Utils method to deal with java bean
*
* @author Liu Dong {@literal }
*/
public class Beans {
private static final WeakLoader, Class>>, BeanCopier> copierCacheLoader
= WeakLoader.create(pair -> getBeanCopier(pair.first(), pair.second()));
private static final WeakLoader, List> propertiesCacheLoader
= WeakLoader.create(Beans::getPropertyDescriptors);
/**
* Convert bean to map.
*
* @return null if bean is null, other wise map contains the key-load entries from bean's properties
*/
public static Map toMap(Object bean) throws ReflectException {
Map map = Maps.create();
List pds = getProperties(bean);
for (BeanProperty pd : pds) {
String name = pd.name();
if (!pd.canRead()) {
continue;
}
Object value = pd.get(bean);
map.put(name, value);
}
return map;
}
/**
* Convert map to bean
*
* @return null if map is null; other wise bean with properties values from map
*/
public static T copyFromMap(Map map, Class cls) {
T bean = newBean(cls);
copyPropertiesFromMap(map, bean);
return bean;
}
/**
* Set bean properties with values from map
*
* @param bean not null
*/
public static void copyPropertiesFromMap(Map map, T bean) {
List properties = getProperties(bean);
for (BeanProperty property : properties) {
String name = property.name();
if (!map.containsKey(name)) {
continue;
}
if (!property.canWrite()) {
continue;
}
property.set(bean, map.get(name));
}
}
/**
* Shallow copy bean via reflect
*/
@SuppressWarnings("unchecked")
public static T copyBean(T bean) {
T newBean;
try {
newBean = (T) bean.getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new ReflectException(e);
}
copyBeanProperties(bean, newBean);
return bean;
}
/**
* Shallow copy bean
*/
public static void copyBeanProperties(Object src, Object dst) {
Pair, Class>> key = Pair.of(src.getClass(), dst.getClass());
BeanCopier beanCopier = copierCacheLoader.get(key);
beanCopier.copy(src, dst);
}
private static BeanCopier getBeanCopier(Class> srcClass, Class> dstClass) {
List srcPdList = getClassProperties(srcClass);
List dstPdList = getClassProperties(dstClass);
Map dstMap = new HashMap<>();
for (BeanProperty pd : dstPdList) {
if (!pd.canWrite()) {
continue;
}
String dstName = pd.name();
dstMap.put(dstName, pd);
}
List> matchList = new ArrayList<>();
for (BeanProperty pd : srcPdList) {
if (!pd.canRead()) {
continue;
}
String srcName = pd.name();
Class> srcType = pd.type();
BeanProperty dstPd = dstMap.get(srcName);
if (dstPd != null) {
Class> dstType = dstPd.type();
if (dstType.isAssignableFrom(srcType)) {
matchList.add(Pair.of(pd, dstPd));
}
}
}
return new BeanCopier(matchList);
}
/**
* Convert bean to String.
* Note: this method use declared fields to construct string ,not use properties
*/
public static String toString(Object bean) {
StringJoiner joiner = new StringJoiner(", ", bean.getClass().getSimpleName() + "{", "}");
for (Field field : getFields(bean.getClass())) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
String name = field.getName();
Object value;
try {
value = field.get(bean);
} catch (IllegalAccessException e) {
throw new ReflectException(e);
}
joiner.add(name + "=" + String.valueOf(value));
}
return joiner.toString();
}
private static T newBean(Class cls) {
try {
return cls.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new ReflectException(e);
}
}
/**
* Get bean properties
*
* @return Immutable property list
* @throws ReflectException
*/
public static List getProperties(Object bean) {
Class> cls = bean.getClass();
return getClassProperties(cls);
}
/**
* Get all fields for class.
*/
public static List getFields(Class> cls) {
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
}
return Lists.of(fields);
}
/**
* Get bean class properties
*
* @return Immutable property list
* @throws ReflectException
*/
public static List getClassProperties(Class> cls) {
return propertiesCacheLoader.get(cls);
}
private static List getPropertyDescriptors(Class> cls) {
return Lists.wrapImmutable(JavaClass.of(cls).getAllProperties());
}
static class BeanCopier {
private final List> matchList;
BeanCopier(List> matchList) {
this.matchList = matchList;
}
void copy(Object src, Object dst) {
for (Pair pair : matchList) {
Object value = pair.first().get(src);
pair.second().set(dst, value);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy