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.
|
||||
* TODO - other fields required here?
|
||||
* @author Keith Donald
|
||||
*/
|
||||
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.mapping.MappingFailure;
|
||||
|
||||
/**
|
||||
* An individual mapping definition between two fields.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
class Mapping implements MappingConfiguration {
|
||||
|
||||
private Expression source;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,12 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
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.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.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
|
|
@ -55,12 +59,16 @@ public class SpelMapper implements Mapper<Object, Object> {
|
|||
|
||||
private boolean autoMappingEnabled = true;
|
||||
|
||||
private final DefaultConversionService conversionService = new DefaultConversionService();
|
||||
private MappingConversionService conversionService = new MappingConversionService();
|
||||
|
||||
public void setAutoMappingEnabled(boolean autoMappingEnabled) {
|
||||
this.autoMappingEnabled = autoMappingEnabled;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService.setParent(conversionService);
|
||||
}
|
||||
|
||||
public MappingConfiguration addMapping(String fieldExpression) {
|
||||
return addMapping(fieldExpression, fieldExpression);
|
||||
}
|
||||
|
|
@ -158,6 +166,20 @@ public class SpelMapper implements Mapper<Object, Object> {
|
|||
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 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("sport", "favoriteSport");
|
||||
mapper.addMapping("nested", "nested").setConverter(new Converter<NestedDto, Nested>() {
|
||||
public Nested convert(NestedDto source) {
|
||||
return (Nested) new SpelMapper().map(source, new Nested());
|
||||
}
|
||||
});
|
||||
mapper.addMapping("nested", "nested");
|
||||
mapper.map(source, target);
|
||||
|
||||
assertEquals("Keith Donald", target.name);
|
||||
|
|
|
|||
Loading…
Reference in New Issue