org.onetwo.common.spring.utils.MapToBeanConvertor Maven / Gradle / Ivy
package org.onetwo.common.spring.utils;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import org.onetwo.common.annotation.FieldName;
import org.onetwo.common.log.JFishLoggerFactory;
import org.onetwo.common.reflect.ReflectUtils;
import org.onetwo.common.spring.SpringUtils;
import org.onetwo.common.utils.Assert;
import org.slf4j.Logger;
import org.springframework.beans.BeanWrapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import lombok.Builder;
/**
* @author wayshall
*
*/
@Builder
public class MapToBeanConvertor {
final private static Logger logger = JFishLoggerFactory.getLogger(MapToBeanConvertor.class);
final private static MapToBeanConvertor INST = MapToBeanConvertor.builder().build();
final public static MapToBeanConvertor inst() {
return INST;
}
final protected static Cache PROPERTIES_CACHES = CacheBuilder.newBuilder()
.weakKeys()
.expireAfterAccess(30, TimeUnit.MINUTES)
.maximumSize(3000)
.build();
final protected Cache propertyCaches = PROPERTIES_CACHES;
private Function keyConvertor;
public T toBean(Map propValues, Class beanClass){
Assert.notNull(beanClass);
Assert.notNull(propValues);
T bean = ReflectUtils.newInstance(beanClass);
return injectBeanProperties(propValues, bean);
}
@SuppressWarnings("unchecked")
public T injectBeanProperties(Map propValues, T bean){
Class> beanClass = bean.getClass();
BeanWrapper bw = SpringUtils.newBeanWrapper(bean);
for(PropertyDescriptor pd : bw.getPropertyDescriptors()){
PropertyContext pc = new PropertyContext(beanClass, pd);
String key = getMapKey(pc);
Object value = propValues.get(key);
if(value==null){
continue;
}
if (value instanceof Map) {
value = toBean((Map)value, pd.getPropertyType());
} else {
value = SpringUtils.getFormattingConversionService().convert(value, pd.getPropertyType());
}
bw.setPropertyValue(pd.getName(), value);
}
return bean;
}
public T injectBeanProperties(Properties properties, T bean){
Class> beanClass = bean.getClass();
BeanWrapper bw = SpringUtils.newBeanWrapper(bean);
for(PropertyDescriptor pd : bw.getPropertyDescriptors()){
PropertyContext pc = new PropertyContext(beanClass, pd);
String key = getMapKey(pc);
String value = properties.getProperty(key);
if(value==null){
continue;
}
Object convertedValue = SpringUtils.getFormattingConversionService().convert(value, pd.getPropertyType());
bw.setPropertyValue(pd.getName(), convertedValue);
}
return bean;
}
public void setKeyConvertor(Function keyConvertor) {
this.keyConvertor = keyConvertor;
}
protected String getMapKey(PropertyContext pc){
try {
return propertyCaches.get(pc, ()->{
Function keyConvertor = this.keyConvertor;
if(keyConvertor==null){
return pc.getName();
}
return keyConvertor.apply(pc);
});
} catch (ExecutionException e) {
logger.error("get map key error for property: {}", pc.getName());
return pc.getName();
}
}
public static class PropertyContext {
final private Class> beanClass;
final private PropertyDescriptor propertyDescriptor;
public PropertyContext(Class> beanClass, PropertyDescriptor propertyDescriptor) {
super();
this.beanClass = beanClass;
this.propertyDescriptor = propertyDescriptor;
}
public String getName(){
/*Method method = propertyDescriptor.getReadMethod();
FieldName fn = null;
if(method==null || (fn = method.getAnnotation(FieldName.class))==null){
Field field = ReflectUtils.getIntro(getBeanClass()).getField(propertyDescriptor.getName());
if(field!=null){
fn = field.getAnnotation(FieldName.class);
}
}
return fn==null?propertyDescriptor.getName():fn.value();*/
Optional fn = findAnnotation(FieldName.class);
if(fn.isPresent()){
return fn.get().value();
}
Optional jp = findAnnotation(JsonProperty.class);//findAnnotationOnPropertyOrField
if(jp.isPresent()){
return jp.get().value();
}
return propertyDescriptor.getName();
}
protected Optional findAnnotation(Class annoClass){
Method method = propertyDescriptor.getReadMethod();
A fn = null;
if(method==null || (fn = method.getAnnotation(annoClass))==null){
Field field = ReflectUtils.getIntro(getBeanClass()).getField(propertyDescriptor.getName());
if(field!=null){
fn = field.getAnnotation(annoClass);
}
}
return Optional.ofNullable(fn);
}
public Class> getBeanClass() {
return beanClass;
}
public PropertyDescriptor getPropertyDescriptor() {
return propertyDescriptor;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((beanClass == null) ? 0 : beanClass.hashCode());
result = prime
* result
+ ((propertyDescriptor == null) ? 0 : propertyDescriptor
.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PropertyContext other = (PropertyContext) obj;
if (beanClass == null) {
if (other.beanClass != null)
return false;
} else if (!beanClass.equals(other.beanClass))
return false;
if (propertyDescriptor == null) {
if (other.propertyDescriptor != null)
return false;
} else if (!propertyDescriptor.equals(other.propertyDescriptor))
return false;
return true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy