polish
This commit is contained in:
parent
e99cda3739
commit
3fb3549997
|
|
@ -30,7 +30,7 @@ final class DefaultMappingTargetFactory implements MappingTargetFactory {
|
|||
return ClassUtils.hasConstructor(targetType.getType(), null);
|
||||
}
|
||||
|
||||
public Object createTarget(TypeDescriptor targetType) {
|
||||
public Object createTarget(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return BeanUtils.instantiate(targetType.getType());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import org.springframework.core.NamedThreadLocal;
|
|||
* @author Keith Donald
|
||||
* @see SpelMapper#map(Object, Object)
|
||||
*/
|
||||
abstract class MappingContextHolder {
|
||||
public abstract class MappingContextHolder {
|
||||
|
||||
private static final ThreadLocal<Stack<Object>> mappingContextHolder = new NamedThreadLocal<Stack<Object>>(
|
||||
"Mapping context");
|
||||
|
|
|
|||
|
|
@ -33,10 +33,20 @@ public final class MappingConverter implements GenericConverter {
|
|||
|
||||
private MappingTargetFactory mappingTargetFactory;
|
||||
|
||||
/**
|
||||
* Creates a new Converter that delegates to the mapper to complete the type conversion process.
|
||||
* Uses a {@link DefaultMappingTargetFactory} to create the target object to map and return.
|
||||
* @param mapper the mapper
|
||||
*/
|
||||
public MappingConverter(Mapper mapper) {
|
||||
this(mapper, new DefaultMappingTargetFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Converter that delegates to the mapper to complete the type conversion process.
|
||||
* Uses the specified MappingTargetFactory to create the target object to map and return.
|
||||
* @param mapper the mapper
|
||||
*/
|
||||
public MappingConverter(Mapper mapper, MappingTargetFactory mappingTargetFactory) {
|
||||
this.mapper = mapper;
|
||||
this.mappingTargetFactory = mappingTargetFactory;
|
||||
|
|
@ -52,7 +62,7 @@ public final class MappingConverter implements GenericConverter {
|
|||
if (sourceType.isAssignableTo(targetType) && isCopyByReference(sourceType, targetType)) {
|
||||
return source;
|
||||
}
|
||||
return createAndMap(targetType, source, sourceType);
|
||||
return createTargetAndMap(source, sourceType, targetType);
|
||||
}
|
||||
|
||||
private boolean isCopyByReference(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
|
@ -63,13 +73,13 @@ public final class MappingConverter implements GenericConverter {
|
|||
}
|
||||
}
|
||||
|
||||
private Object createAndMap(TypeDescriptor targetType, Object source, TypeDescriptor sourceType) {
|
||||
private Object createTargetAndMap(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (this.mappingTargetFactory.supports(targetType)) {
|
||||
Object target = this.mappingTargetFactory.createTarget(targetType);
|
||||
Object target = this.mappingTargetFactory.createTarget(source, sourceType, targetType);
|
||||
return this.mapper.map(source, target);
|
||||
} else {
|
||||
IllegalStateException cause = new IllegalStateException("["
|
||||
+ this.mappingTargetFactory.getClass().getName() + "] does not support target type ["
|
||||
+ this.mappingTargetFactory.getClass().getName() + "] does not support targetType ["
|
||||
+ targetType.getName() + "]");
|
||||
throw new ConversionFailedException(sourceType, targetType, source, cause);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,6 @@ public interface MappingTargetFactory {
|
|||
* @param targetType the target object type descriptor
|
||||
* @return the target
|
||||
*/
|
||||
public Object createTarget(TypeDescriptor targetType);
|
||||
public Object createTarget(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
|
||||
}
|
||||
|
|
@ -170,7 +170,8 @@ public class SpelMapper implements Mapper<Object, Object> {
|
|||
*/
|
||||
public void addNestedMapper(Class<?> sourceType, Class<?> targetType, Mapper<?, ?> nestedMapper,
|
||||
MappingTargetFactory targetFactory) {
|
||||
this.conversionService.addGenericConverter(sourceType, targetType, new MappingConverter(nestedMapper));
|
||||
this.conversionService.addGenericConverter(sourceType, targetType, new MappingConverter(nestedMapper,
|
||||
targetFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import java.util.Set;
|
|||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.expression.AccessException;
|
||||
|
|
@ -201,6 +202,41 @@ public class SpelMapperTests {
|
|||
assertEquals("bar and baz", target.nested.foo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapBeanNestedCustomNestedMapperCustomMappingTargetFactory() {
|
||||
PersonDto source = new PersonDto();
|
||||
final NestedDto nested = new NestedDto();
|
||||
nested.foo = "bar";
|
||||
source.setNested(nested);
|
||||
|
||||
Person target = new Person();
|
||||
|
||||
SpelMapper nestedMapper = new SpelMapper();
|
||||
nestedMapper.setAutoMappingEnabled(false);
|
||||
nestedMapper.addMapping("foo").setConverter(new Converter<String, String>() {
|
||||
public String convert(String source) {
|
||||
return source + " and baz";
|
||||
}
|
||||
});
|
||||
mapper.addNestedMapper(NestedDto.class, Nested.class, nestedMapper, new MappingTargetFactory() {
|
||||
public boolean supports(TypeDescriptor targetType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object createTarget(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
NestedDto nestedDto = (NestedDto) source;
|
||||
assertEquals(nested, nestedDto);
|
||||
return new Nested();
|
||||
}
|
||||
});
|
||||
|
||||
mapper.setAutoMappingEnabled(false);
|
||||
mapper.addMapping("nested");
|
||||
mapper.map(source, target);
|
||||
|
||||
assertEquals("bar and baz", target.nested.foo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapBeanNestedCustomNestedMapperHandCoded() {
|
||||
PersonDto source = new PersonDto();
|
||||
|
|
@ -225,6 +261,37 @@ public class SpelMapperTests {
|
|||
|
||||
assertEquals("bar and baz", target.nested.foo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapBeanNestedCustomConverterDelegatingToMapper() {
|
||||
PersonDto source = new PersonDto();
|
||||
NestedDto nested = new NestedDto();
|
||||
nested.foo = "bar";
|
||||
source.setNested(nested);
|
||||
|
||||
Person target = new Person();
|
||||
|
||||
mapper.getConverterRegistry().addConverter(new Converter<NestedDto, Nested>() {
|
||||
public Nested convert(NestedDto source) {
|
||||
// allows construction of target to be controlled by the converter
|
||||
Nested nested = new Nested();
|
||||
// mapping can do whatever, here we delegate to nested SpelMapper
|
||||
SpelMapper nestedMapper = new SpelMapper();
|
||||
nestedMapper.addMapping("foo").setConverter(new Converter<String, String>() {
|
||||
public String convert(String source) {
|
||||
return source + " and baz";
|
||||
}
|
||||
});
|
||||
return (Nested) nestedMapper.map(source, nested);
|
||||
}
|
||||
});
|
||||
|
||||
mapper.setAutoMappingEnabled(false);
|
||||
mapper.addMapping("nested");
|
||||
mapper.map(source, target);
|
||||
|
||||
assertEquals("bar and baz", target.nested.foo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapList() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue