diff --git a/core-common/src/main/java/org/mapstruct/BeanMapping.java b/core-common/src/main/java/org/mapstruct/BeanMapping.java index ffcf547f0..bd40dc536 100644 --- a/core-common/src/main/java/org/mapstruct/BeanMapping.java +++ b/core-common/src/main/java/org/mapstruct/BeanMapping.java @@ -27,7 +27,8 @@ import java.lang.annotation.Target; /** * Configures the mapping between two bean types. *

- * Either {@link #resultType()} or {@link #qualifiedBy()} must be specified. + * Either {@link #resultType()} , {@link #qualifiedBy()} or {@link #qualifiedBy()}must be specified. + *

* * @author Sjaak Derksen */ @@ -43,13 +44,22 @@ public @interface BeanMapping { Class resultType() default void.class; /** - * A qualifier can be specified to aid the selection process of a suitable factory method. This is useful in - * case multiple factory method (hand written of internal) qualify and result in an 'Ambiguous factory methods' - * error. + * A qualifier can be specified to aid the selection process of a suitable factory method. This is useful in case + * multiple factory method (hand written of internal) qualify and result in an 'Ambiguous factory methods' error. * * A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method. * * @return the qualifiers */ Class[] qualifiedBy() default { }; + + /** + * The strategy to be applied when {@code null} is passed as source value to this bean mapping. If no + * strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} or + * {@link Mapper#nullValueMappingStrategy()} will be applied, using {@link NullValueMappingStrategy#RETURN_NULL} + * by default. + * + * @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapping. + */ + NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.DEFAULT; } diff --git a/core-common/src/main/java/org/mapstruct/IterableMapping.java b/core-common/src/main/java/org/mapstruct/IterableMapping.java index c5f5fd632..1e734b2fa 100644 --- a/core-common/src/main/java/org/mapstruct/IterableMapping.java +++ b/core-common/src/main/java/org/mapstruct/IterableMapping.java @@ -63,4 +63,15 @@ public @interface IterableMapping { * @return the elementTargetType to select */ Class elementTargetType() default void.class; + + + /** + * The strategy to be applied when {@code null} is passed as source value to this iterable mapping. If no + * strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} or + * {@link Mapper#nullValueMappingStrategy()} will be applied, using {@link NullValueMappingStrategy#RETURN_NULL} + * by default. + * + * @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapping. + */ + NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.DEFAULT; } diff --git a/core-common/src/main/java/org/mapstruct/MapMapping.java b/core-common/src/main/java/org/mapstruct/MapMapping.java index 3b6ff4830..e754ee0e8 100644 --- a/core-common/src/main/java/org/mapstruct/MapMapping.java +++ b/core-common/src/main/java/org/mapstruct/MapMapping.java @@ -93,4 +93,15 @@ public @interface MapMapping { * @return the resultType to select */ Class valueTargetType() default void.class; + + + /** + * The strategy to be applied when {@code null} is passed as source value to this map mapping. If no + * strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} or + * {@link Mapper#nullValueMappingStrategy()} will be applied, using {@link NullValueMappingStrategy#RETURN_NULL} + * by default. + * + * @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapping. + */ + NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.DEFAULT; } diff --git a/core-common/src/main/java/org/mapstruct/NullValueMapping.java b/core-common/src/main/java/org/mapstruct/NullValueMapping.java deleted file mode 100644 index 83ffd1698..000000000 --- a/core-common/src/main/java/org/mapstruct/NullValueMapping.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/) - * and/or other contributors as indicated by the @authors tag. See the - * copyright.txt file in the distribution for a full listing of all - * contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.mapstruct; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Specifies how the annotated method should deal with {@code null} values. - *

- * If no strategy is configured explicitly for a given method, the configuration from the enclosing mapper will be - * applied, using {@link NullValueMappingStrategy#RETURN_NULL} by default. - * - * @author Sjaak Derksen - */ -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.SOURCE) -public @interface NullValueMapping { - - /** - * The strategy for mapping null values. - * - * @return The strategy for mapping null values - */ - NullValueMappingStrategy value(); -} diff --git a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java index 6a390d741..1f3657ebd 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java @@ -43,7 +43,6 @@ import org.mapstruct.ap.model.source.SourceReference; import org.mapstruct.ap.option.ReportingPolicy; import org.mapstruct.ap.prism.BeanMappingPrism; import org.mapstruct.ap.prism.CollectionMappingStrategyPrism; -import org.mapstruct.ap.prism.NullValueMappingPrism; import org.mapstruct.ap.util.Executables; import org.mapstruct.ap.util.MapperConfiguration; import org.mapstruct.ap.util.Message; @@ -54,7 +53,6 @@ import org.mapstruct.ap.util.Strings; * configured by one or more {@link PropertyMapping}s. * * @author Gunnar Morling - * @author Sjaak Derksen */ public class BeanMappingMethod extends MappingMethod { @@ -106,16 +104,15 @@ public class BeanMappingMethod extends MappingMethod { reportErrorForUnmappedTargetPropertiesIfRequired(); // mapNullToDefault - NullValueMappingPrism prism = NullValueMappingPrism.getInstanceOn( method.getExecutable() ); + BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() ); boolean mapNullToDefault = - MapperConfiguration.getInstanceOn( ctx.getMapperTypeElement() ).isMapToDefault( prism ); + MapperConfiguration.getInstanceOn( ctx.getMapperTypeElement() ).isMapToDefault( beanMappingPrism ); MethodReference factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, method.getResultType() ); // if there's no factory method, try the resultType in the @BeanMapping Type resultType = null; if ( factoryMethod == null ) { - BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() ); BeanMapping beanMapping = BeanMapping.fromPrism( beanMappingPrism, method.getExecutable(), ctx.getMessager() ); if ( beanMapping != null && beanMapping.getResultType() != null ) { diff --git a/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java index e3cc04477..b1b3462af 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java @@ -30,7 +30,7 @@ import org.mapstruct.ap.model.assignment.SetterWrapper; import org.mapstruct.ap.model.common.Parameter; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.source.Method; -import org.mapstruct.ap.prism.NullValueMappingPrism; +import org.mapstruct.ap.prism.IterableMappingPrism; import org.mapstruct.ap.util.MapperConfiguration; import org.mapstruct.ap.util.Message; import org.mapstruct.ap.util.Strings; @@ -125,7 +125,7 @@ public class IterableMappingMethod extends MappingMethod { assignment = new SetterWrapper( assignment, method.getThrownTypes() ); } // mapNullToDefault - NullValueMappingPrism prism = NullValueMappingPrism.getInstanceOn( method.getExecutable() ); + IterableMappingPrism prism = IterableMappingPrism.getInstanceOn( method.getExecutable() ); boolean mapNullToDefault = MapperConfiguration.getInstanceOn( ctx.getMapperTypeElement() ).isMapToDefault( prism ); diff --git a/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java index 68ba2dacb..5b119a218 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java @@ -28,7 +28,7 @@ import org.mapstruct.ap.model.assignment.LocalVarWrapper; import org.mapstruct.ap.model.common.Parameter; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.source.Method; -import org.mapstruct.ap.prism.NullValueMappingPrism; +import org.mapstruct.ap.prism.MapMappingPrism; import org.mapstruct.ap.util.MapperConfiguration; import org.mapstruct.ap.util.Message; import org.mapstruct.ap.util.Strings; @@ -146,7 +146,7 @@ public class MapMappingMethod extends MappingMethod { } // mapNullToDefault - NullValueMappingPrism prism = NullValueMappingPrism.getInstanceOn( method.getExecutable() ); + MapMappingPrism prism = MapMappingPrism.getInstanceOn( method.getExecutable() ); boolean mapNullToDefault = MapperConfiguration.getInstanceOn( ctx.getMapperTypeElement() ).isMapToDefault( prism ); diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/BeanMapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/BeanMapping.java index 2df68a11c..550150215 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/BeanMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/BeanMapping.java @@ -24,6 +24,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.prism.BeanMappingPrism; +import org.mapstruct.ap.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.util.Message; @@ -44,7 +45,9 @@ public class BeanMapping { } boolean resultTypeIsDefined = !TypeKind.VOID.equals( beanMapping.resultType().getKind() ); - if ( !resultTypeIsDefined && beanMapping.qualifiedBy().isEmpty() ) { + boolean nullValueMappingIsDefault = + beanMapping.nullValueMappingStrategy().equals( NullValueMappingStrategyPrism.DEFAULT.toString() ); + if ( !resultTypeIsDefined && beanMapping.qualifiedBy().isEmpty() && nullValueMappingIsDefault ) { messager.printMessage( method, Message.BEANMAPPING_NO_ELEMENTS ); } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java index 1815f533f..3a5160bd8 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java @@ -27,6 +27,7 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.prism.IterableMappingPrism; +import org.mapstruct.ap.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.util.Message; /** @@ -49,9 +50,12 @@ public class IterableMapping { } boolean elementTargetTypeIsDefined = !TypeKind.VOID.equals( iterableMapping.elementTargetType().getKind() ); + boolean nullValueMappingIsDefault = + iterableMapping.nullValueMappingStrategy().equals( NullValueMappingStrategyPrism.DEFAULT.toString() ); if ( !elementTargetTypeIsDefined && iterableMapping.dateFormat().isEmpty() - && iterableMapping.qualifiedBy().isEmpty() ) { + && iterableMapping.qualifiedBy().isEmpty() + && nullValueMappingIsDefault) { messager.printMessage( method, Message.ITERABLEMAPPING_NO_ELEMENTS ); } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java index 57ed64ac2..f80cda089 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java @@ -26,6 +26,7 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.prism.MapMappingPrism; +import org.mapstruct.ap.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.util.Message; /** @@ -48,7 +49,8 @@ public class MapMapping { if ( mapMapping == null ) { return null; } - + boolean nullValueMappingIsDefault = + mapMapping.nullValueMappingStrategy().equals( NullValueMappingStrategyPrism.DEFAULT.toString() ); boolean keyTargetTypeIsDefined = !TypeKind.VOID.equals( mapMapping.keyTargetType().getKind() ); boolean valueTargetTypeIsDefined = !TypeKind.VOID.equals( mapMapping.valueTargetType().getKind() ); if ( mapMapping.keyDateFormat().isEmpty() @@ -56,7 +58,8 @@ public class MapMapping { && mapMapping.valueDateFormat().isEmpty() && mapMapping.valueQualifiedBy().isEmpty() && !keyTargetTypeIsDefined - && !valueTargetTypeIsDefined ) { + && !valueTargetTypeIsDefined + && nullValueMappingIsDefault ) { messager.printMessage( method, Message.MAPMAPPING_NO_ELEMENTS ); } diff --git a/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java b/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java index fca54dccb..d559e7e1c 100644 --- a/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java +++ b/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java @@ -33,7 +33,6 @@ import org.mapstruct.MapperConfig; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; import org.mapstruct.Mappings; -import org.mapstruct.NullValueMapping; import org.mapstruct.Qualifier; import org.mapstruct.TargetType; @@ -56,7 +55,6 @@ import org.mapstruct.TargetType; @GeneratePrism(value = InheritConfiguration.class, publicAccess = true), @GeneratePrism(value = InheritInverseConfiguration.class, publicAccess = true), @GeneratePrism(value = Qualifier.class, publicAccess = true), - @GeneratePrism(value = NullValueMapping.class, publicAccess = true), // external types @GeneratePrism(value = XmlElementDecl.class, publicAccess = true) diff --git a/processor/src/main/java/org/mapstruct/ap/util/MapperConfiguration.java b/processor/src/main/java/org/mapstruct/ap/util/MapperConfiguration.java index 27a36ed7b..702566610 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/MapperConfiguration.java +++ b/processor/src/main/java/org/mapstruct/ap/util/MapperConfiguration.java @@ -30,11 +30,13 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.option.ReportingPolicy; +import org.mapstruct.ap.prism.BeanMappingPrism; import org.mapstruct.ap.prism.CollectionMappingStrategyPrism; +import org.mapstruct.ap.prism.IterableMappingPrism; +import org.mapstruct.ap.prism.MapMappingPrism; import org.mapstruct.ap.prism.MapperConfigPrism; import org.mapstruct.ap.prism.MapperPrism; import org.mapstruct.ap.prism.MappingInheritanceStrategyPrism; -import org.mapstruct.ap.prism.NullValueMappingPrism; import org.mapstruct.ap.prism.NullValueMappingStrategyPrism; /** @@ -132,17 +134,52 @@ public class MapperConfiguration { return MappingInheritanceStrategyPrism.EXPLICIT; } - public boolean isMapToDefault(NullValueMappingPrism mapNullToDefault) { + public boolean isMapToDefault(BeanMappingPrism mapNullToDefault) { // check on method level if ( mapNullToDefault != null ) { NullValueMappingStrategyPrism methodPolicy - = NullValueMappingStrategyPrism.valueOf( mapNullToDefault.value() ); + = NullValueMappingStrategyPrism.valueOf( mapNullToDefault.nullValueMappingStrategy() ); if ( methodPolicy != NullValueMappingStrategyPrism.DEFAULT ) { return methodPolicy == NullValueMappingStrategyPrism.RETURN_DEFAULT; } } + return isMapToDefaultOnMapperAndMappingConfigLevel(); + + } + + public boolean isMapToDefault(MapMappingPrism mapNullToDefault) { + + // check on method level + if ( mapNullToDefault != null ) { + NullValueMappingStrategyPrism methodPolicy + = NullValueMappingStrategyPrism.valueOf( mapNullToDefault.nullValueMappingStrategy() ); + if ( methodPolicy != NullValueMappingStrategyPrism.DEFAULT ) { + return methodPolicy == NullValueMappingStrategyPrism.RETURN_DEFAULT; + } + } + + return isMapToDefaultOnMapperAndMappingConfigLevel(); + } + + public boolean isMapToDefault(IterableMappingPrism mapNullToDefault) { + + // check on method level + if ( mapNullToDefault != null ) { + NullValueMappingStrategyPrism methodPolicy + = NullValueMappingStrategyPrism.valueOf( mapNullToDefault.nullValueMappingStrategy() ); + if ( methodPolicy != NullValueMappingStrategyPrism.DEFAULT ) { + return methodPolicy == NullValueMappingStrategyPrism.RETURN_DEFAULT; + } + } + + return isMapToDefaultOnMapperAndMappingConfigLevel(); + } + + + private boolean isMapToDefaultOnMapperAndMappingConfigLevel() { + // check on mapper level NullValueMappingStrategyPrism mapperPolicy = NullValueMappingStrategyPrism.valueOf( mapperPrism.nullValueMappingStrategy() ); diff --git a/processor/src/main/java/org/mapstruct/ap/util/Message.java b/processor/src/main/java/org/mapstruct/ap/util/Message.java index 8db9c5086..7f75126ce 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/Message.java +++ b/processor/src/main/java/org/mapstruct/ap/util/Message.java @@ -28,7 +28,7 @@ import javax.tools.Diagnostic; public enum Message { // CHECKSTYLE:OFF - BEANMAPPING_NO_ELEMENTS( "'resultType' and 'qualifiedBy' are undefined in @BeanMapping, define at least one of them." ), + BEANMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'resultType' and 'qualifiedBy' are undefined in @BeanMapping, define at least one of them." ), BEANMAPPING_NOT_ASSIGNABLE( "%s not assignable to: %s." ), BEANMAPPING_UNKNOWN_PROPERTY_IN_RETURNTYPE( "Unknown property \"%s\" in return type." ), BEANMAPPING_SEVERAL_POSSIBLE_SOURCES( "Several possible source properties for target property \"%s\"." ), @@ -52,10 +52,10 @@ public enum Message { MAPMAPPING_KEY_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source key type to target key type." ), MAPMAPPING_VALUE_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source value type to target value type." ), - MAPMAPPING_NO_ELEMENTS( "'keyDateFormat', 'keyQualifiedBy', 'keyTargetType', 'valueDateFormat', 'valueQualfiedBy' and 'valueTargetType' are all undefined in @MapMapping, define at least one of them." ), + MAPMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'keyDateFormat', 'keyQualifiedBy', 'keyTargetType', 'valueDateFormat', 'valueQualfiedBy' and 'valueTargetType' are all undefined in @MapMapping, define at least one of them." ), ITERABLEMAPPING_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source element type into target element type." ), - ITERABLEMAPPING_NO_ELEMENTS( "'dateformat', 'qualifiedBy' and 'elementTargetType' are undefined in @IterableMapping, define at least one of them." ), + ITERABLEMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy','dateformat', 'qualifiedBy' and 'elementTargetType' are undefined in @IterableMapping, define at least one of them." ), ENUMMAPPING_MULTIPLE_TARGETS( "One enum constant must not be mapped to more than one target constant, but constant %s is mapped to %s." ), ENUMMAPPING_UNDEFINED_SOURCE( "A source constant must be specified for mappings of an enum mapping method." ), diff --git a/processor/src/test/java/org/mapstruct/ap/test/array/ScienceMapper.java b/processor/src/test/java/org/mapstruct/ap/test/array/ScienceMapper.java index 203773918..a646820a9 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/array/ScienceMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/array/ScienceMapper.java @@ -19,10 +19,10 @@ package org.mapstruct.ap.test.array; import java.util.List; +import org.mapstruct.IterableMapping; import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; -import org.mapstruct.NullValueMapping; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.ap.test.array._target.ScientistDto; import org.mapstruct.ap.test.array.source.Scientist; @@ -43,33 +43,33 @@ public interface ScienceMapper { ScientistDto[] scientistsToDtos(Scientist[] scientists, @MappingTarget ScientistDto[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) boolean[] nvmMapping(boolean[] source, @MappingTarget boolean[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) short[] nvmMapping(int[] source, @MappingTarget short[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) char[] nvmMapping(String[] source, @MappingTarget char[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) int[] nvmMapping(int[] source, @MappingTarget int[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) long[] nvmMapping(int[] source, @MappingTarget long[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) float[] nvmMapping(int[] source, @MappingTarget float[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) double[] nvmMapping(int[] source, @MappingTarget double[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) String[] nvmMapping(int[] source, @MappingTarget String[] target); void nvmMappingVoidReturnNull(int[] source, @MappingTarget long[] target); - @NullValueMapping( NullValueMappingStrategy.RETURN_DEFAULT ) + @IterableMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) void nvmMappingVoidReturnDefault(int[] source, @MappingTarget long[] target); diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_374/Issue374Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_374/Issue374Mapper.java index 3e35fdc88..6069f2297 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/bugs/_374/Issue374Mapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_374/Issue374Mapper.java @@ -20,10 +20,10 @@ package org.mapstruct.ap.test.bugs._374; import java.util.List; import java.util.Map; +import org.mapstruct.BeanMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; -import org.mapstruct.NullValueMapping; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.factory.Mappers; @@ -39,7 +39,7 @@ public interface Issue374Mapper { @Mapping(target = "constant", constant = "test") Target map(Source source, @MappingTarget Target target); - @NullValueMapping( NullValueMappingStrategy.RETURN_NULL ) + @BeanMapping( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL ) @Mapping(target = "constant", constant = "test") Target map2(Source source, @MappingTarget Target target); diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/erroneous/ErroneousCollectionMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/collection/erroneous/ErroneousCollectionMappingTest.java index e3de4f9f7..414d36497 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/collection/erroneous/ErroneousCollectionMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/erroneous/ErroneousCollectionMappingTest.java @@ -65,8 +65,8 @@ public class ErroneousCollectionMappingTest { @Diagnostic(type = EmptyItererableMappingMapper.class, kind = Kind.ERROR, line = 35, - messageRegExp = "'dateformat', 'qualifiedBy' and 'elementTargetType' are undefined in " - + "@IterableMapping, define at least one of them.") + messageRegExp = "'nullValueMappingStrategy','dateformat', 'qualifiedBy' and 'elementTargetType' are " + + "undefined in @IterableMapping, define at least one of them.") } ) public void shouldFailOnEmptyIterableAnnotation() { @@ -81,9 +81,9 @@ public class ErroneousCollectionMappingTest { @Diagnostic(type = EmptyMapMappingMapper.class, kind = Kind.ERROR, line = 34, - messageRegExp = "'keyDateFormat', 'keyQualifiedBy', 'keyTargetType', 'valueDateFormat', " - + "'valueQualfiedBy' and 'valueTargetType' are all undefined in @MapMapping, define at least " - + "one of them.") + messageRegExp = "'nullValueMappingStrategy', 'keyDateFormat', 'keyQualifiedBy', 'keyTargetType', " + + "'valueDateFormat', 'valueQualfiedBy' and 'valueTargetType' are all undefined in @MapMapping, " + + "define at least one of them.") } ) public void shouldFailOnEmptyMapAnnotation() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapper.java b/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapper.java index b892cd47d..1da3360a8 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapper.java @@ -21,11 +21,13 @@ package org.mapstruct.ap.test.nullvaluemapping; import java.util.List; import java.util.Map; import java.util.UUID; +import org.mapstruct.BeanMapping; +import org.mapstruct.IterableMapping; +import org.mapstruct.MapMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; -import org.mapstruct.NullValueMapping; import org.mapstruct.ap.test.nullvaluemapping._target.CarDto; import org.mapstruct.ap.test.nullvaluemapping._target.DriverAndCarDto; import org.mapstruct.ap.test.nullvaluemapping.source.Car; @@ -39,7 +41,7 @@ public interface CarMapper { CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); - @NullValueMapping(RETURN_DEFAULT) + @BeanMapping(nullValueMappingStrategy = RETURN_DEFAULT) @Mappings({ @Mapping(target = "seatCount", source = "numberOfSeats"), @Mapping(target = "model", constant = "ModelT"), @@ -47,7 +49,7 @@ public interface CarMapper { }) CarDto carToCarDto(Car car); - @NullValueMapping(RETURN_DEFAULT) + @BeanMapping(nullValueMappingStrategy = RETURN_DEFAULT) @Mappings({ @Mapping(target = "seatCount", source = "car.numberOfSeats"), @Mapping(target = "model", source = "model"), // TODO, should not be needed, must be made based on name only @@ -56,13 +58,13 @@ public interface CarMapper { CarDto carToCarDto(Car car, String model); - @NullValueMapping(RETURN_DEFAULT) + @IterableMapping(nullValueMappingStrategy = RETURN_DEFAULT) List carsToCarDtos(List cars); - @NullValueMapping(RETURN_DEFAULT) + @MapMapping(nullValueMappingStrategy = RETURN_DEFAULT) Map carsToCarDtoMap(Map cars); - @NullValueMapping(RETURN_DEFAULT) + @BeanMapping(nullValueMappingStrategy = RETURN_DEFAULT) DriverAndCarDto driverAndCarToDto(Driver driver, Car car); DriverAndCarDto driverAndCarToDtoReturningNull(Driver driver, Car car); diff --git a/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnConfig.java b/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnConfig.java index b95d66c5f..912e14daf 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnConfig.java +++ b/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnConfig.java @@ -21,11 +21,12 @@ package org.mapstruct.ap.test.nullvaluemapping; import java.util.List; import java.util.Map; import java.util.UUID; +import org.mapstruct.IterableMapping; +import org.mapstruct.MapMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; -import org.mapstruct.NullValueMapping; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.ap.test.nullvaluemapping._target.CarDto; import org.mapstruct.ap.test.nullvaluemapping.source.Car; @@ -44,10 +45,10 @@ public interface CarMapperSettingOnConfig { CarDto carToCarDto(Car car); - @NullValueMapping(NullValueMappingStrategy.DEFAULT) + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.DEFAULT, dateFormat = "dummy") List carsToCarDtos(List cars); - @NullValueMapping(NullValueMappingStrategy.RETURN_NULL) + @MapMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) Map carsToCarDtoMap(Map cars); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnMapper.java b/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnMapper.java index 70bc3089b..597b750ac 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/nullvaluemapping/CarMapperSettingOnMapper.java @@ -21,11 +21,12 @@ package org.mapstruct.ap.test.nullvaluemapping; import java.util.List; import java.util.Map; import java.util.UUID; +import org.mapstruct.IterableMapping; +import org.mapstruct.MapMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; -import org.mapstruct.NullValueMapping; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.ap.test.nullvaluemapping._target.CarDto; import org.mapstruct.ap.test.nullvaluemapping.source.Car; @@ -44,10 +45,10 @@ public interface CarMapperSettingOnMapper { CarDto carToCarDto(Car car); - @NullValueMapping(NullValueMappingStrategy.RETURN_DEFAULT) + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT) List carsToCarDtos(List cars); - @NullValueMapping(NullValueMappingStrategy.RETURN_NULL) + @MapMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) Map carsToCarDtoMap(Map cars); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/QualifierTest.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/QualifierTest.java index 58bd4bd1e..c58d5726f 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/QualifierTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/QualifierTest.java @@ -186,8 +186,8 @@ public class QualifierTest { @Diagnostic( type = ErroneousMovieFactoryMapper.class, kind = Kind.ERROR, line = 37, - messageRegExp = "'resultType' and 'qualifiedBy' are undefined in @BeanMapping, " - + "define at least one of them." ) + messageRegExp = "'nullValueMappingStrategy', 'resultType' and 'qualifiedBy' are undefined in " + + "@BeanMapping, define at least one of them." ) } ) public void testEmptyBeanMapping() {