package demo; import java.beans.PropertyDescriptor; import java.util.Collections; import java.util.Set; import javax.persistence.Entity; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanWrapperImpl; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalConverter; import org.springframework.core.convert.converter.GenericConverter; import org.springframework.stereotype.Component; @Component public class FieldMappingObjectConverter implements GenericConverter, ConditionalConverter { @Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { //only for entities? //TODO check if source type is a entity managed by Spring Data if (!sourceType.hasAnnotation(Entity.class)) { return false; } if (targetType.getType().isInterface()) { return false; } return isCompatibleProjectionType(sourceType, targetType); } private boolean isCompatibleProjectionType(TypeDescriptor sourceType, TypeDescriptor targetType) { // TODO perform more sophisticated compatibility check, e.g. take matching fields into account, or mapping annotations... PropertyDescriptor[] targetPds = new BeanWrapperImpl(targetType.getClass()).getPropertyDescriptors(); PropertyDescriptor[] sourcePds = new BeanWrapperImpl(sourceType.getClass()).getPropertyDescriptors(); for (PropertyDescriptor pdt : targetPds) { boolean found = false; for (PropertyDescriptor pds : sourcePds) { found |= pdt.getName().equals(pds.getName()); } if (!found) { return false; } } return true; } @Override public Set getConvertibleTypes() { return Collections.singleton(new ConvertiblePair(Object.class, Object.class)); } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { //TODO more sophisticated bean creation and copying... Object target = BeanUtils.instantiateClass(targetType.getObjectType()); BeanUtils.copyProperties(source, target); return target; } }