conditional mapping
This commit is contained in:
parent
3c4596a424
commit
9584a81687
|
|
@ -26,6 +26,12 @@ import org.springframework.util.ClassUtils;
|
|||
*/
|
||||
final class DefaultMappingTargetFactory implements MappingTargetFactory {
|
||||
|
||||
private static final DefaultMappingTargetFactory INSTANCE = new DefaultMappingTargetFactory();
|
||||
|
||||
private DefaultMappingTargetFactory() {
|
||||
|
||||
}
|
||||
|
||||
public boolean supports(TypeDescriptor targetType) {
|
||||
return ClassUtils.hasConstructor(targetType.getType(), null);
|
||||
}
|
||||
|
|
@ -34,4 +40,8 @@ final class DefaultMappingTargetFactory implements MappingTargetFactory {
|
|||
return BeanUtils.instantiate(targetType.getType());
|
||||
}
|
||||
|
||||
public static MappingTargetFactory getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,10 +31,13 @@ final class FieldToFieldMapping implements SpelMapping {
|
|||
@SuppressWarnings("unchecked")
|
||||
private final Converter converter;
|
||||
|
||||
public FieldToFieldMapping(Expression sourceField, Expression targetField, Converter<?, ?> converter) {
|
||||
private final Expression condition;
|
||||
|
||||
public FieldToFieldMapping(Expression sourceField, Expression targetField, Converter<?, ?> converter, Expression condition) {
|
||||
this.sourceField = sourceField;
|
||||
this.targetField = targetField;
|
||||
this.converter = converter;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public String getSourceField() {
|
||||
|
|
@ -51,6 +54,9 @@ final class FieldToFieldMapping implements SpelMapping {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void map(SpelMappingContext context) {
|
||||
if (!context.conditionHolds(this.condition)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Object value = context.getSourceFieldValue(this.sourceField);
|
||||
if (this.converter != null) {
|
||||
|
|
|
|||
|
|
@ -28,10 +28,13 @@ final class FieldToMultiFieldMapping implements SpelMapping {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final Mapper targetFieldMapper;
|
||||
|
||||
public FieldToMultiFieldMapping(Expression sourceField, Mapper<?, ?> targetFieldMapper) {
|
||||
|
||||
private final Expression condition;
|
||||
|
||||
public FieldToMultiFieldMapping(Expression sourceField, Mapper<?, ?> targetFieldMapper, Expression condition) {
|
||||
this.sourceField = sourceField;
|
||||
this.targetFieldMapper = targetFieldMapper;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public String getSourceField() {
|
||||
|
|
@ -44,6 +47,9 @@ final class FieldToMultiFieldMapping implements SpelMapping {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void map(SpelMappingContext context) {
|
||||
if (!context.conditionHolds(this.condition)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Object value = context.getSourceFieldValue(this.sourceField);
|
||||
this.targetFieldMapper.map(value, context.getTarget());
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public interface MapperBuilder<S, T> {
|
|||
* The source and target field names will be the same value.
|
||||
* For example, calling <code>addMapping("order")</code> will register a mapping that maps between the <code>order</code> field on the source and the <code>order</code> field on the target.
|
||||
* This is a convenience method for calling {@link #addMapping(String, String)} with the same source and target value..
|
||||
* @param fieldExpression the field mapping expression
|
||||
* @param field the field mapping expression
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addMapping(String field);
|
||||
|
|
@ -60,7 +60,7 @@ public interface MapperBuilder<S, T> {
|
|||
* The source and target field expressions will be the same value.
|
||||
* For example, calling <code>addMapping("order")</code> will register a mapping that maps between the <code>order</code> field on the source and the <code>order</code> field on the target.
|
||||
* This is a convenience method for calling {@link #addMapping(String, String, Converter)} with the same source and target value..
|
||||
* @param fieldExpression the field mapping expression
|
||||
* @param field the field mapping expression
|
||||
* @param converter the converter that will convert the source field value before mapping the value to the target field
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
|
|
@ -81,8 +81,8 @@ public interface MapperBuilder<S, T> {
|
|||
* Register a mapping between a source field and a target field.
|
||||
* Use this method when the name of the source field and the name of the target field are different.
|
||||
* For example, calling <code>addMapping("order", "primaryOrder")</code> will register a mapping that maps between the <code>order</code> field on the source and the <code>primaryOrder</code> field on the target.
|
||||
* @param sourceFieldExpression the source field mapping expression
|
||||
* @param targetFieldExpression the target field mapping expression
|
||||
* @param sourceField the source field mapping expression
|
||||
* @param targetField the target field mapping expression
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addMapping(String sourceField, String targetField);
|
||||
|
|
@ -91,8 +91,8 @@ public interface MapperBuilder<S, T> {
|
|||
* Register a mapping between a source field and a target field that first converts the source field value using the provided Converter.
|
||||
* Use this method when the name of the source field and the name of the target field are different.
|
||||
* For example, calling <code>addMapping("order", "primaryOrder")</code> will register a mapping that maps between the <code>order</code> field on the source and the <code>primaryOrder</code> field on the target.
|
||||
* @param sourceFieldExpression the source field mapping expression
|
||||
* @param targetFieldExpression the target field mapping expression
|
||||
* @param sourceField the source field mapping expression
|
||||
* @param targetField the target field mapping expression
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addMapping(String sourceField, String targetField, Converter<?, ?> converter);
|
||||
|
|
@ -107,6 +107,71 @@ public interface MapperBuilder<S, T> {
|
|||
*/
|
||||
MapperBuilder<S, T> addMapping(String[] fields, Mapper<S, T> mapper);
|
||||
|
||||
/**
|
||||
* Register a conditional mapping between a source field and a target field.
|
||||
* The source and target field names will be the same value.
|
||||
* @param field the field mapping expression
|
||||
* @param condition the boolean expression that determines if this mapping executes
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addConditionalMapping(String field, String condition);
|
||||
|
||||
/**
|
||||
* Register a condition mapping between a source field and a target field that first converts the source field value using the provided Converter.
|
||||
* The source and target field expressions will be the same value.
|
||||
* @param field the field mapping expression
|
||||
* @param converter the converter that converts the source field value before mapping
|
||||
* @param condition the boolean expression that determines if this mapping executes
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addConditionalMapping(String field, Converter<?, ?> converter, String condition);
|
||||
|
||||
/**
|
||||
* Register a conditional mapping between a source field and multiple target fields.
|
||||
* Use this method when you need to map a single source field value to multiple fields on the target.
|
||||
* For example, calling <code>addMapping("name", firstAndLastNameMapper)</code> might register a mapping that maps the <code>name</code> field on the source to the <code>firstName</code> and <code>lastName</code> fields on the target.
|
||||
* The target field {@link Mapper} will be passed the value of the source field for its source and the target object T for its target.
|
||||
* @param field the source field expression
|
||||
* @param mapper the mapper of the target fields
|
||||
* @param condition the boolean expression that determines if this mapping executes
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addConditionalMapping(String field, Mapper<?, T> mapper, String condition);
|
||||
|
||||
/**
|
||||
* Register a conditional mapping between a source field and a target field.
|
||||
* Use this method when the name of the source field and the name of the target field are different.
|
||||
* For example, calling <code>addMapping("order", "primaryOrder")</code> will register a mapping that maps between the <code>order</code> field on the source and the <code>primaryOrder</code> field on the target.
|
||||
* @param sourceField the source field mapping expression
|
||||
* @param targetField the target field mapping expression
|
||||
* @param condition the boolean expression that determines if this mapping executes
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addConditionalMapping(String sourceField, String targetField, String condition);
|
||||
|
||||
/**
|
||||
* Register a conditional mapping between a source field and a target field that first converts the source field value using the provided Converter.
|
||||
* Use this method when the name of the source field and the name of the target field are different.
|
||||
* For example, calling <code>addMapping("order", "primaryOrder")</code> will register a mapping that maps between the <code>order</code> field on the source and the <code>primaryOrder</code> field on the target.
|
||||
* @param sourceField the source field mapping expression
|
||||
* @param targetField the target field mapping expression
|
||||
* @param converter the converter that converts the source field value before mapping
|
||||
* @param condition the boolean expression that determines if this mapping executes
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addConditionalMapping(String sourceField, String targetField, Converter<?, ?> converter, String condition);
|
||||
|
||||
/**
|
||||
* Register a conditional mapping between multiple source fields and a single target field.
|
||||
* For example, calling <code>addMapping(dateAndTimeFieldsToDateTimeFieldMapper)</code> might register a mapping that maps the <code>date</code> and <code>time</code> fields on the source to the <code>dateTime</code> field on the target.
|
||||
* The provided {@link Mapper} will be passed the source object S for its source and the target object T for its target.
|
||||
* @param fields the source field mapping expressions
|
||||
* @param mapper the fields to field mapper
|
||||
* @param condition the boolean expression that determines if this mapping executes
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
*/
|
||||
MapperBuilder<S, T> addMapping(String[] fields, Mapper<S, T> mapper, String condition);
|
||||
|
||||
/**
|
||||
* Register a Mapper that will be used to map between nested source and target fields of a specific sourceType/targetType pair.
|
||||
* The source and target field types are determined by introspecting the parameterized types on the Mapper generic interface.
|
||||
|
|
@ -130,11 +195,18 @@ public interface MapperBuilder<S, T> {
|
|||
* Register a custom type converter to use to convert between two mapped types.
|
||||
* The Converter may convert between simple types, such as Strings to Dates.
|
||||
* Alternatively, it may convert between complex types and initiate a recursive mapping operation between two object fields.
|
||||
* @return this, for configuring additional field mapping options fluently
|
||||
* @see Converter
|
||||
* @see MappingConverter
|
||||
*/
|
||||
MapperBuilder<S, T> addConverter(Converter<?, ?> converter);
|
||||
|
||||
/**
|
||||
* Set the source fields to exclude from mapping.
|
||||
* @param fields the source fields as var args
|
||||
*/
|
||||
MapperBuilder<S, T> setExcludedFields(String... fields);
|
||||
|
||||
/**
|
||||
* Get the Mapper produced by this builder.
|
||||
* Call this method after instructing the builder.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ final class MappingConversionService extends DefaultConversionService {
|
|||
|
||||
@Override
|
||||
protected GenericConverter getDefaultConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return new MappingConverter(new SpelMapper());
|
||||
return new MappingConverter(new SpelMapper(), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -33,15 +33,6 @@ final class MappingConverter implements GenericConverter {
|
|||
|
||||
private final 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.
|
||||
|
|
@ -49,7 +40,11 @@ final class MappingConverter implements GenericConverter {
|
|||
*/
|
||||
public MappingConverter(Mapper mapper, MappingTargetFactory mappingTargetFactory) {
|
||||
this.mapper = mapper;
|
||||
this.mappingTargetFactory = mappingTargetFactory;
|
||||
if (mappingTargetFactory != null) {
|
||||
this.mappingTargetFactory = mappingTargetFactory;
|
||||
} else {
|
||||
this.mappingTargetFactory = DefaultMappingTargetFactory.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package org.springframework.mapping.support;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.mapping.Mapper;
|
||||
|
||||
/**
|
||||
|
|
@ -29,9 +30,12 @@ final class MultiFieldToFieldMapping implements SpelMapping {
|
|||
@SuppressWarnings("unchecked")
|
||||
private final Mapper multiFieldMapper;
|
||||
|
||||
public MultiFieldToFieldMapping(String[] fields, Mapper<?, ?> multiFieldMapper) {
|
||||
private Expression condition;
|
||||
|
||||
public MultiFieldToFieldMapping(String[] fields, Mapper<?, ?> multiFieldMapper, Expression condition) {
|
||||
this.fields = fields;
|
||||
this.multiFieldMapper = multiFieldMapper;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public String[] getSourceFields() {
|
||||
|
|
@ -49,6 +53,9 @@ final class MultiFieldToFieldMapping implements SpelMapping {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void map(SpelMappingContext context) {
|
||||
if (!context.conditionHolds(this.condition)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.multiFieldMapper.map(context.getSource(), context.getTarget());
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -71,64 +71,32 @@ final class SpelMapper implements Mapper<Object, Object> {
|
|||
this.mappableTypeFactory = mappableTypeFactory;
|
||||
}
|
||||
|
||||
public void addMapping(String sourceFieldExpression, String targetFieldExpression, Converter<?, ?> converter) {
|
||||
public void setExcludedFields(String[] fields) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void addMapping(String sourceFieldExpression, String targetFieldExpression, Converter<?, ?> converter,
|
||||
String condition) {
|
||||
Expression sourceField = parseSourceField(sourceFieldExpression);
|
||||
Expression targetField = parseTargetField(targetFieldExpression);
|
||||
FieldToFieldMapping mapping = new FieldToFieldMapping(sourceField, targetField, converter);
|
||||
FieldToFieldMapping mapping = new FieldToFieldMapping(sourceField, targetField, converter,
|
||||
parseCondition(condition));
|
||||
this.mappings.add(mapping);
|
||||
}
|
||||
|
||||
public void addMapping(String field, Mapper<?, ?> mapper) {
|
||||
this.mappings.add(new FieldToMultiFieldMapping(parseSourceField(field), mapper));
|
||||
public void addMapping(String field, Mapper<?, ?> mapper, String condition) {
|
||||
this.mappings.add(new FieldToMultiFieldMapping(parseSourceField(field), mapper, parseCondition(condition)));
|
||||
}
|
||||
|
||||
public void addMapping(String[] fields, Mapper<?, ?> mapper) {
|
||||
this.mappings.add(new MultiFieldToFieldMapping(fields, mapper));
|
||||
public void addMapping(String[] fields, Mapper<?, ?> mapper, String condition) {
|
||||
this.mappings.add(new MultiFieldToFieldMapping(fields, mapper, parseCondition(condition)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Mapper that will map the fields of a nested sourceType/targetType pair.
|
||||
* The source and target field types are determined by introspecting the parameterized types on the implementation's Mapper generic interface.
|
||||
* The target instance that is mapped is constructed by a {@link DefaultMappingTargetFactory}.
|
||||
* This method is a convenience method for {@link #addNestedMapper(Class, Class, Mapper)}.
|
||||
* @param nestedMapper the nested mapper
|
||||
*/
|
||||
public void addNestedMapper(Mapper<?, ?> nestedMapper) {
|
||||
Class<?>[] typeInfo = getRequiredTypeInfo(nestedMapper);
|
||||
addNestedMapper(typeInfo[0], typeInfo[1], nestedMapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Mapper that will map the fields of a nested sourceType/targetType pair.
|
||||
* The source and target field types are determined by introspecting the parameterized types on the implementation's Mapper generic interface.
|
||||
* The target instance that is mapped is constructed by the provided {@link MappingTargetFactory}.
|
||||
* This method is a convenience method for {@link #addNestedMapper(Class, Class, Mapper, MappingTargetFactory)}.
|
||||
* @param nestedMapper the nested mapper
|
||||
* @param targetFactory the nested mapper's target factory
|
||||
*/
|
||||
public void addNestedMapper(Mapper<?, ?> nestedMapper, MappingTargetFactory targetFactory) {
|
||||
Class<?>[] typeInfo = getRequiredTypeInfo(nestedMapper);
|
||||
addNestedMapper(typeInfo[0], typeInfo[1], nestedMapper, targetFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Mapper that will map the fields of a nested sourceType/targetType pair.
|
||||
* The target instance that is mapped is constructed by a {@link DefaultMappingTargetFactory}.
|
||||
* @param sourceType the source nested object property type
|
||||
* @param targetType the target nested object property type
|
||||
* @param nestedMapper the nested mapper
|
||||
*/
|
||||
public void addNestedMapper(Class<?> sourceType, Class<?> targetType, Mapper<?, ?> nestedMapper) {
|
||||
this.conversionService.addGenericConverter(sourceType, targetType, new MappingConverter(nestedMapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Mapper that will map the fields of a nested sourceType/targetType pair.
|
||||
* @param sourceType the source nested object property type
|
||||
* @param targetType the target nested object property type
|
||||
* @param nestedMapper the nested mapper
|
||||
* @param targetFactory the nested mapper's target factory
|
||||
*/
|
||||
public void addNestedMapper(Class<?> sourceType, Class<?> targetType, Mapper<?, ?> nestedMapper,
|
||||
MappingTargetFactory targetFactory) {
|
||||
this.conversionService.addGenericConverter(sourceType, targetType, new MappingConverter(nestedMapper,
|
||||
|
|
@ -170,25 +138,33 @@ final class SpelMapper implements Mapper<Object, Object> {
|
|||
// internal helpers
|
||||
|
||||
private Expression parseSourceField(String sourceFieldExpression) {
|
||||
Expression sourceExp;
|
||||
try {
|
||||
sourceExp = sourceExpressionParser.parseExpression(sourceFieldExpression);
|
||||
return sourceExpressionParser.parseExpression(sourceFieldExpression);
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("The mapping source '" + sourceFieldExpression
|
||||
+ "' is not a parseable value expression", e);
|
||||
}
|
||||
return sourceExp;
|
||||
}
|
||||
|
||||
private Expression parseCondition(String condition) {
|
||||
if (condition == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return sourceExpressionParser.parseExpression(condition);
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("The mapping condition '" + condition
|
||||
+ "' is not a parseable value expression", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Expression parseTargetField(String targetFieldExpression) {
|
||||
Expression targetExp;
|
||||
try {
|
||||
targetExp = targetExpressionParser.parseExpression(targetFieldExpression);
|
||||
return targetExpressionParser.parseExpression(targetFieldExpression);
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("The mapping target '" + targetFieldExpression
|
||||
+ "' is not a parseable property expression", e);
|
||||
}
|
||||
return targetExp;
|
||||
}
|
||||
|
||||
private Class<?>[] getRequiredTypeInfo(Mapper<?, ?> mapper) {
|
||||
|
|
@ -221,7 +197,7 @@ final class SpelMapper implements Mapper<Object, Object> {
|
|||
}
|
||||
try {
|
||||
if (targetExpression.isWritable(targetContext)) {
|
||||
autoMappings.add(new FieldToFieldMapping(sourceExpression, targetExpression, null));
|
||||
autoMappings.add(new FieldToFieldMapping(sourceExpression, targetExpression, null, null));
|
||||
}
|
||||
} catch (EvaluationException e) {
|
||||
|
||||
|
|
@ -246,4 +222,5 @@ final class SpelMapper implements Mapper<Object, Object> {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,37 +40,68 @@ final class SpelMapperBuilder<S, T> implements MapperBuilder<S, T> {
|
|||
}
|
||||
|
||||
public MapperBuilder<S, T> addMapping(String field) {
|
||||
this.mapper.addMapping(field, field, null);
|
||||
this.mapper.addMapping(field, field, null, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addMapping(String field, Converter<?, ?> converter) {
|
||||
this.mapper.addMapping(field, field, converter);
|
||||
this.mapper.addMapping(field, field, converter, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addMapping(String field, Mapper<?, T> mapper) {
|
||||
this.mapper.addMapping(field, mapper);
|
||||
this.mapper.addMapping(field, mapper, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addMapping(String sourceField, String targetField) {
|
||||
this.mapper.addMapping(sourceField, targetField, null);
|
||||
this.mapper.addMapping(sourceField, targetField, null, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addMapping(String sourceField, String targetField, Converter<?, ?> converter) {
|
||||
this.mapper.addMapping(sourceField, targetField, converter);
|
||||
this.mapper.addMapping(sourceField, targetField, converter, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addMapping(String[] fields, Mapper<S, T> mapper) {
|
||||
this.mapper.addMapping(fields, mapper);
|
||||
this.mapper.addMapping(fields, mapper, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addConditionalMapping(String field, String condition) {
|
||||
this.mapper.addMapping(field, field, null, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addConditionalMapping(String field, Converter<?, ?> converter, String condition) {
|
||||
this.mapper.addMapping(field, field, converter, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addConditionalMapping(String field, Mapper<?, T> mapper, String condition) {
|
||||
this.mapper.addMapping(field, mapper, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addConditionalMapping(String sourceField, String targetField, String condition) {
|
||||
this.mapper.addMapping(sourceField, targetField, null, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addConditionalMapping(String sourceField, String targetField, Converter<?, ?> converter,
|
||||
String condition) {
|
||||
this.mapper.addMapping(sourceField, targetField, converter, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addMapping(String[] fields, Mapper<S, T> mapper, String condition) {
|
||||
this.mapper.addMapping(fields, mapper, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> addNestedMapper(Mapper<?, ?> nestedMapper) {
|
||||
this.mapper.addNestedMapper(nestedMapper);
|
||||
this.mapper.addNestedMapper(nestedMapper, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +114,11 @@ final class SpelMapperBuilder<S, T> implements MapperBuilder<S, T> {
|
|||
this.mapper.getConverterRegistry().addConverter(converter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MapperBuilder<S, T> setExcludedFields(String... fields) {
|
||||
this.mapper.setExcludedFields(fields);
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Mapper<S, T> getMapper() {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,14 @@ final class SpelMappingContext {
|
|||
public Object getTarget() {
|
||||
return this.targetEvaluationContext.getRootObject().getValue();
|
||||
}
|
||||
|
||||
|
||||
public boolean conditionHolds(Expression condition) {
|
||||
if (condition == null) {
|
||||
return true;
|
||||
}
|
||||
return Boolean.TRUE.equals(condition.getValue(this.sourceEvaluationContext));
|
||||
}
|
||||
|
||||
public Object getSourceFieldValue(Expression sourceField) {
|
||||
return sourceField.getValue(this.sourceEvaluationContext);
|
||||
}
|
||||
|
|
@ -61,4 +68,5 @@ final class SpelMappingContext {
|
|||
throw new MappingException(this.failures);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -317,6 +317,45 @@ public class MappingTests {
|
|||
.getActivationDateTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void conditionalMapping() {
|
||||
Map<String, String> domestic = new HashMap<String, String>();
|
||||
domestic.put("international", "false");
|
||||
domestic.put("areaCode", "205");
|
||||
domestic.put("prefix", "339");
|
||||
domestic.put("line", "1234");
|
||||
domestic.put("countryCode", "whatever");
|
||||
domestic.put("cityCode", "whatever");
|
||||
|
||||
Mapper<Map, PhoneNumber> mapper = MapperFactory.mapperBuilder(Map.class, PhoneNumber.class)
|
||||
.addConditionalMapping("countryCode", "international == 'true'")
|
||||
.addConditionalMapping("cityCode", "international == 'true'")
|
||||
.getMapper();
|
||||
|
||||
PhoneNumber number = mapper.map(domestic, new PhoneNumber());
|
||||
assertEquals("205", number.getAreaCode());
|
||||
assertEquals("339", number.getPrefix());
|
||||
assertEquals("1234", number.getLine());
|
||||
assertNull(number.getCountryCode());
|
||||
assertNull(number.getCityCode());
|
||||
|
||||
Map<String, String> international = new HashMap<String, String>();
|
||||
international.put("international", "true");
|
||||
international.put("areaCode", "205");
|
||||
international.put("prefix", "339");
|
||||
international.put("line", "1234");
|
||||
international.put("countryCode", "1");
|
||||
international.put("cityCode", "2");
|
||||
|
||||
PhoneNumber number2 = mapper.map(international, new PhoneNumber());
|
||||
|
||||
assertEquals("205", number2.getAreaCode());
|
||||
assertEquals("339", number2.getPrefix());
|
||||
assertEquals("1234", number2.getLine());
|
||||
assertEquals("1", number2.getCountryCode());
|
||||
assertEquals("2", number2.getCityCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapList() {
|
||||
PersonDto source = new PersonDto();
|
||||
|
|
@ -876,4 +915,59 @@ public class MappingTests {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public static class PhoneNumber {
|
||||
|
||||
private String areaCode;
|
||||
|
||||
private String prefix;
|
||||
|
||||
private String line;
|
||||
|
||||
private String countryCode;
|
||||
|
||||
private String cityCode;
|
||||
|
||||
public String getAreaCode() {
|
||||
return areaCode;
|
||||
}
|
||||
|
||||
public void setAreaCode(String areaCode) {
|
||||
this.areaCode = areaCode;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public void setLine(String line) {
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public String getCountryCode() {
|
||||
return countryCode;
|
||||
}
|
||||
|
||||
public void setCountryCode(String countryCode) {
|
||||
this.countryCode = countryCode;
|
||||
}
|
||||
|
||||
public String getCityCode() {
|
||||
return cityCode;
|
||||
}
|
||||
|
||||
public void setCityCode(String cityCode) {
|
||||
this.cityCode = cityCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue