#669 Documentation update for source presence checker and nullValueCheckStrategy

This commit is contained in:
sjaakd 2016-07-06 21:35:30 +02:00
parent e725b9a2c6
commit 23ebd273c8
7 changed files with 38 additions and 22 deletions

View File

@ -29,17 +29,6 @@ package org.mapstruct;
public enum NullValueCheckStrategy { public enum NullValueCheckStrategy {
/** /**
* This option includes a null check. When:
* <p>
* <ol>
* <li>a source value is directly assigned to a target</li>
* <li>a source value assigned to a target by calling a type conversion on the target first</li>
* </ol>
* <p>
* <b>NOTE:</b> mapping methods (generated or hand written) are excluded from this null check. They are intended to
* handle a null source value as 'valid' input.
*
*//**
* This option includes a null check. When: * This option includes a null check. When:
* <p> * <p>
* <ol> * <ol>
@ -56,6 +45,6 @@ public enum NullValueCheckStrategy {
/** /**
* This option always includes a null check. * This option always includes a null check.
*/ */
ALLWAYS, ALWAYS,
} }

View File

@ -1512,6 +1512,33 @@ However, by specifying `nullValueMappingStrategy = NullValueMappingStrategy.RETU
The strategy works in a hierarchical fashion. Setting `nullValueMappingStrategy` on mapping method level will override `@Mapper#nullValueMappingStrategy`, and `@Mapper#nullValueMappingStrategy` will override `@MappingConfig#nullValueMappingStrategy`. The strategy works in a hierarchical fashion. Setting `nullValueMappingStrategy` on mapping method level will override `@Mapper#nullValueMappingStrategy`, and `@Mapper#nullValueMappingStrategy` will override `@MappingConfig#nullValueMappingStrategy`.
[[checking-source-property-for-null-arguments]]
=== Controlling checking result for 'null' properties in bean mapping
MapStruct offers control over when to generate a `null` check. By default (`nullValueCheckStrategy = NullValueMappingStrategy.ON_IMPLICIT_CONVERSION`) a `null` check will be generated for:
* direct setting of source value to target value when target is primitive and is source not.
* applying type conversion and then:
.. calling the setter on the target.
.. calling another type conversion and subsequently calling the setter on the target.
.. calling a mapping method and subsequently calling the setter on the target.
First calling a mapping method on the source property is not protected by a null check. Therefor generated mapping methods will do a null check prior to carrying out mapping on a source property. Handwritten mapping methods must take care of null value checking. They have the possibility to add 'meaning' to `null`. For instance: mapping `null` to a default value.
The option `nullValueCheckStrategy = NullValueMappingStrategy.ALWAYS` will always include a null check when source is non primitive, unless a source presence checker is defined on the source bean.
The strategy works in a hierarchical fashion. `@Mapper#nullValueMappingStrategy` will override `@MappingConfig#nullValueMappingStrategy`.
[[source-presence-check]]
=== Source presence checking
Some frameworks generate bean properties that have a source presence checker. Often this is in the form of a method `hasXYZ`, `XYZ` being a property on the source bean in a bean mapping method. MapStruct will call this `hasXYZ` instead of performing a `null` check when it finds such `hasXYZ` method.
[TIP]
====
The source presence checker name can be changed in the MapStruct service provider interface (SPI). It can also be deactivated in this way.
====
[[exceptions]] [[exceptions]]
=== Exceptions === Exceptions

View File

@ -23,7 +23,6 @@ import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentTy
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.MAPPED_TYPE_CONVERTED; import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.MAPPED_TYPE_CONVERTED;
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED; import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED;
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED_MAPPED; import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED_MAPPED;
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategy.ALLWAYS;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -58,6 +57,7 @@ import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.Strings; import org.mapstruct.ap.internal.util.Strings;
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS;
/** /**
* Represents the mapping between a source and target property, e.g. from {@code String Source#foo} to * Represents the mapping between a source and target property, e.g. from {@code String Source#foo} to
@ -344,7 +344,7 @@ public class PropertyMapping extends ModelElement {
else if ( getSourcePresenceCheckerRef() != null ) { else if ( getSourcePresenceCheckerRef() != null ) {
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() ); result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
} }
else if ( ALLWAYS.equals( method.getMapperConfiguration().getNullValueCheckStrategy() ) ) { else if ( ALWAYS.equals( method.getMapperConfiguration().getNullValueCheckStrategy() ) ) {
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() ); result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
} }
else if ( result.getType() == TYPE_CONVERTED else if ( result.getType() == TYPE_CONVERTED

View File

@ -24,8 +24,8 @@ package org.mapstruct.ap.internal.prism;
* *
* @author Sean Huang * @author Sean Huang
*/ */
public enum NullValueCheckStrategy { public enum NullValueCheckStrategyPrism {
ON_IMPLICIT_CONVERSION, ON_IMPLICIT_CONVERSION,
ALLWAYS; ALWAYS;
} }

View File

@ -32,7 +32,7 @@ import org.mapstruct.ap.internal.prism.MapperConfigPrism;
import org.mapstruct.ap.internal.prism.MapperPrism; import org.mapstruct.ap.internal.prism.MapperPrism;
import org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism; import org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategy; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
/** /**
* Provides an aggregated view to the settings given via {@link org.mapstruct.Mapper} and * Provides an aggregated view to the settings given via {@link org.mapstruct.Mapper} and
@ -136,12 +136,12 @@ public class MapperConfiguration {
} }
} }
public NullValueCheckStrategy getNullValueCheckStrategy() { public NullValueCheckStrategyPrism getNullValueCheckStrategy() {
if ( mapperConfigPrism != null && mapperPrism.values.nullValueCheckStrategy() == null ) { if ( mapperConfigPrism != null && mapperPrism.values.nullValueCheckStrategy() == null ) {
return NullValueCheckStrategy.valueOf( mapperConfigPrism.nullValueCheckStrategy() ); return NullValueCheckStrategyPrism.valueOf( mapperConfigPrism.nullValueCheckStrategy() );
} }
else { else {
return NullValueCheckStrategy.valueOf( mapperPrism.nullValueCheckStrategy() ); return NullValueCheckStrategyPrism.valueOf( mapperPrism.nullValueCheckStrategy() );
} }
} }

View File

@ -27,7 +27,7 @@ import org.mapstruct.factory.Mappers;
* *
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
@Mapper( nullValueCheckStrategy = NullValueCheckStrategy.ALLWAYS ) @Mapper( nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS )
public abstract class RockFestivalMapper { public abstract class RockFestivalMapper {
public static final RockFestivalMapper INSTANCE = Mappers.getMapper( RockFestivalMapper.class ); public static final RockFestivalMapper INSTANCE = Mappers.getMapper( RockFestivalMapper.class );

View File

@ -24,7 +24,7 @@ import org.mapstruct.NullValueCheckStrategy;
* *
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
@MapperConfig( nullValueCheckStrategy = NullValueCheckStrategy.ALLWAYS ) @MapperConfig( nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS )
public interface RockFestivalMapperConfig { public interface RockFestivalMapperConfig {
} }