#1571 apply nullvaluecheck strategy on all relevant levels

This commit is contained in:
Sjaak Derksen 2018-09-24 23:35:35 +02:00 committed by GitHub
parent dcddba6853
commit 459f57e805
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 373 additions and 45 deletions

View File

@ -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.

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 );

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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 ) {

View File

@ -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
*/

View File

@ -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 ) {

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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 {
}

View File

@ -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);
}

View File

@ -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();
}
}