mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1571 apply nullvaluecheck strategy on all relevant levels
This commit is contained in:
parent
dcddba6853
commit
459f57e805
@ -11,6 +11,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||
|
||||
/**
|
||||
* Configures the mapping between two bean types.
|
||||
* <p>
|
||||
@ -61,6 +63,15 @@ public @interface BeanMapping {
|
||||
*/
|
||||
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL;
|
||||
|
||||
/**
|
||||
* Determines when to include a null check on the source property value of a bean mapping.
|
||||
*
|
||||
* Can be overridden by the one on {@link MapperConfig}, {@link Mapper} or {@link Mapping}.
|
||||
*
|
||||
* @return strategy how to do null checking
|
||||
*/
|
||||
NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION;
|
||||
|
||||
/**
|
||||
* Default ignore all mappings. All mappings have to be defined manually. No automatic mapping will take place. No
|
||||
* warning will be issued on missing target properties.
|
||||
|
@ -153,7 +153,7 @@ public @interface Mapper {
|
||||
/**
|
||||
* Determines when to include a null check on the source property value of a bean mapping.
|
||||
*
|
||||
* Can be overridden by the one on {@link MapperConfig} or {@link Mapping}.
|
||||
* Can be overridden by the one on {@link MapperConfig}, {@link BeanMapping} or {@link Mapping}.
|
||||
*
|
||||
* @return strategy how to do null checking
|
||||
*/
|
||||
|
@ -138,7 +138,7 @@ public @interface MapperConfig {
|
||||
/**
|
||||
* Determines when to include a null check on the source property value of a bean mapping.
|
||||
*
|
||||
* Can be overridden by the one on {@link Mapper} or {@link Mapping}.
|
||||
* Can be overridden by the one on {@link Mapper}, {@link BeanMapping} or {@link Mapping}.
|
||||
*
|
||||
* @return strategy how to do null checking
|
||||
*/
|
||||
|
@ -15,6 +15,8 @@ import java.text.SimpleDateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||
|
||||
/**
|
||||
* Configures the mapping of one bean attribute or enum constant.
|
||||
* <p>
|
||||
@ -255,4 +257,14 @@ public @interface Mapping {
|
||||
* @return Default value to set in case the source property is {@code null}.
|
||||
*/
|
||||
String defaultValue() default "";
|
||||
|
||||
/**
|
||||
* Determines when to include a null check on the source property value of a bean mapping.
|
||||
*
|
||||
* Can be overridden by the one on {@link MapperConfig}, {@link Mapper} or {@link BeanMapping}.
|
||||
*
|
||||
* @return strategy how to do null checking
|
||||
*/
|
||||
NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION;
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ import java.text.SimpleDateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||
|
||||
/**
|
||||
* Configures the mapping of one bean attribute or enum constant.
|
||||
* <p>
|
||||
@ -260,4 +262,14 @@ public @interface Mapping {
|
||||
* @return Default value to set in case the source property is {@code null}.
|
||||
*/
|
||||
String defaultValue() default "";
|
||||
|
||||
/**
|
||||
* Determines when to include a null check on the source property value of a bean mapping.
|
||||
*
|
||||
* Can be overridden by the one on {@link MapperConfig}, {@link Mapper} or {@link BeanMapping}.
|
||||
*
|
||||
* @return strategy how to do null checking
|
||||
*/
|
||||
NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION;
|
||||
|
||||
}
|
||||
|
@ -75,8 +75,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
private Set<String> targetProperties;
|
||||
private final List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
||||
private final Set<Parameter> unprocessedSourceParameters = new HashSet<Parameter>();
|
||||
private NullValueMappingStrategyPrism nullValueMappingStrategy;
|
||||
private SelectionParameters selectionParameters;
|
||||
private final Set<String> existingVariableNames = new HashSet<String>();
|
||||
private Map<String, List<Mapping>> methodMappings;
|
||||
private SingleMappingByTargetPropertyNameFunction singleMapping;
|
||||
@ -135,16 +133,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder selectionParameters(SelectionParameters selectionParameters) {
|
||||
this.selectionParameters = selectionParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder nullValueMappingStrategy(NullValueMappingStrategyPrism nullValueMappingStrategy) {
|
||||
this.nullValueMappingStrategy = nullValueMappingStrategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BeanMappingMethod build() {
|
||||
// map properties with mapping
|
||||
boolean mappingErrorOccured = handleDefinedMappings();
|
||||
@ -168,12 +156,20 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
reportErrorForUnmappedTargetPropertiesIfRequired();
|
||||
reportErrorForUnmappedSourcePropertiesIfRequired();
|
||||
|
||||
// get bean mapping (when specified as annotation )
|
||||
BeanMapping beanMapping = method.getMappingOptions().getBeanMapping();
|
||||
BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() );
|
||||
|
||||
// mapNullToDefault
|
||||
NullValueMappingStrategyPrism nullValueMappingStrategy =
|
||||
beanMapping != null ? beanMapping.getNullValueMappingStrategy() : null;
|
||||
boolean mapNullToDefault = method.getMapperConfiguration().isMapToDefault( nullValueMappingStrategy );
|
||||
|
||||
|
||||
BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() );
|
||||
// selectionParameters
|
||||
SelectionParameters selectionParameters = beanMapping != null ? beanMapping.getSelectionParameters() : null;
|
||||
|
||||
// check if there's a factory method for the result type
|
||||
MethodReference factoryMethod = null;
|
||||
if ( !method.isUpdateMethod() ) {
|
||||
factoryMethod = ObjectFactoryMethodResolver.getFactoryMethod(
|
||||
@ -481,6 +477,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
.dependsOn( mapping.getDependsOn() )
|
||||
.defaultValue( mapping.getDefaultValue() )
|
||||
.defaultJavaExpression( mapping.getDefaultJavaExpression() )
|
||||
.nullValueCheckStrategyPrism( mapping.getNullValueCheckStrategy() )
|
||||
.build();
|
||||
handledTargets.add( propertyName );
|
||||
unprocessedSourceParameters.remove( sourceRef.getParameter() );
|
||||
@ -597,6 +594,8 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
.existingVariableNames( existingVariableNames )
|
||||
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() )
|
||||
.forgeMethodWithMappingOptions( extractAdditionalOptions( targetPropertyName, false ) )
|
||||
.nullValueCheckStrategyPrism( mapping != null ? mapping.getNullValueCheckStrategy()
|
||||
: null )
|
||||
.build();
|
||||
|
||||
unprocessedSourceParameters.remove( sourceParameter );
|
||||
@ -660,6 +659,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
.existingVariableNames( existingVariableNames )
|
||||
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() )
|
||||
.forgeMethodWithMappingOptions( extractAdditionalOptions( targetProperty.getKey(), false ) )
|
||||
.nullValueCheckStrategyPrism( mapping != null ? mapping.getNullValueCheckStrategy() : null )
|
||||
.build();
|
||||
|
||||
propertyMappings.add( propertyMapping );
|
||||
|
@ -57,6 +57,7 @@ public class CollectionAssignmentBuilder {
|
||||
private PropertyMapping.TargetWriteAccessorType targetAccessorType;
|
||||
private Assignment assignment;
|
||||
private SourceRHS sourceRHS;
|
||||
private NullValueCheckStrategyPrism nullValueCheckStrategy;
|
||||
|
||||
public CollectionAssignmentBuilder mappingBuilderContext(MappingBuilderContext ctx) {
|
||||
this.ctx = ctx;
|
||||
@ -108,6 +109,11 @@ public class CollectionAssignmentBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CollectionAssignmentBuilder nullValueCheckStrategy( NullValueCheckStrategyPrism nullValueCheckStrategy ) {
|
||||
this.nullValueCheckStrategy = nullValueCheckStrategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Assignment build() {
|
||||
Assignment result = assignment;
|
||||
|
||||
@ -146,14 +152,14 @@ public class CollectionAssignmentBuilder {
|
||||
result,
|
||||
method.getThrownTypes(),
|
||||
targetType,
|
||||
method.getMapperConfiguration().getNullValueCheckStrategy(),
|
||||
nullValueCheckStrategy,
|
||||
ctx.getTypeFactory(),
|
||||
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType ),
|
||||
mapNullToDefault()
|
||||
);
|
||||
}
|
||||
else if ( result.getType() == Assignment.AssignmentType.DIRECT ||
|
||||
method.getMapperConfiguration().getNullValueCheckStrategy() == NullValueCheckStrategyPrism.ALWAYS ) {
|
||||
nullValueCheckStrategy == NullValueCheckStrategyPrism.ALWAYS ) {
|
||||
|
||||
result = new SetterWrapperForCollectionsAndMapsWithNullCheck(
|
||||
result,
|
||||
@ -199,4 +205,5 @@ public class CollectionAssignmentBuilder {
|
||||
return method.getMapperConfiguration().getNullValueMappingStrategy()
|
||||
== NullValueMappingStrategyPrism.RETURN_DEFAULT;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,17 +5,11 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model;
|
||||
|
||||
import static org.mapstruct.ap.internal.model.common.Assignment.AssignmentType.DIRECT;
|
||||
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS;
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
import static org.mapstruct.ap.internal.util.Collections.last;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
@ -33,6 +27,7 @@ import org.mapstruct.ap.internal.model.common.ModelElement;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.SourceRHS;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.BeanMapping;
|
||||
import org.mapstruct.ap.internal.model.source.ForgedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.ForgedMethodHistory;
|
||||
import org.mapstruct.ap.internal.model.source.MappingOptions;
|
||||
@ -52,6 +47,11 @@ import org.mapstruct.ap.internal.util.Strings;
|
||||
import org.mapstruct.ap.internal.util.ValueProvider;
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
|
||||
import static org.mapstruct.ap.internal.model.common.Assignment.AssignmentType.DIRECT;
|
||||
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS;
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
import static org.mapstruct.ap.internal.util.Collections.last;
|
||||
|
||||
/**
|
||||
* Represents the mapping between a source and target property, e.g. from {@code String Source#foo} to
|
||||
* {@code int Target#bar}. Name and type of source and target property can differ. If they have different types, the
|
||||
@ -197,6 +197,7 @@ public class PropertyMapping extends ModelElement {
|
||||
private MappingOptions forgeMethodWithMappingOptions;
|
||||
private boolean forceUpdateMethod;
|
||||
private boolean forgedNamedBased = true;
|
||||
private NullValueCheckStrategyPrism nullValueCheckStrategyPrism;
|
||||
|
||||
PropertyMappingBuilder() {
|
||||
super( PropertyMappingBuilder.class );
|
||||
@ -253,6 +254,12 @@ public class PropertyMapping extends ModelElement {
|
||||
return this;
|
||||
}
|
||||
|
||||
public PropertyMappingBuilder nullValueCheckStrategyPrism(
|
||||
NullValueCheckStrategyPrism nullValueCheckStrategyPrism) {
|
||||
this.nullValueCheckStrategyPrism = nullValueCheckStrategyPrism;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PropertyMapping build() {
|
||||
// handle source
|
||||
this.rightHandSide = getSourceRHS( sourceReference );
|
||||
@ -427,11 +434,16 @@ public class PropertyMapping extends ModelElement {
|
||||
!rhs.isSourceReferenceParameter(), mapNullToDefault );
|
||||
}
|
||||
else {
|
||||
NullValueCheckStrategyPrism nvcs = method.getMapperConfiguration().getNullValueCheckStrategy();
|
||||
return new SetterWrapper( rhs, method.getThrownTypes(), nvcs, isFieldAssignment(), targetType );
|
||||
return new SetterWrapper( rhs, method.getThrownTypes(), getNvcs(), isFieldAssignment(), targetType );
|
||||
}
|
||||
}
|
||||
|
||||
private NullValueCheckStrategyPrism getNvcs() {
|
||||
BeanMapping beanMapping = method.getMappingOptions().getBeanMapping();
|
||||
NullValueCheckStrategyPrism nvcsBean = beanMapping != null ? beanMapping.getNullValueCheckStrategy() : null;
|
||||
return method.getMapperConfiguration().getNullValueCheckStrategy( nvcsBean, nullValueCheckStrategyPrism );
|
||||
}
|
||||
|
||||
private Assignment assignToPlainViaAdder( Assignment rightHandSide) {
|
||||
|
||||
Assignment result = rightHandSide;
|
||||
@ -461,6 +473,7 @@ public class PropertyMapping extends ModelElement {
|
||||
.targetAccessorType( targetAccessorType )
|
||||
.rightHandSide( rightHandSide )
|
||||
.assignment( rhs )
|
||||
.nullValueCheckStrategy( getNvcs() )
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.prism.BeanMappingPrism;
|
||||
import org.mapstruct.ap.internal.prism.BuilderPrism;
|
||||
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
|
||||
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
||||
import org.mapstruct.ap.internal.prism.ReportingPolicyPrism;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
@ -27,6 +28,7 @@ public class BeanMapping {
|
||||
|
||||
private final SelectionParameters selectionParameters;
|
||||
private final NullValueMappingStrategyPrism nullValueMappingStrategy;
|
||||
private final NullValueCheckStrategyPrism nullValueCheckStrategy;
|
||||
private final ReportingPolicyPrism reportingPolicy;
|
||||
private final boolean ignoreByDefault;
|
||||
private final List<String> ignoreUnmappedSourceProperties;
|
||||
@ -42,6 +44,7 @@ public class BeanMapping {
|
||||
return new BeanMapping(
|
||||
map.selectionParameters,
|
||||
map.nullValueMappingStrategy,
|
||||
map.nullValueCheckStrategy,
|
||||
map.reportingPolicy,
|
||||
false,
|
||||
map.ignoreUnmappedSourceProperties,
|
||||
@ -63,6 +66,11 @@ public class BeanMapping {
|
||||
? null
|
||||
: NullValueMappingStrategyPrism.valueOf( beanMapping.nullValueMappingStrategy() );
|
||||
|
||||
NullValueCheckStrategyPrism nullValueCheckStrategy =
|
||||
null == beanMapping.values.nullValueCheckStrategy()
|
||||
? null
|
||||
: NullValueCheckStrategyPrism.valueOf( beanMapping.nullValueCheckStrategy() );
|
||||
|
||||
boolean ignoreByDefault = beanMapping.ignoreByDefault();
|
||||
BuilderPrism builderMapping = null;
|
||||
if ( beanMapping.values.builder() != null ) {
|
||||
@ -71,7 +79,7 @@ public class BeanMapping {
|
||||
|
||||
if ( !resultTypeIsDefined && beanMapping.qualifiedBy().isEmpty() && beanMapping.qualifiedByName().isEmpty()
|
||||
&& beanMapping.ignoreUnmappedSourceProperties().isEmpty()
|
||||
&& ( nullValueMappingStrategy == null ) && !ignoreByDefault
|
||||
&& ( nullValueMappingStrategy == null ) && ( nullValueCheckStrategy == null ) && !ignoreByDefault
|
||||
&& builderMapping == null ) {
|
||||
|
||||
messager.printMessage( method, Message.BEANMAPPING_NO_ELEMENTS );
|
||||
@ -88,6 +96,7 @@ public class BeanMapping {
|
||||
return new BeanMapping(
|
||||
cmp,
|
||||
nullValueMappingStrategy,
|
||||
nullValueCheckStrategy,
|
||||
null,
|
||||
ignoreByDefault,
|
||||
beanMapping.ignoreUnmappedSourceProperties(),
|
||||
@ -102,14 +111,24 @@ public class BeanMapping {
|
||||
* @return bean mapping that needs to be used for Mappings
|
||||
*/
|
||||
public static BeanMapping forForgedMethods() {
|
||||
return new BeanMapping( null, null, ReportingPolicyPrism.IGNORE, false, Collections.<String>emptyList(), null );
|
||||
return new BeanMapping(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
ReportingPolicyPrism.IGNORE,
|
||||
false,
|
||||
Collections.<String>emptyList(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private BeanMapping(SelectionParameters selectionParameters, NullValueMappingStrategyPrism nvms,
|
||||
NullValueCheckStrategyPrism nvcs,
|
||||
ReportingPolicyPrism reportingPolicy, boolean ignoreByDefault,
|
||||
List<String> ignoreUnmappedSourceProperties, BuilderPrism builder) {
|
||||
List<String> ignoreUnmappedSourceProperties, BuilderPrism builder) {
|
||||
this.selectionParameters = selectionParameters;
|
||||
this.nullValueMappingStrategy = nvms;
|
||||
this.nullValueCheckStrategy = nvcs;
|
||||
this.reportingPolicy = reportingPolicy;
|
||||
this.ignoreByDefault = ignoreByDefault;
|
||||
this.ignoreUnmappedSourceProperties = ignoreUnmappedSourceProperties;
|
||||
@ -124,6 +143,10 @@ public class BeanMapping {
|
||||
return nullValueMappingStrategy;
|
||||
}
|
||||
|
||||
public NullValueCheckStrategyPrism getNullValueCheckStrategy() {
|
||||
return nullValueCheckStrategy;
|
||||
}
|
||||
|
||||
public ReportingPolicyPrism getReportingPolicy() {
|
||||
return reportingPolicy;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.prism.MappingPrism;
|
||||
import org.mapstruct.ap.internal.prism.MappingsPrism;
|
||||
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
|
||||
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
@ -56,6 +57,7 @@ public class Mapping {
|
||||
private final AnnotationValue sourceAnnotationValue;
|
||||
private final AnnotationValue targetAnnotationValue;
|
||||
private final AnnotationValue dependsOnAnnotationValue;
|
||||
private final NullValueCheckStrategyPrism nullValueCheckStrategy;
|
||||
|
||||
private SourceReference sourceReference;
|
||||
private TargetReference targetReference;
|
||||
@ -181,6 +183,11 @@ public class Mapping {
|
||||
typeUtils
|
||||
);
|
||||
|
||||
NullValueCheckStrategyPrism nullValueCheckStrategy =
|
||||
null == mappingPrism.values.nullValueCheckStrategy()
|
||||
? null
|
||||
: NullValueCheckStrategyPrism.valueOf( mappingPrism.nullValueCheckStrategy() );
|
||||
|
||||
return new Mapping(
|
||||
source,
|
||||
constant,
|
||||
@ -195,7 +202,8 @@ public class Mapping {
|
||||
formattingParam,
|
||||
selectionParams,
|
||||
mappingPrism.values.dependsOn(),
|
||||
dependsOn
|
||||
dependsOn,
|
||||
nullValueCheckStrategy
|
||||
);
|
||||
}
|
||||
|
||||
@ -214,7 +222,8 @@ public class Mapping {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new ArrayList()
|
||||
new ArrayList(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@ -223,7 +232,8 @@ public class Mapping {
|
||||
String targetName, String defaultValue, boolean isIgnored, AnnotationMirror mirror,
|
||||
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
|
||||
FormattingParameters formattingParameters, SelectionParameters selectionParameters,
|
||||
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn ) {
|
||||
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn,
|
||||
NullValueCheckStrategyPrism nullValueCheckStrategy ) {
|
||||
this.sourceName = sourceName;
|
||||
this.constant = constant;
|
||||
this.javaExpression = javaExpression;
|
||||
@ -238,6 +248,7 @@ public class Mapping {
|
||||
this.selectionParameters = selectionParameters;
|
||||
this.dependsOnAnnotationValue = dependsOnAnnotationValue;
|
||||
this.dependsOn = dependsOn;
|
||||
this.nullValueCheckStrategy = nullValueCheckStrategy;
|
||||
}
|
||||
|
||||
private Mapping( Mapping mapping, TargetReference targetReference ) {
|
||||
@ -257,6 +268,7 @@ public class Mapping {
|
||||
this.dependsOn = mapping.dependsOn;
|
||||
this.sourceReference = mapping.sourceReference;
|
||||
this.targetReference = targetReference;
|
||||
this.nullValueCheckStrategy = mapping.nullValueCheckStrategy;
|
||||
}
|
||||
|
||||
private Mapping( Mapping mapping, SourceReference sourceReference ) {
|
||||
@ -276,6 +288,7 @@ public class Mapping {
|
||||
this.dependsOn = mapping.dependsOn;
|
||||
this.sourceReference = sourceReference;
|
||||
this.targetReference = mapping.targetReference;
|
||||
this.nullValueCheckStrategy = mapping.nullValueCheckStrategy;
|
||||
}
|
||||
|
||||
private static String getExpression(MappingPrism mappingPrism, ExecutableElement element,
|
||||
@ -441,6 +454,10 @@ public class Mapping {
|
||||
return targetReference;
|
||||
}
|
||||
|
||||
public NullValueCheckStrategyPrism getNullValueCheckStrategy() {
|
||||
return nullValueCheckStrategy;
|
||||
}
|
||||
|
||||
public Mapping popTargetReference() {
|
||||
if ( targetReference != null ) {
|
||||
TargetReference newTargetReference = targetReference.pop();
|
||||
@ -488,7 +505,8 @@ public class Mapping {
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
dependsOnAnnotationValue,
|
||||
Collections.<String>emptyList()
|
||||
Collections.<String>emptyList(),
|
||||
nullValueCheckStrategy
|
||||
);
|
||||
|
||||
reverse.init(
|
||||
@ -529,7 +547,8 @@ public class Mapping {
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
dependsOnAnnotationValue,
|
||||
dependsOn
|
||||
dependsOn,
|
||||
nullValueCheckStrategy
|
||||
);
|
||||
|
||||
if ( sourceReference != null ) {
|
||||
|
@ -7,7 +7,7 @@ package org.mapstruct.ap.internal.prism;
|
||||
|
||||
|
||||
/**
|
||||
* Prism for the enum {@link org.mapstruct.SourceValuePresenceCheckStrategy}
|
||||
* Prism for the enum {@link org.mapstruct.NullValueCheckStrategy}
|
||||
*
|
||||
* @author Sean Huang
|
||||
*/
|
||||
|
@ -365,19 +365,11 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
}
|
||||
else {
|
||||
|
||||
NullValueMappingStrategyPrism nullValueMappingStrategy = null;
|
||||
SelectionParameters selectionParameters = null;
|
||||
|
||||
if ( mappingOptions.getBeanMapping() != null ) {
|
||||
nullValueMappingStrategy = mappingOptions.getBeanMapping().getNullValueMappingStrategy();
|
||||
selectionParameters = mappingOptions.getBeanMapping().getSelectionParameters();
|
||||
}
|
||||
BeanMappingMethod.Builder builder = new BeanMappingMethod.Builder();
|
||||
BeanMappingMethod beanMappingMethod = builder
|
||||
.mappingContext( mappingContext )
|
||||
.sourceMethod( method )
|
||||
.nullValueMappingStrategy( nullValueMappingStrategy )
|
||||
.selectionParameters( selectionParameters )
|
||||
.build();
|
||||
|
||||
if ( beanMappingMethod != null ) {
|
||||
|
@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.util;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
@ -148,8 +147,15 @@ public class MapperConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
public NullValueCheckStrategyPrism getNullValueCheckStrategy() {
|
||||
if ( mapperConfigPrism != null && mapperPrism.values.nullValueCheckStrategy() == null ) {
|
||||
public NullValueCheckStrategyPrism getNullValueCheckStrategy(NullValueCheckStrategyPrism beanPrism,
|
||||
NullValueCheckStrategyPrism mappingPrism) {
|
||||
if ( mappingPrism != null ) {
|
||||
return mappingPrism;
|
||||
}
|
||||
else if ( beanPrism != null ) {
|
||||
return beanPrism;
|
||||
}
|
||||
else if ( mapperConfigPrism != null && mapperPrism.values.nullValueCheckStrategy() == null ) {
|
||||
return NullValueCheckStrategyPrism.valueOf( mapperConfigPrism.nullValueCheckStrategy() );
|
||||
}
|
||||
else {
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.nullcheck.strategy;
|
||||
|
||||
public class HouseDto {
|
||||
|
||||
private String owner;
|
||||
private Integer number;
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Integer getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(Integer number) {
|
||||
this.number = number;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.nullcheck.strategy;
|
||||
|
||||
public class HouseEntity {
|
||||
|
||||
private String owner;
|
||||
private boolean ownerSet = false;
|
||||
|
||||
private Integer number;
|
||||
private boolean numberSet = false;
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
ownerSet = true;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public boolean ownerSet() {
|
||||
return ownerSet;
|
||||
}
|
||||
|
||||
public Integer getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(Integer number) {
|
||||
numberSet = true;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public boolean numberSet() {
|
||||
return numberSet;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.nullcheck.strategy;
|
||||
|
||||
import org.mapstruct.BeanMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.NullValueCheckStrategy;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
|
||||
public interface HouseMapper {
|
||||
|
||||
HouseMapper INSTANCE = Mappers.getMapper( HouseMapper.class );
|
||||
|
||||
HouseEntity mapWithNvcsOnMapper(HouseDto in);
|
||||
|
||||
@BeanMapping(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION)
|
||||
HouseEntity mapWithNvcsOnBean(HouseDto in);
|
||||
|
||||
@BeanMapping(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION)
|
||||
@Mapping(target = "number", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
|
||||
HouseEntity mapWithNvcsOnMapping(HouseDto in);
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.nullcheck.strategy;
|
||||
|
||||
import org.mapstruct.MapperConfig;
|
||||
import org.mapstruct.NullValueCheckStrategy;
|
||||
|
||||
@MapperConfig(
|
||||
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
|
||||
)
|
||||
public interface HouseMapperConfig {
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.nullcheck.strategy;
|
||||
|
||||
import org.mapstruct.BeanMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.NullValueCheckStrategy;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper(config = HouseMapperConfig.class)
|
||||
public interface HouseMapperWithConfig {
|
||||
|
||||
HouseMapperWithConfig INSTANCE = Mappers.getMapper( HouseMapperWithConfig.class );
|
||||
|
||||
HouseEntity mapWithNvcsOnMapper(HouseDto in);
|
||||
|
||||
@BeanMapping(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION)
|
||||
HouseEntity mapWithNvcsOnBean(HouseDto in);
|
||||
|
||||
@BeanMapping(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION)
|
||||
@Mapping(target = "number", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
|
||||
HouseEntity mapWithNvcsOnMapping(HouseDto in);
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.nullcheck.strategy;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.testutil.IssueKey;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@IssueKey("1571")
|
||||
@WithClasses({
|
||||
HouseDto.class,
|
||||
HouseEntity.class,
|
||||
HouseMapper.class,
|
||||
HouseMapperConfig.class,
|
||||
HouseMapperWithConfig.class
|
||||
})
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
public class NullValueCheckTest {
|
||||
|
||||
@Test
|
||||
public void testDefinedOnMapper() {
|
||||
|
||||
HouseEntity entity = HouseMapper.INSTANCE.mapWithNvcsOnMapper( new HouseDto() );
|
||||
|
||||
assertThat( entity ).isNotNull();
|
||||
assertThat( entity.ownerSet() ).isFalse();
|
||||
assertThat( entity.numberSet() ).isFalse();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefinedOnBean() {
|
||||
|
||||
HouseEntity entity = HouseMapper.INSTANCE.mapWithNvcsOnBean( new HouseDto() );
|
||||
|
||||
assertThat( entity ).isNotNull();
|
||||
assertThat( entity.ownerSet() ).isTrue();
|
||||
assertThat( entity.numberSet() ).isTrue();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefinedOnMapping() {
|
||||
|
||||
HouseEntity entity = HouseMapper.INSTANCE.mapWithNvcsOnMapping( new HouseDto() );
|
||||
|
||||
assertThat( entity ).isNotNull();
|
||||
assertThat( entity.ownerSet() ).isTrue();
|
||||
assertThat( entity.numberSet() ).isFalse();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefinedOnConfig() {
|
||||
|
||||
HouseEntity entity = HouseMapperWithConfig.INSTANCE.mapWithNvcsOnMapper( new HouseDto() );
|
||||
|
||||
assertThat( entity ).isNotNull();
|
||||
assertThat( entity.ownerSet() ).isFalse();
|
||||
assertThat( entity.numberSet() ).isFalse();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefinedOnConfigAndBean() {
|
||||
|
||||
HouseEntity entity = HouseMapperWithConfig.INSTANCE.mapWithNvcsOnBean( new HouseDto() );
|
||||
|
||||
assertThat( entity ).isNotNull();
|
||||
assertThat( entity.ownerSet() ).isTrue();
|
||||
assertThat( entity.numberSet() ).isTrue();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefinedOnConfigAndMapping() {
|
||||
|
||||
HouseEntity entity = HouseMapperWithConfig.INSTANCE.mapWithNvcsOnMapping( new HouseDto() );
|
||||
|
||||
assertThat( entity ).isNotNull();
|
||||
assertThat( entity.ownerSet() ).isTrue();
|
||||
assertThat( entity.numberSet() ).isFalse();
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user