recursive mapping support
This commit is contained in:
parent
fd8935ba0b
commit
0a843e60a6
|
|
@ -17,6 +17,7 @@ package org.springframework.mapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates an individual mapping failed.
|
* Indicates an individual mapping failed.
|
||||||
|
* TODO - other fields required here?
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
*/
|
*/
|
||||||
public class MappingFailure {
|
public class MappingFailure {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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 org.springframework.mapping.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a mapping target by calling its default constructor.
|
||||||
|
* @author Keith Donald
|
||||||
|
* @see BeanUtils#instantiate(Class)
|
||||||
|
*/
|
||||||
|
class DefaultMapperTargetFactory implements MapperTargetFactory {
|
||||||
|
|
||||||
|
public Object createTarget(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
|
return BeanUtils.instantiate(targetType.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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 org.springframework.mapping.support;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
import org.springframework.core.convert.support.GenericConverter;
|
||||||
|
import org.springframework.mapping.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts a Mapper to a Converter, allowing the conversion between two object types to be completed by a Mapper.
|
||||||
|
* Delegates to a {@link MapperTargetFactory} to construct the conversion target object that will be mapped.
|
||||||
|
* The default MapperTargetFactory instantiates a target by calling its default constructor.
|
||||||
|
* @author Keith Donald
|
||||||
|
*/
|
||||||
|
public class MapperConverter implements GenericConverter {
|
||||||
|
|
||||||
|
private Mapper mapper;
|
||||||
|
|
||||||
|
private MapperTargetFactory mappingTargetFactory;
|
||||||
|
|
||||||
|
public MapperConverter(Mapper mapper) {
|
||||||
|
this(mapper, new DefaultMapperTargetFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapperConverter(Mapper mapper, MapperTargetFactory mappingTargetFactory) {
|
||||||
|
this.mapper = mapper;
|
||||||
|
this.mappingTargetFactory = mappingTargetFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
|
if (source == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Object target = this.mappingTargetFactory.createTarget(source, sourceType, targetType);
|
||||||
|
return this.mapper.map(source, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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 org.springframework.mapping.support;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
import org.springframework.mapping.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory for customizing how the target of a map operation is constructed.
|
||||||
|
* Used by a {@link MapperConverter} when executing a type conversion.
|
||||||
|
* @author Keith Donald
|
||||||
|
* @see MapperConverter
|
||||||
|
* @see Mapper#map(Object, Object)
|
||||||
|
*/
|
||||||
|
public interface MapperTargetFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the target object to be mapped to.
|
||||||
|
* @param source the source object to map from
|
||||||
|
* @param sourceType the source object type descriptor
|
||||||
|
* @param targetType the target object type descriptor
|
||||||
|
* @return the target
|
||||||
|
*/
|
||||||
|
public Object createTarget(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||||
|
}
|
||||||
|
|
@ -26,6 +26,10 @@ import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.mapping.MappingFailure;
|
import org.springframework.mapping.MappingFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An individual mapping definition between two fields.
|
||||||
|
* @author Keith Donald
|
||||||
|
*/
|
||||||
class Mapping implements MappingConfiguration {
|
class Mapping implements MappingConfiguration {
|
||||||
|
|
||||||
private Expression source;
|
private Expression source;
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,12 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
|
import org.springframework.core.convert.support.GenericConverter;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
|
|
@ -55,12 +59,16 @@ public class SpelMapper implements Mapper<Object, Object> {
|
||||||
|
|
||||||
private boolean autoMappingEnabled = true;
|
private boolean autoMappingEnabled = true;
|
||||||
|
|
||||||
private final DefaultConversionService conversionService = new DefaultConversionService();
|
private MappingConversionService conversionService = new MappingConversionService();
|
||||||
|
|
||||||
public void setAutoMappingEnabled(boolean autoMappingEnabled) {
|
public void setAutoMappingEnabled(boolean autoMappingEnabled) {
|
||||||
this.autoMappingEnabled = autoMappingEnabled;
|
this.autoMappingEnabled = autoMappingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConversionService(ConversionService conversionService) {
|
||||||
|
this.conversionService.setParent(conversionService);
|
||||||
|
}
|
||||||
|
|
||||||
public MappingConfiguration addMapping(String fieldExpression) {
|
public MappingConfiguration addMapping(String fieldExpression) {
|
||||||
return addMapping(fieldExpression, fieldExpression);
|
return addMapping(fieldExpression, fieldExpression);
|
||||||
}
|
}
|
||||||
|
|
@ -158,6 +166,20 @@ public class SpelMapper implements Mapper<Object, Object> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class MappingConversionService extends GenericConversionService {
|
||||||
|
|
||||||
|
public MappingConversionService() {
|
||||||
|
setParent(new DefaultConversionService());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
|
GenericConverter converter = super.getConverter(sourceType, targetType);
|
||||||
|
return converter != null ? converter : new MapperConverter(new SpelMapper());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static class MappableTypeFactory {
|
private static class MappableTypeFactory {
|
||||||
|
|
||||||
private static final MapMappableType MAP_MAPPABLE_TYPE = new MapMappableType();
|
private static final MapMappableType MAP_MAPPABLE_TYPE = new MapMappableType();
|
||||||
|
|
@ -173,4 +195,5 @@ public class SpelMapper implements Mapper<Object, Object> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,11 +142,7 @@ public class SpelMapperTests {
|
||||||
|
|
||||||
mapper.addMapping("fullName", "name");
|
mapper.addMapping("fullName", "name");
|
||||||
mapper.addMapping("sport", "favoriteSport");
|
mapper.addMapping("sport", "favoriteSport");
|
||||||
mapper.addMapping("nested", "nested").setConverter(new Converter<NestedDto, Nested>() {
|
mapper.addMapping("nested", "nested");
|
||||||
public Nested convert(NestedDto source) {
|
|
||||||
return (Nested) new SpelMapper().map(source, new Nested());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mapper.map(source, target);
|
mapper.map(source, target);
|
||||||
|
|
||||||
assertEquals("Keith Donald", target.name);
|
assertEquals("Keith Donald", target.name);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue