#1306 Add new NullValuePropertyMappingStrategy which leaves @MappingTarget untouched (#1618)

This commit is contained in:
Sjaak Derksen 2018-10-25 22:14:26 +01:00 committed by GitHub
parent cfe0f6250c
commit 288813fc3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 1161 additions and 195 deletions

View File

@ -54,7 +54,7 @@ public @interface BeanMapping {
String[] qualifiedByName() default { }; String[] qualifiedByName() default { };
/** /**
* The strategy to be applied when {@code null} is passed as source value to this bean mapping. If no * The strategy to be applied when {@code null} is passed as source bean argument value to this bean mapping. If no
* strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} or * strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} or
* {@link Mapper#nullValueMappingStrategy()} will be applied, using {@link NullValueMappingStrategy#RETURN_NULL} * {@link Mapper#nullValueMappingStrategy()} will be applied, using {@link NullValueMappingStrategy#RETURN_NULL}
* by default. * by default.
@ -63,6 +63,18 @@ public @interface BeanMapping {
*/ */
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL;
/**
* The strategy to be applied when a source bean property is {@code null} or not present. If no strategy is
* configured, the strategy given via {@link MapperConfig#nullValuePropertyMappingStrategy()} or
* {@link Mapper#nullValuePropertyMappingStrategy()} will be applied,
* {@link NullValuePropertyMappingStrategy#SET_TO_NULL} will be used by default.
*
* @return The strategy to be applied when {@code null} is passed as source property value or the source property
* is not present.
*/
NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy()
default NullValuePropertyMappingStrategy.SET_TO_NULL;
/** /**
* Determines when to include a null check on the source property value of a bean mapping. * Determines when to include a null check on the source property value of a bean mapping.
* *

View File

@ -129,14 +129,25 @@ public @interface Mapper {
CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.ACCESSOR_ONLY; CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.ACCESSOR_ONLY;
/** /**
* The strategy to be applied when {@code null} is passed as source value to the methods of this mapper. If no * The strategy to be applied when {@code null} is passed as source argument value to the methods of this mapper.
* strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} will be applied, * If no strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} will be
* using {@link NullValueMappingStrategy#RETURN_NULL} by default. * 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 mapper. * @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapper.
*/ */
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL;
/**
* The strategy to be applied when a source bean property is {@code null} or not present. If no strategy is
* configured, the strategy given via {@link MapperConfig#nullValuePropertyMappingStrategy()} will be applied,
* {@link NullValuePropertyMappingStrategy#SET_TO_NULL} will be used by default.
*
* @return The strategy to be applied when {@code null} is passed as source property value or the source property
* is not present.
*/
NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() default
NullValuePropertyMappingStrategy.SET_TO_NULL;
/** /**
* The strategy to use for applying method-level configuration annotations of prototype methods in the interface * The strategy to use for applying method-level configuration annotations of prototype methods in the interface
* specified with {@link #config()}. Annotations that can be inherited are for example {@link Mapping}, * specified with {@link #config()}. Annotations that can be inherited are for example {@link Mapping},

View File

@ -115,13 +115,23 @@ public @interface MapperConfig {
CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.ACCESSOR_ONLY; CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.ACCESSOR_ONLY;
/** /**
* The strategy to be applied when {@code null} is passed as source value to mapping methods. If no strategy is * The strategy to be applied when {@code null} is passed as source argument value to mapping methods. If no
* configured, {@link NullValueMappingStrategy#RETURN_NULL} will be used by default. * strategy is configured, {@link NullValueMappingStrategy#RETURN_NULL} will be used by default.
* *
* @return The strategy to be applied when {@code null} is passed as source value to mapping methods. * @return The strategy to be applied when {@code null} is passed as source value to mapping methods.
*/ */
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL;
/**
* The strategy to be applied when a source bean property is {@code null} or not present. If no strategy is
* configured, {@link NullValuePropertyMappingStrategy#SET_TO_NULL} will be used by default.
*
* @return The strategy to be applied when {@code null} is passed as source property value or the source property
* is not present.
*/
NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() default
NullValuePropertyMappingStrategy.SET_TO_NULL;
/** /**
* The strategy to use for applying method-level configuration annotations of prototype methods in the interface * The strategy to use for applying method-level configuration annotations of prototype methods in the interface
* annotated with this annotation. Annotations that can be inherited are for example {@link Mapping}, * annotated with this annotation. Annotations that can be inherited are for example {@link Mapping},

View File

@ -242,6 +242,7 @@ public @interface Mapping {
* If not possible, MapStruct will try to apply a user defined mapping method. * If not possible, MapStruct will try to apply a user defined mapping method.
* </li> * </li>
* </ul> * </ul>
* <p>
* </li> * </li>
* <li>other * <li>other
* <p> * <p>
@ -267,4 +268,18 @@ public @interface Mapping {
*/ */
NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION; NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION;
/**
* The strategy to be applied when the source property is {@code null} or not present. If no strategy is configured,
* the strategy given via {@link MapperConfig#nullValuePropertyMappingStrategy()},
* {@link BeanMapping#nullValuePropertyMappingStrategy()} or
* {@link Mapper#nullValuePropertyMappingStrategy()} will be applied.
*
* {@link NullValuePropertyMappingStrategy#SET_TO_NULL} will be used by default.
*
* @return The strategy to be applied when {@code null} is passed as source property value or the source property
* is not present.
*/
NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy()
default NullValuePropertyMappingStrategy.SET_TO_NULL;
} }

View File

@ -16,17 +16,18 @@ public final class MappingConstants {
} }
/** /**
* Represents a {@code null} source or target. * In an {@link ValueMapping} this represents a {@code null} source or target.
*/ */
public static final String NULL = "<NULL>"; public static final String NULL = "<NULL>";
/** /**
* Represents any source that is not already mapped by either a defined mapping or by means of name based mapping. * In an {@link ValueMapping} this represents any source that is not already mapped by either a defined mapping or
* by means of name based mapping.
*/ */
public static final String ANY_REMAINING = "<ANY_REMAINING>"; public static final String ANY_REMAINING = "<ANY_REMAINING>";
/** /**
* Represents any source that is not already mapped by a defined mapping. * In an {@link ValueMapping} this represents any source that is not already mapped by a defined mapping.
*/ */
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>"; public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";

View File

@ -33,6 +33,6 @@ public enum NullValueCheckStrategy {
/** /**
* This option always includes a null check. * This option always includes a null check.
*/ */
ALWAYS, ALWAYS;
} }

View File

@ -0,0 +1,37 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct;
/**
* Strategy for dealing with {@code null} or not present properties in the source bean. The
* {@link NullValuePropertyMappingStrategy} can be defined on {@link MapperConfig}, {@link Mapper}, {@link BeanMapping}
* and {@link Mapping}.
* Precedence is arranged in the reverse order. So {@link Mapping} will override {@link BeanMapping}, will
* overide {@link Mapper}
*
* The enum only applies to update method: methods that update a pre-existing target (annotated with
* {@code @}{@link MappingTarget}).
*
* @author Sjaak Derksen
*/
public enum NullValuePropertyMappingStrategy {
/**
* If a source bean property equals {@code null} the target bean property will be set explicitly to {@code null}.
*/
SET_TO_NULL,
/**
* If a source bean property equals {@code null} the target bean property will be set to its default value.
*/
SET_TO_DEFAULT,
/**
* If a source bean property equals {@code null} the target bean property will be ignored and retain its
* existing value.
*/
IGNORE;
}

View File

@ -2107,6 +2107,20 @@ 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`.
[[mapping-result-for-null-properties]]
=== Controlling mapping result for 'null' properties in bean mappings (update mapping methods only).
MapStruct offers control over the property to set in an `@MappingTarget` annotated target bean when the source property equals `null` or the presence check method yields absent.
By default the source property will be set to null. However:
1. By specifying `nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT` on `@Mapping`, `@BeanMapping`, `@Mapper` or `@MappingConfig`, the mapping result can be altered to return *default* values (`Object`, `ArrayList`, `HashMap`).
2. By specifying `nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE` on `@Mapping`, `@BeanMapping`, `@Mapper` or `@MappingConfig`, the mapping result will be equal to the original value of the `@MappingTarget` annotated target.
The strategy works in a hierarchical fashion. Setting `Mapping#nullValuePropertyMappingStrategy` on mapping level will override `nullValuePropertyMappingStrategy` on mapping method level will override `@Mapper#nullValuePropertyMappingStrategy`, and `@Mapper#nullValuePropertyMappingStrategy` will override `@MappingConfig#nullValuePropertyMappingStrategy`.
[[checking-source-property-for-null-arguments]] [[checking-source-property-for-null-arguments]]
=== Controlling checking result for 'null' properties in bean mapping === Controlling checking result for 'null' properties in bean mapping
@ -2122,7 +2136,7 @@ First calling a mapping method on the source property is not protected by a null
The option `nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS` will always include a null check when source is non primitive, unless a source presence checker is defined on the source bean. The option `nullValueCheckStrategy = NullValueCheckStrategy.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#nullValueCheckStrategy` will override `@MappingConfig#nullValueCheckStrategy`. The strategy works in a hierarchical fashion. `@Mapping#nullValueCheckStrategy` will override `@BeanMapping#nullValueCheckStrategy`, `@BeanMapping#nullValueCheckStrategy` will override `@Mapper#nullValueCheckStrategy` and `@Mapper#nullValueCheckStrategy` will override `@MappingConfig#nullValueCheckStrategy`.
[[source-presence-check]] [[source-presence-check]]
=== Source presence checking === Source presence checking

View File

@ -477,7 +477,8 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
.dependsOn( mapping.getDependsOn() ) .dependsOn( mapping.getDependsOn() )
.defaultValue( mapping.getDefaultValue() ) .defaultValue( mapping.getDefaultValue() )
.defaultJavaExpression( mapping.getDefaultJavaExpression() ) .defaultJavaExpression( mapping.getDefaultJavaExpression() )
.nullValueCheckStrategyPrism( mapping.getNullValueCheckStrategy() ) .nullValueCheckStrategy( mapping.getNullValueCheckStrategy() )
.nullValuePropertyMappingStrategy( mapping.getNullValuePropertyMappingStrategy() )
.build(); .build();
handledTargets.add( propertyName ); handledTargets.add( propertyName );
unprocessedSourceParameters.remove( sourceRef.getParameter() ); unprocessedSourceParameters.remove( sourceRef.getParameter() );
@ -594,8 +595,9 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
.existingVariableNames( existingVariableNames ) .existingVariableNames( existingVariableNames )
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() ) .dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() )
.forgeMethodWithMappingOptions( extractAdditionalOptions( targetPropertyName, false ) ) .forgeMethodWithMappingOptions( extractAdditionalOptions( targetPropertyName, false ) )
.nullValueCheckStrategyPrism( mapping != null ? mapping.getNullValueCheckStrategy() .nullValueCheckStrategy( mapping != null ? mapping.getNullValueCheckStrategy() : null )
: null ) .nullValuePropertyMappingStrategy( mapping != null ?
mapping.getNullValuePropertyMappingStrategy() : null )
.build(); .build();
unprocessedSourceParameters.remove( sourceParameter ); unprocessedSourceParameters.remove( sourceParameter );
@ -659,7 +661,9 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
.existingVariableNames( existingVariableNames ) .existingVariableNames( existingVariableNames )
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() ) .dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() )
.forgeMethodWithMappingOptions( extractAdditionalOptions( targetProperty.getKey(), false ) ) .forgeMethodWithMappingOptions( extractAdditionalOptions( targetProperty.getKey(), false ) )
.nullValueCheckStrategyPrism( mapping != null ? mapping.getNullValueCheckStrategy() : null ) .nullValueCheckStrategy( mapping != null ? mapping.getNullValueCheckStrategy() : null )
.nullValuePropertyMappingStrategy( mapping != null ?
mapping.getNullValuePropertyMappingStrategy() : null )
.build(); .build();
propertyMappings.add( propertyMapping ); propertyMappings.add( propertyMapping );

View File

@ -17,7 +17,7 @@ import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism; import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.accessor.Accessor; import org.mapstruct.ap.internal.util.accessor.Accessor;
@ -57,7 +57,8 @@ public class CollectionAssignmentBuilder {
private PropertyMapping.TargetWriteAccessorType targetAccessorType; private PropertyMapping.TargetWriteAccessorType targetAccessorType;
private Assignment assignment; private Assignment assignment;
private SourceRHS sourceRHS; private SourceRHS sourceRHS;
private NullValueCheckStrategyPrism nullValueCheckStrategy; private NullValueCheckStrategyPrism nvcs;
private NullValuePropertyMappingStrategyPrism nvpms;
public CollectionAssignmentBuilder mappingBuilderContext(MappingBuilderContext ctx) { public CollectionAssignmentBuilder mappingBuilderContext(MappingBuilderContext ctx) {
this.ctx = ctx; this.ctx = ctx;
@ -109,8 +110,13 @@ public class CollectionAssignmentBuilder {
return this; return this;
} }
public CollectionAssignmentBuilder nullValueCheckStrategy( NullValueCheckStrategyPrism nullValueCheckStrategy ) { public CollectionAssignmentBuilder nullValueCheckStrategy( NullValueCheckStrategyPrism nvcs ) {
this.nullValueCheckStrategy = nullValueCheckStrategy; this.nvcs = nvcs;
return this;
}
public CollectionAssignmentBuilder nullValuePropertyMappingStrategy( NullValuePropertyMappingStrategyPrism nvpms ) {
this.nvpms = nvpms;
return this; return this;
} }
@ -143,7 +149,7 @@ public class CollectionAssignmentBuilder {
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType ), PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType ),
targetType, targetType,
true, true,
mapNullToDefault() nvpms
); );
} }
else if ( method.isUpdateMethod() && !targetImmutable ) { else if ( method.isUpdateMethod() && !targetImmutable ) {
@ -152,22 +158,21 @@ public class CollectionAssignmentBuilder {
result, result,
method.getThrownTypes(), method.getThrownTypes(),
targetType, targetType,
nullValueCheckStrategy, nvcs,
nvpms,
ctx.getTypeFactory(), ctx.getTypeFactory(),
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType ), PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType )
mapNullToDefault()
); );
} }
else if ( result.getType() == Assignment.AssignmentType.DIRECT || else if ( result.getType() == Assignment.AssignmentType.DIRECT ||
nullValueCheckStrategy == NullValueCheckStrategyPrism.ALWAYS ) { nvcs == NullValueCheckStrategyPrism.ALWAYS ) {
result = new SetterWrapperForCollectionsAndMapsWithNullCheck( result = new SetterWrapperForCollectionsAndMapsWithNullCheck(
result, result,
method.getThrownTypes(), method.getThrownTypes(),
targetType, targetType,
ctx.getTypeFactory(), ctx.getTypeFactory(),
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType ), PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType )
mapNullToDefault()
); );
} }
else { else {
@ -201,9 +206,4 @@ public class CollectionAssignmentBuilder {
return result; return result;
} }
private boolean mapNullToDefault() {
return method.getMapperConfiguration().getNullValueMappingStrategy()
== NullValueMappingStrategyPrism.RETURN_DEFAULT;
}
} }

View File

@ -38,6 +38,7 @@ import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.model.source.SourceReference; import org.mapstruct.ap.internal.model.source.SourceReference;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils; import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.Executables; import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.MapperConfiguration;
@ -197,7 +198,9 @@ public class PropertyMapping extends ModelElement {
private MappingOptions forgeMethodWithMappingOptions; private MappingOptions forgeMethodWithMappingOptions;
private boolean forceUpdateMethod; private boolean forceUpdateMethod;
private boolean forgedNamedBased = true; private boolean forgedNamedBased = true;
private NullValueCheckStrategyPrism nullValueCheckStrategyPrism; private NullValueCheckStrategyPrism nvcs;
private NullValueMappingStrategyPrism nvms;
private NullValuePropertyMappingStrategyPrism nvpms;
PropertyMappingBuilder() { PropertyMappingBuilder() {
super( PropertyMappingBuilder.class ); super( PropertyMappingBuilder.class );
@ -254,13 +257,33 @@ public class PropertyMapping extends ModelElement {
return this; return this;
} }
public PropertyMappingBuilder nullValueCheckStrategyPrism( public PropertyMappingBuilder nullValueCheckStrategy(NullValueCheckStrategyPrism nvcs ) {
NullValueCheckStrategyPrism nullValueCheckStrategyPrism) { this.nvcs = nvcs;
this.nullValueCheckStrategyPrism = nullValueCheckStrategyPrism; return this;
}
public PropertyMappingBuilder nullValuePropertyMappingStrategy( NullValuePropertyMappingStrategyPrism nvpms ) {
this.nvpms = nvpms;
return this; return this;
} }
public PropertyMapping build() { public PropertyMapping build() {
MapperConfiguration mapperConfiguration = method.getMapperConfiguration();
BeanMapping beanMapping = method.getMappingOptions().getBeanMapping();
// null value check strategy (determine true value based on hierarchy)
NullValueCheckStrategyPrism nvcsBean = beanMapping != null ? beanMapping.getNullValueCheckStrategy() : null;
this.nvcs = mapperConfiguration.getNullValueCheckStrategy( nvcsBean, nvcs );
// null value mapping strategy
this.nvms = mapperConfiguration.getNullValueMappingStrategy();
// null value property mapping strategy (determine true value based on hierarchy)
NullValuePropertyMappingStrategyPrism nvpmsBean =
beanMapping != null ? beanMapping.getNullValuePropertyMappingStrategy() : null;
this.nvpms = mapperConfiguration.getNullValuePropertyMappingStrategy( nvpmsBean, nvpms );
// handle source // handle source
this.rightHandSide = getSourceRHS( sourceReference ); this.rightHandSide = getSourceRHS( sourceReference );
rightHandSide.setUseElementAsSourceTypeForMatching( rightHandSide.setUseElementAsSourceTypeForMatching(
@ -425,25 +448,22 @@ public class PropertyMapping extends ModelElement {
); );
} }
boolean mapNullToDefault = method.getMapperConfiguration().
getNullValueMappingStrategy() == NullValueMappingStrategyPrism.RETURN_DEFAULT;
Assignment factory = ObjectFactoryMethodResolver Assignment factory = ObjectFactoryMethodResolver
.getFactoryMethod( method, targetType, SelectionParameters.forSourceRHS( rightHandSide ), ctx ); .getFactoryMethod( method, targetType, SelectionParameters.forSourceRHS( rightHandSide ), ctx );
return new UpdateWrapper( rhs, method.getThrownTypes(), factory, isFieldAssignment(), targetType, return new UpdateWrapper(
!rhs.isSourceReferenceParameter(), mapNullToDefault ); rhs,
method.getThrownTypes(),
factory, isFieldAssignment(),
targetType,
!rhs.isSourceReferenceParameter(),
nvpms
);
} }
else { else {
return new SetterWrapper( rhs, method.getThrownTypes(), getNvcs(), isFieldAssignment(), targetType ); return new SetterWrapper( rhs, method.getThrownTypes(), nvcs, 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) { private Assignment assignToPlainViaAdder( Assignment rightHandSide) {
Assignment result = rightHandSide; Assignment result = rightHandSide;
@ -473,7 +493,8 @@ public class PropertyMapping extends ModelElement {
.targetAccessorType( targetAccessorType ) .targetAccessorType( targetAccessorType )
.rightHandSide( rightHandSide ) .rightHandSide( rightHandSide )
.assignment( rhs ) .assignment( rhs )
.nullValueCheckStrategy( getNvcs() ) .nullValueCheckStrategy( nvcs )
.nullValuePropertyMappingStrategy( nvpms )
.build(); .build();
} }
@ -831,14 +852,17 @@ public class PropertyMapping extends ModelElement {
); );
} }
boolean mapNullToDefault = method.getMapperConfiguration().
getNullValueMappingStrategy() == NullValueMappingStrategyPrism.RETURN_DEFAULT;
Assignment factoryMethod = Assignment factoryMethod =
ObjectFactoryMethodResolver.getFactoryMethod( method, targetType, null, ctx ); ObjectFactoryMethodResolver.getFactoryMethod( method, targetType, null, ctx );
assignment = new UpdateWrapper( assignment, method.getThrownTypes(), factoryMethod, assignment = new UpdateWrapper(
isFieldAssignment(), targetType, false, mapNullToDefault ); assignment,
method.getThrownTypes(),
factoryMethod,
isFieldAssignment(),
targetType,
false,
null );
} }
else { else {
assignment = new SetterWrapper( assignment, method.getThrownTypes(), isFieldAssignment() ); assignment = new SetterWrapper( assignment, method.getThrownTypes(), isFieldAssignment() );

View File

@ -6,13 +6,18 @@
package org.mapstruct.ap.internal.model.assignment; package org.mapstruct.ap.internal.model.assignment;
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS; import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS;
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.IGNORE;
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.SET_TO_DEFAULT;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.common.Assignment; import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
/** /**
* This wrapper handles the situation where an assignment is done for an update method. * This wrapper handles the situation where an assignment is done for an update method.
@ -29,28 +34,45 @@ import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
public class ExistingInstanceSetterWrapperForCollectionsAndMaps public class ExistingInstanceSetterWrapperForCollectionsAndMaps
extends SetterWrapperForCollectionsAndMapsWithNullCheck { extends SetterWrapperForCollectionsAndMapsWithNullCheck {
private final boolean includeSourceNullCheck; private final boolean includeElseBranch;
private final boolean mapNullToDefault;
private final Type targetType;
public ExistingInstanceSetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment, public ExistingInstanceSetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
List<Type> thrownTypesToExclude, List<Type> thrownTypesToExclude,
Type targetType, Type targetType,
NullValueCheckStrategyPrism nvms, NullValueCheckStrategyPrism nvcs,
NullValuePropertyMappingStrategyPrism nvpms,
TypeFactory typeFactory, TypeFactory typeFactory,
boolean fieldAssignment, boolean fieldAssignment) {
boolean mapNullToDefault) {
super( super(
decoratedAssignment, decoratedAssignment,
thrownTypesToExclude, thrownTypesToExclude,
targetType, targetType,
typeFactory, typeFactory,
fieldAssignment, fieldAssignment
mapNullToDefault
); );
this.includeSourceNullCheck = ALWAYS == nvms; this.mapNullToDefault = SET_TO_DEFAULT == nvpms;
this.targetType = targetType;
this.includeElseBranch = ALWAYS != nvcs && IGNORE != nvpms;
} }
public boolean isIncludeSourceNullCheck() { @Override
return includeSourceNullCheck; public Set<Type> getImportTypes() {
Set<Type> imported = new HashSet<Type>( super.getImportTypes() );
if ( isMapNullToDefault() && ( targetType.getImplementationType() != null ) ) {
imported.add( targetType.getImplementationType() );
}
return imported;
} }
public boolean isIncludeElseBranch() {
return includeElseBranch;
}
public boolean isMapNullToDefault() {
return mapNullToDefault;
}
} }

View File

@ -26,14 +26,12 @@ public class SetterWrapperForCollectionsAndMapsWithNullCheck extends WrapperForC
private final Type targetType; private final Type targetType;
private final TypeFactory typeFactory; private final TypeFactory typeFactory;
private final boolean mapNullToDefault;
public SetterWrapperForCollectionsAndMapsWithNullCheck(Assignment decoratedAssignment, public SetterWrapperForCollectionsAndMapsWithNullCheck(Assignment decoratedAssignment,
List<Type> thrownTypesToExclude, List<Type> thrownTypesToExclude,
Type targetType, Type targetType,
TypeFactory typeFactory, TypeFactory typeFactory,
boolean fieldAssignment, boolean fieldAssignment) {
boolean mapNullToDefault) {
super( super(
decoratedAssignment, decoratedAssignment,
thrownTypesToExclude, thrownTypesToExclude,
@ -42,7 +40,6 @@ public class SetterWrapperForCollectionsAndMapsWithNullCheck extends WrapperForC
); );
this.targetType = targetType; this.targetType = targetType;
this.typeFactory = typeFactory; this.typeFactory = typeFactory;
this.mapNullToDefault = mapNullToDefault;
} }
@Override @Override
@ -63,9 +60,6 @@ public class SetterWrapperForCollectionsAndMapsWithNullCheck extends WrapperForC
if (isDirectAssignment() || getSourcePresenceCheckerReference() == null ) { if (isDirectAssignment() || getSourcePresenceCheckerReference() == null ) {
imported.addAll( getNullCheckLocalVarType().getImportTypes() ); imported.addAll( getNullCheckLocalVarType().getImportTypes() );
} }
if ( isMapNullToDefault() && ( targetType.getImplementationType() != null ) ) {
imported.add( targetType.getImplementationType() );
}
return imported; return imported;
} }
@ -77,8 +71,4 @@ public class SetterWrapperForCollectionsAndMapsWithNullCheck extends WrapperForC
return "java.util.EnumSet".equals( targetType.getFullyQualifiedName() ); return "java.util.EnumSet".equals( targetType.getFullyQualifiedName() );
} }
public boolean isMapNullToDefault() {
return mapNullToDefault;
}
} }

View File

@ -12,6 +12,10 @@ import java.util.Set;
import org.mapstruct.ap.internal.model.common.Assignment; import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.SET_TO_DEFAULT;
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.SET_TO_NULL;
/** /**
* Wraps the assignment in a target setter. * Wraps the assignment in a target setter.
@ -24,6 +28,7 @@ public class UpdateWrapper extends AssignmentWrapper {
private final Assignment factoryMethod; private final Assignment factoryMethod;
private final Type targetImplementationType; private final Type targetImplementationType;
private final boolean includeSourceNullCheck; private final boolean includeSourceNullCheck;
private final boolean includeExplicitNullWhenSourceIsNull;
private final boolean mapNullToDefault; private final boolean mapNullToDefault;
public UpdateWrapper( Assignment decoratedAssignment, public UpdateWrapper( Assignment decoratedAssignment,
@ -32,13 +37,14 @@ public class UpdateWrapper extends AssignmentWrapper {
boolean fieldAssignment, boolean fieldAssignment,
Type targetType, Type targetType,
boolean includeSourceNullCheck, boolean includeSourceNullCheck,
boolean mapNullToDefault ) { NullValuePropertyMappingStrategyPrism nvpms) {
super( decoratedAssignment, fieldAssignment ); super( decoratedAssignment, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude; this.thrownTypesToExclude = thrownTypesToExclude;
this.factoryMethod = factoryMethod; this.factoryMethod = factoryMethod;
this.targetImplementationType = determineImplType( factoryMethod, targetType ); this.targetImplementationType = determineImplType( factoryMethod, targetType );
this.includeSourceNullCheck = includeSourceNullCheck; this.includeSourceNullCheck = includeSourceNullCheck;
this.mapNullToDefault = mapNullToDefault; this.mapNullToDefault = nvpms == SET_TO_DEFAULT;
this.includeExplicitNullWhenSourceIsNull = nvpms == SET_TO_NULL;
} }
private static Type determineImplType(Assignment factoryMethod, Type targetType) { private static Type determineImplType(Assignment factoryMethod, Type targetType) {
@ -91,6 +97,10 @@ public class UpdateWrapper extends AssignmentWrapper {
return includeSourceNullCheck; return includeSourceNullCheck;
} }
public boolean isIncludeExplicitNullWhenSourceIsNull() {
return includeExplicitNullWhenSourceIsNull;
}
public boolean isMapNullToDefault() { public boolean isMapNullToDefault() {
return mapNullToDefault; return mapNullToDefault;
} }

View File

@ -15,6 +15,7 @@ import org.mapstruct.ap.internal.prism.BeanMappingPrism;
import org.mapstruct.ap.internal.prism.BuilderPrism; import org.mapstruct.ap.internal.prism.BuilderPrism;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.ReportingPolicyPrism; import org.mapstruct.ap.internal.prism.ReportingPolicyPrism;
import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
@ -33,6 +34,7 @@ public class BeanMapping {
private final boolean ignoreByDefault; private final boolean ignoreByDefault;
private final List<String> ignoreUnmappedSourceProperties; private final List<String> ignoreUnmappedSourceProperties;
private final BuilderPrism builder; private final BuilderPrism builder;
private final NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy;
/** /**
* creates a mapping for inheritance. Will set ignoreByDefault to false. * creates a mapping for inheritance. Will set ignoreByDefault to false.
@ -44,6 +46,7 @@ public class BeanMapping {
return new BeanMapping( return new BeanMapping(
map.selectionParameters, map.selectionParameters,
map.nullValueMappingStrategy, map.nullValueMappingStrategy,
map.nullValuePropertyMappingStrategy,
map.nullValueCheckStrategy, map.nullValueCheckStrategy,
map.reportingPolicy, map.reportingPolicy,
false, false,
@ -66,6 +69,11 @@ public class BeanMapping {
? null ? null
: NullValueMappingStrategyPrism.valueOf( beanMapping.nullValueMappingStrategy() ); : NullValueMappingStrategyPrism.valueOf( beanMapping.nullValueMappingStrategy() );
NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy =
null == beanMapping.values.nullValuePropertyMappingStrategy()
? null
: NullValuePropertyMappingStrategyPrism.valueOf( beanMapping.nullValuePropertyMappingStrategy() );
NullValueCheckStrategyPrism nullValueCheckStrategy = NullValueCheckStrategyPrism nullValueCheckStrategy =
null == beanMapping.values.nullValueCheckStrategy() null == beanMapping.values.nullValueCheckStrategy()
? null ? null
@ -79,8 +87,8 @@ public class BeanMapping {
if ( !resultTypeIsDefined && beanMapping.qualifiedBy().isEmpty() && beanMapping.qualifiedByName().isEmpty() if ( !resultTypeIsDefined && beanMapping.qualifiedBy().isEmpty() && beanMapping.qualifiedByName().isEmpty()
&& beanMapping.ignoreUnmappedSourceProperties().isEmpty() && beanMapping.ignoreUnmappedSourceProperties().isEmpty()
&& ( nullValueMappingStrategy == null ) && ( nullValueCheckStrategy == null ) && !ignoreByDefault && ( nullValueMappingStrategy == null ) && ( nullValuePropertyMappingStrategy == null )
&& builderMapping == null ) { && ( nullValueCheckStrategy == null ) && !ignoreByDefault && builderMapping == null ) {
messager.printMessage( method, Message.BEANMAPPING_NO_ELEMENTS ); messager.printMessage( method, Message.BEANMAPPING_NO_ELEMENTS );
} }
@ -96,6 +104,7 @@ public class BeanMapping {
return new BeanMapping( return new BeanMapping(
cmp, cmp,
nullValueMappingStrategy, nullValueMappingStrategy,
nullValuePropertyMappingStrategy,
nullValueCheckStrategy, nullValueCheckStrategy,
null, null,
ignoreByDefault, ignoreByDefault,
@ -115,6 +124,7 @@ public class BeanMapping {
null, null,
null, null,
null, null,
null,
ReportingPolicyPrism.IGNORE, ReportingPolicyPrism.IGNORE,
false, false,
Collections.<String>emptyList(), Collections.<String>emptyList(),
@ -123,11 +133,12 @@ public class BeanMapping {
} }
private BeanMapping(SelectionParameters selectionParameters, NullValueMappingStrategyPrism nvms, private BeanMapping(SelectionParameters selectionParameters, NullValueMappingStrategyPrism nvms,
NullValueCheckStrategyPrism nvcs, NullValuePropertyMappingStrategyPrism nvpms, NullValueCheckStrategyPrism nvcs,
ReportingPolicyPrism reportingPolicy, boolean ignoreByDefault, ReportingPolicyPrism reportingPolicy, boolean ignoreByDefault,
List<String> ignoreUnmappedSourceProperties, BuilderPrism builder) { List<String> ignoreUnmappedSourceProperties, BuilderPrism builder) {
this.selectionParameters = selectionParameters; this.selectionParameters = selectionParameters;
this.nullValueMappingStrategy = nvms; this.nullValueMappingStrategy = nvms;
this.nullValuePropertyMappingStrategy = nvpms;
this.nullValueCheckStrategy = nvcs; this.nullValueCheckStrategy = nvcs;
this.reportingPolicy = reportingPolicy; this.reportingPolicy = reportingPolicy;
this.ignoreByDefault = ignoreByDefault; this.ignoreByDefault = ignoreByDefault;
@ -143,6 +154,10 @@ public class BeanMapping {
return nullValueMappingStrategy; return nullValueMappingStrategy;
} }
public NullValuePropertyMappingStrategyPrism getNullValuePropertyMappingStrategy() {
return nullValuePropertyMappingStrategy;
}
public NullValueCheckStrategyPrism getNullValueCheckStrategy() { public NullValueCheckStrategyPrism getNullValueCheckStrategy() {
return nullValueCheckStrategy; return nullValueCheckStrategy;
} }

View File

@ -27,6 +27,7 @@ import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.MappingPrism; import org.mapstruct.ap.internal.prism.MappingPrism;
import org.mapstruct.ap.internal.prism.MappingsPrism; import org.mapstruct.ap.internal.prism.MappingsPrism;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils; import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
@ -58,6 +59,7 @@ public class Mapping {
private final AnnotationValue targetAnnotationValue; private final AnnotationValue targetAnnotationValue;
private final AnnotationValue dependsOnAnnotationValue; private final AnnotationValue dependsOnAnnotationValue;
private final NullValueCheckStrategyPrism nullValueCheckStrategy; private final NullValueCheckStrategyPrism nullValueCheckStrategy;
private final NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy;
private SourceReference sourceReference; private SourceReference sourceReference;
private TargetReference targetReference; private TargetReference targetReference;
@ -89,70 +91,7 @@ public class Mapping {
public static Mapping fromMappingPrism(MappingPrism mappingPrism, ExecutableElement element, public static Mapping fromMappingPrism(MappingPrism mappingPrism, ExecutableElement element,
FormattingMessager messager, Types typeUtils) { FormattingMessager messager, Types typeUtils) {
if ( mappingPrism.target().isEmpty() ) { if (!isConsistent( mappingPrism, element, messager ) ) {
messager.printMessage(
element,
mappingPrism.mirror,
mappingPrism.values.target(),
Message.PROPERTYMAPPING_EMPTY_TARGET
);
return null;
}
if ( !mappingPrism.source().isEmpty() && mappingPrism.values.constant() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_SOURCE_AND_CONSTANT_BOTH_DEFINED );
return null;
}
else if ( !mappingPrism.source().isEmpty() && mappingPrism.values.expression() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_SOURCE_AND_EXPRESSION_BOTH_DEFINED );
return null;
}
else if ( mappingPrism.values.expression() != null && mappingPrism.values.constant() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_EXPRESSION_AND_CONSTANT_BOTH_DEFINED );
return null;
}
else if ( mappingPrism.values.expression() != null && mappingPrism.values.defaultValue() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_EXPRESSION_AND_DEFAULT_VALUE_BOTH_DEFINED );
return null;
}
else if ( mappingPrism.values.constant() != null && mappingPrism.values.defaultValue() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_CONSTANT_AND_DEFAULT_VALUE_BOTH_DEFINED );
return null;
}
else if ( mappingPrism.values.expression() != null && mappingPrism.values.defaultExpression() != null) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_EXPRESSION_AND_DEFAULT_EXPRESSION_BOTH_DEFINED );
return null;
}
else if ( mappingPrism.values.constant() != null && mappingPrism.values.defaultExpression() != null) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_CONSTANT_AND_DEFAULT_EXPRESSION_BOTH_DEFINED );
return null;
}
else if ( mappingPrism.values.defaultValue() != null && mappingPrism.values.defaultExpression() != null) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_DEFAULT_VALUE_AND_DEFAULT_EXPRESSION_BOTH_DEFINED );
return null; return null;
} }
@ -168,7 +107,6 @@ public class Mapping {
List<String> dependsOn = List<String> dependsOn =
mappingPrism.dependsOn() != null ? mappingPrism.dependsOn() : Collections.<String>emptyList(); mappingPrism.dependsOn() != null ? mappingPrism.dependsOn() : Collections.<String>emptyList();
FormattingParameters formattingParam = new FormattingParameters( FormattingParameters formattingParam = new FormattingParameters(
dateFormat, dateFormat,
numberFormat, numberFormat,
@ -188,6 +126,11 @@ public class Mapping {
? null ? null
: NullValueCheckStrategyPrism.valueOf( mappingPrism.nullValueCheckStrategy() ); : NullValueCheckStrategyPrism.valueOf( mappingPrism.nullValueCheckStrategy() );
NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy =
null == mappingPrism.values.nullValuePropertyMappingStrategy()
? null
: NullValuePropertyMappingStrategyPrism.valueOf( mappingPrism.nullValuePropertyMappingStrategy() );
return new Mapping( return new Mapping(
source, source,
constant, constant,
@ -203,7 +146,8 @@ public class Mapping {
selectionParams, selectionParams,
mappingPrism.values.dependsOn(), mappingPrism.values.dependsOn(),
dependsOn, dependsOn,
nullValueCheckStrategy nullValueCheckStrategy,
nullValuePropertyMappingStrategy
); );
} }
@ -223,17 +167,144 @@ public class Mapping {
null, null,
null, null,
new ArrayList(), new ArrayList(),
null,
null null
); );
} }
private static boolean isConsistent(MappingPrism mappingPrism, ExecutableElement element,
FormattingMessager messager) {
if ( mappingPrism.target().isEmpty() ) {
messager.printMessage(
element,
mappingPrism.mirror,
mappingPrism.values.target(),
Message.PROPERTYMAPPING_EMPTY_TARGET
);
return false;
}
if ( !mappingPrism.source().isEmpty() && mappingPrism.values.constant() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_SOURCE_AND_CONSTANT_BOTH_DEFINED
);
return false;
}
else if ( !mappingPrism.source().isEmpty() && mappingPrism.values.expression() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_SOURCE_AND_EXPRESSION_BOTH_DEFINED
);
return false;
}
else if ( mappingPrism.values.expression() != null && mappingPrism.values.constant() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_EXPRESSION_AND_CONSTANT_BOTH_DEFINED
);
return false;
}
else if ( mappingPrism.values.expression() != null && mappingPrism.values.defaultValue() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_EXPRESSION_AND_DEFAULT_VALUE_BOTH_DEFINED
);
return false;
}
else if ( mappingPrism.values.constant() != null && mappingPrism.values.defaultValue() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_CONSTANT_AND_DEFAULT_VALUE_BOTH_DEFINED
);
return false;
}
else if ( mappingPrism.values.expression() != null && mappingPrism.values.defaultExpression() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_EXPRESSION_AND_DEFAULT_EXPRESSION_BOTH_DEFINED
);
return false;
}
else if ( mappingPrism.values.constant() != null && mappingPrism.values.defaultExpression() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_CONSTANT_AND_DEFAULT_EXPRESSION_BOTH_DEFINED
);
return false;
}
else if ( mappingPrism.values.defaultValue() != null && mappingPrism.values.defaultExpression() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_DEFAULT_VALUE_AND_DEFAULT_EXPRESSION_BOTH_DEFINED
);
return false;
}
else if ( mappingPrism.values.nullValuePropertyMappingStrategy() != null
&& mappingPrism.values.defaultValue() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_DEFAULT_VALUE_AND_NVPMS
);
return false;
}
else if ( mappingPrism.values.nullValuePropertyMappingStrategy() != null
&& mappingPrism.values.constant() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_CONSTANT_VALUE_AND_NVPMS
);
return false;
}
else if ( mappingPrism.values.nullValuePropertyMappingStrategy() != null
&& mappingPrism.values.expression() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_EXPRESSION_VALUE_AND_NVPMS
);
return false;
}
else if ( mappingPrism.values.nullValuePropertyMappingStrategy() != null
&& mappingPrism.values.defaultExpression() != null ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_DEFAULT_EXPERSSION_AND_NVPMS
);
return false;
}
else if ( mappingPrism.values.nullValuePropertyMappingStrategy() != null
&& mappingPrism.ignore() != null && mappingPrism.ignore() ) {
messager.printMessage(
element,
mappingPrism.mirror,
Message.PROPERTYMAPPING_IGNORE_AND_NVPMS
);
return false;
}
return true;
}
@SuppressWarnings("checkstyle:parameternumber") @SuppressWarnings("checkstyle:parameternumber")
private Mapping( String sourceName, String constant, String javaExpression, String defaultJavaExpression, private Mapping( String sourceName, String constant, String javaExpression, String defaultJavaExpression,
String targetName, String defaultValue, boolean isIgnored, AnnotationMirror mirror, String targetName, String defaultValue, boolean isIgnored, AnnotationMirror mirror,
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue, AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
FormattingParameters formattingParameters, SelectionParameters selectionParameters, FormattingParameters formattingParameters, SelectionParameters selectionParameters,
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn, AnnotationValue dependsOnAnnotationValue, List<String> dependsOn,
NullValueCheckStrategyPrism nullValueCheckStrategy ) { NullValueCheckStrategyPrism nullValueCheckStrategy,
NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy ) {
this.sourceName = sourceName; this.sourceName = sourceName;
this.constant = constant; this.constant = constant;
this.javaExpression = javaExpression; this.javaExpression = javaExpression;
@ -249,6 +320,7 @@ public class Mapping {
this.dependsOnAnnotationValue = dependsOnAnnotationValue; this.dependsOnAnnotationValue = dependsOnAnnotationValue;
this.dependsOn = dependsOn; this.dependsOn = dependsOn;
this.nullValueCheckStrategy = nullValueCheckStrategy; this.nullValueCheckStrategy = nullValueCheckStrategy;
this.nullValuePropertyMappingStrategy = nullValuePropertyMappingStrategy;
} }
private Mapping( Mapping mapping, TargetReference targetReference ) { private Mapping( Mapping mapping, TargetReference targetReference ) {
@ -269,6 +341,7 @@ public class Mapping {
this.sourceReference = mapping.sourceReference; this.sourceReference = mapping.sourceReference;
this.targetReference = targetReference; this.targetReference = targetReference;
this.nullValueCheckStrategy = mapping.nullValueCheckStrategy; this.nullValueCheckStrategy = mapping.nullValueCheckStrategy;
this.nullValuePropertyMappingStrategy = mapping.nullValuePropertyMappingStrategy;
} }
private Mapping( Mapping mapping, SourceReference sourceReference ) { private Mapping( Mapping mapping, SourceReference sourceReference ) {
@ -289,6 +362,7 @@ public class Mapping {
this.sourceReference = sourceReference; this.sourceReference = sourceReference;
this.targetReference = mapping.targetReference; this.targetReference = mapping.targetReference;
this.nullValueCheckStrategy = mapping.nullValueCheckStrategy; this.nullValueCheckStrategy = mapping.nullValueCheckStrategy;
this.nullValuePropertyMappingStrategy = mapping.nullValuePropertyMappingStrategy;
} }
private static String getExpression(MappingPrism mappingPrism, ExecutableElement element, private static String getExpression(MappingPrism mappingPrism, ExecutableElement element,
@ -458,6 +532,10 @@ public class Mapping {
return nullValueCheckStrategy; return nullValueCheckStrategy;
} }
public NullValuePropertyMappingStrategyPrism getNullValuePropertyMappingStrategy() {
return nullValuePropertyMappingStrategy;
}
public Mapping popTargetReference() { public Mapping popTargetReference() {
if ( targetReference != null ) { if ( targetReference != null ) {
TargetReference newTargetReference = targetReference.pop(); TargetReference newTargetReference = targetReference.pop();
@ -506,7 +584,8 @@ public class Mapping {
selectionParameters, selectionParameters,
dependsOnAnnotationValue, dependsOnAnnotationValue,
Collections.<String>emptyList(), Collections.<String>emptyList(),
nullValueCheckStrategy nullValueCheckStrategy,
nullValuePropertyMappingStrategy
); );
reverse.init( reverse.init(
@ -548,7 +627,8 @@ public class Mapping {
selectionParameters, selectionParameters,
dependsOnAnnotationValue, dependsOnAnnotationValue,
dependsOn, dependsOn,
nullValueCheckStrategy nullValueCheckStrategy,
nullValuePropertyMappingStrategy
); );
if ( sourceReference != null ) { if ( sourceReference != null ) {
@ -568,5 +648,6 @@ public class Mapping {
"\n targetName='" + targetName + "\'," + "\n targetName='" + targetName + "\'," +
"\n}"; "\n}";
} }
} }

View File

@ -20,5 +20,4 @@ public final class MappingConstantsPrism {
public static final String ANY_REMAINING = "<ANY_REMAINING>"; public static final String ANY_REMAINING = "<ANY_REMAINING>";
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>"; public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";
} }

View File

@ -0,0 +1,19 @@
/*
* 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.internal.prism;
/**
* Prism for the enum {@link org.mapstruct.NullValuePropertyMappingStrategy}
*
* @author Sjaak Derksen
*/
public enum NullValuePropertyMappingStrategyPrism {
SET_TO_NULL,
SET_TO_DEFAULT,
IGNORE;
}

View File

@ -22,6 +22,7 @@ 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.NullValueCheckStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.ReportingPolicyPrism; import org.mapstruct.ap.internal.prism.ReportingPolicyPrism;
/** /**
@ -163,6 +164,25 @@ public class MapperConfiguration {
} }
} }
public NullValuePropertyMappingStrategyPrism getNullValuePropertyMappingStrategy(
NullValuePropertyMappingStrategyPrism beanPrism,
NullValuePropertyMappingStrategyPrism mappingPrism) {
if ( mappingPrism != null ) {
return mappingPrism;
}
else if ( beanPrism != null ) {
return beanPrism;
}
else if ( mapperConfigPrism != null && mapperPrism.values.nullValueCheckStrategy() == null ) {
return NullValuePropertyMappingStrategyPrism.valueOf(
mapperConfigPrism.nullValuePropertyMappingStrategy()
);
}
else {
return NullValuePropertyMappingStrategyPrism.valueOf( mapperPrism.nullValuePropertyMappingStrategy() );
}
}
public InjectionStrategyPrism getInjectionStrategy() { public InjectionStrategyPrism getInjectionStrategy() {
if ( mapperConfigPrism != null && mapperPrism.values.injectionStrategy() == null ) { if ( mapperConfigPrism != null && mapperPrism.values.injectionStrategy() == null ) {
return InjectionStrategyPrism.valueOf( mapperConfigPrism.injectionStrategy() ); return InjectionStrategyPrism.valueOf( mapperConfigPrism.injectionStrategy() );

View File

@ -15,7 +15,7 @@ import javax.tools.Diagnostic;
public enum Message { public enum Message {
// CHECKSTYLE:OFF // CHECKSTYLE:OFF
BEANMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'resultType' and 'qualifiedBy' are undefined in @BeanMapping, define at least one of them." ), BEANMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy', 'nullValuePropertyMappingStrategy', 'resultType' and 'qualifiedBy' are undefined in @BeanMapping, define at least one of them." ),
BEANMAPPING_NOT_ASSIGNABLE( "%s not assignable to: %s." ), BEANMAPPING_NOT_ASSIGNABLE( "%s not assignable to: %s." ),
BEANMAPPING_ABSTRACT( "The result type %s may not be an abstract class nor interface." ), BEANMAPPING_ABSTRACT( "The result type %s may not be an abstract class nor interface." ),
BEANMAPPING_UNKNOWN_PROPERTY_IN_RESULTTYPE( "Unknown property \"%s\" in result type %s. Did you mean \"%s\"?" ), BEANMAPPING_UNKNOWN_PROPERTY_IN_RESULTTYPE( "Unknown property \"%s\" in result type %s. Did you mean \"%s\"?" ),
@ -44,6 +44,11 @@ public enum Message {
PROPERTYMAPPING_EXPRESSION_AND_DEFAULT_EXPRESSION_BOTH_DEFINED( "Expression and default expression are both defined in @Mapping, either define an expression or a default expression." ), PROPERTYMAPPING_EXPRESSION_AND_DEFAULT_EXPRESSION_BOTH_DEFINED( "Expression and default expression are both defined in @Mapping, either define an expression or a default expression." ),
PROPERTYMAPPING_CONSTANT_AND_DEFAULT_EXPRESSION_BOTH_DEFINED( "Constant and default expression are both defined in @Mapping, either define a constant or a default expression." ), PROPERTYMAPPING_CONSTANT_AND_DEFAULT_EXPRESSION_BOTH_DEFINED( "Constant and default expression are both defined in @Mapping, either define a constant or a default expression." ),
PROPERTYMAPPING_DEFAULT_VALUE_AND_DEFAULT_EXPRESSION_BOTH_DEFINED( "Default value and default expression are both defined in @Mapping, either define a default value or a default expression." ), PROPERTYMAPPING_DEFAULT_VALUE_AND_DEFAULT_EXPRESSION_BOTH_DEFINED( "Default value and default expression are both defined in @Mapping, either define a default value or a default expression." ),
PROPERTYMAPPING_DEFAULT_VALUE_AND_NVPMS( "Default value and nullValuePropertyMappingStrategy are both defined in @Mapping, either define a defaultValue or an nullValuePropertyMappingStrategy." ),
PROPERTYMAPPING_EXPRESSION_VALUE_AND_NVPMS( "Expression and nullValuePropertyMappingStrategy are both defined in @Mapping, either define an expression or an nullValuePropertyMappingStrategy." ),
PROPERTYMAPPING_CONSTANT_VALUE_AND_NVPMS( "Constant and nullValuePropertyMappingStrategy are both defined in @Mapping, either define a constant or an nullValuePropertyMappingStrategy." ),
PROPERTYMAPPING_DEFAULT_EXPERSSION_AND_NVPMS( "DefaultExpression and nullValuePropertyMappingStrategy are both defined in @Mapping, either define a defaultExpression or an nullValuePropertyMappingStrategy." ),
PROPERTYMAPPING_IGNORE_AND_NVPMS( "Ignore and nullValuePropertyMappingStrategy are both defined in @Mapping, either define ignore or an nullValuePropertyMappingStrategy." ),
PROPERTYMAPPING_INVALID_EXPRESSION( "Value for expression must be given in the form \"java(<EXPRESSION>)\"." ), PROPERTYMAPPING_INVALID_EXPRESSION( "Value for expression must be given in the form \"java(<EXPRESSION>)\"." ),
PROPERTYMAPPING_INVALID_DEFAULT_EXPRESSION( "Value for default expression must be given in the form \"java(<EXPRESSION>)\"." ), PROPERTYMAPPING_INVALID_DEFAULT_EXPRESSION( "Value for default expression must be given in the form \"java(<EXPRESSION>)\"." ),
PROPERTYMAPPING_INVALID_PARAMETER_NAME( "Method has no source parameter named \"%s\". Method source parameters are: \"%s\"." ), PROPERTYMAPPING_INVALID_PARAMETER_NAME( "Method has no source parameter named \"%s\". Method source parameters are: \"%s\"." ),

View File

@ -14,7 +14,7 @@
${ext.targetBeanName}.${ext.targetReadAccessorName}.clear(); ${ext.targetBeanName}.${ext.targetReadAccessorName}.clear();
${ext.targetBeanName}.${ext.targetReadAccessorName}.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( <@lib.handleWithAssignmentOrNullCheckVar/> ); ${ext.targetBeanName}.${ext.targetReadAccessorName}.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( <@lib.handleWithAssignmentOrNullCheckVar/> );
</@lib.handleLocalVarNullCheck> </@lib.handleLocalVarNullCheck>
<#if !ext.defaultValueAssignment?? && !sourcePresenceCheckerReference?? && !includeSourceNullCheck>else {<#-- the opposite (defaultValueAssignment) case is handeld inside lib.handleLocalVarNullCheck --> <#if !ext.defaultValueAssignment?? && !sourcePresenceCheckerReference?? && includeElseBranch>else {<#-- the opposite (defaultValueAssignment) case is handeld inside lib.handleLocalVarNullCheck -->
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if mapNullToDefault><@lib.initTargetObject/><#else>null</#if></@lib.handleWrite>; ${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if mapNullToDefault><@lib.initTargetObject/><#else>null</#if></@lib.handleWrite>;
} }
</#if> </#if>

View File

@ -10,10 +10,6 @@
<@lib.sourceLocalVarAssignment/> <@lib.sourceLocalVarAssignment/>
<@lib.handleExceptions> <@lib.handleExceptions>
<@callTargetWriteAccessor/> <@callTargetWriteAccessor/>
<#if !ext.defaultValueAssignment??>else {<#-- the opposite (defaultValueAssignment) case is handeld inside lib.handleLocalVarNullCheck -->
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if mapNullToDefault><@lib.initTargetObject/><#else>null</#if></@lib.handleWrite>;
}
</#if>
</@lib.handleExceptions> </@lib.handleExceptions>
<#-- <#--
assigns the target via the regular target write accessor (usually the setter) assigns the target via the regular target write accessor (usually the setter)

View File

@ -13,9 +13,11 @@
<@assignToExistingTarget/> <@assignToExistingTarget/>
<@lib.handleAssignment/>; <@lib.handleAssignment/>;
} }
<#if mapNullToDefault || includeExplicitNullWhenSourceIsNull>
else { else {
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if mapNullToDefault><@lib.initTargetObject/><#else>null</#if></@lib.handleWrite>; ${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if mapNullToDefault><@lib.initTargetObject/><#else>null</#if></@lib.handleWrite>;
} }
</#if>
<#else> <#else>
<@assignToExistingTarget/> <@assignToExistingTarget/>
<@lib.handleAssignment/>; <@lib.handleAssignment/>;

View File

@ -5,12 +5,11 @@
*/ */
package org.mapstruct.ap.test.bugs._1273; package org.mapstruct.ap.test.bugs._1273;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Dto { public class Dto {
List<Long> longs = new ArrayList<Long>(); List<Long> longs;
public List<Long> getLongs() { public List<Long> getLongs() {
return longs; return longs;

View File

@ -5,12 +5,20 @@
*/ */
package org.mapstruct.ap.test.bugs._1273; package org.mapstruct.ap.test.bugs._1273;
import org.mapstruct.Mapper; import java.util.ArrayList;
import org.mapstruct.NullValueMappingStrategy;
@Mapper( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT ) import org.mapstruct.Mapper;
import org.mapstruct.ObjectFactory;
@Mapper
public interface EntityMapperReturnDefault { public interface EntityMapperReturnDefault {
Dto asTarget(Entity entity); Dto asTarget(Entity entity);
@ObjectFactory
default Dto createDto() {
Dto result = new Dto();
result.setLongs( new ArrayList<>( ) );
return result;
}
} }

View File

@ -5,12 +5,15 @@
*/ */
package org.mapstruct.ap.test.bugs._913; package org.mapstruct.ap.test.bugs._913;
import org.mapstruct.BeanMapping;
import org.mapstruct.InheritConfiguration; import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget; import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.NullValueCheckStrategy;
import org.mapstruct.ObjectFactory;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -22,6 +25,7 @@ public interface DomainDtoWithNcvsAlwaysMapper {
DomainDtoWithNcvsAlwaysMapper INSTANCE = Mappers.getMapper( DomainDtoWithNcvsAlwaysMapper.class ); DomainDtoWithNcvsAlwaysMapper INSTANCE = Mappers.getMapper( DomainDtoWithNcvsAlwaysMapper.class );
@BeanMapping( qualifiedByName = "DomainObjectFactory" )
@Mappings({ @Mappings({
@Mapping(target = "strings", source = "strings"), @Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"), @Mapping(target = "longs", source = "strings"),
@ -36,4 +40,13 @@ public interface DomainDtoWithNcvsAlwaysMapper {
@InheritConfiguration( name = "create" ) @InheritConfiguration( name = "create" )
Domain updateWithReturn(DtoWithPresenceCheck source, @MappingTarget Domain target); Domain updateWithReturn(DtoWithPresenceCheck source, @MappingTarget Domain target);
@ObjectFactory
@Named( "DomainObjectFactory" )
default Domain createNullDomain() {
Domain domain = new Domain();
domain.setLongs( null );
domain.setStrings( null );
return domain;
}
} }

View File

@ -11,13 +11,17 @@ import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget; import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.NullValueMappingStrategy;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
* *
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
@Mapper( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, uses = Helper.class ) @Mapper(
nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT,
nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT,
uses = Helper.class )
public interface DomainDtoWithNvmsDefaultMapper { public interface DomainDtoWithNvmsDefaultMapper {
DomainDtoWithNvmsDefaultMapper INSTANCE = Mappers.getMapper( DomainDtoWithNvmsDefaultMapper.class ); DomainDtoWithNvmsDefaultMapper INSTANCE = Mappers.getMapper( DomainDtoWithNvmsDefaultMapper.class );

View File

@ -5,11 +5,14 @@
*/ */
package org.mapstruct.ap.test.bugs._913; package org.mapstruct.ap.test.bugs._913;
import org.mapstruct.BeanMapping;
import org.mapstruct.InheritConfiguration; import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget; import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.ObjectFactory;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -22,6 +25,7 @@ public interface DomainDtoWithNvmsNullMapper {
DomainDtoWithNvmsNullMapper INSTANCE = Mappers.getMapper( DomainDtoWithNvmsNullMapper.class ); DomainDtoWithNvmsNullMapper INSTANCE = Mappers.getMapper( DomainDtoWithNvmsNullMapper.class );
@BeanMapping( qualifiedByName = "DomainObjectFactory" )
@Mappings({ @Mappings({
@Mapping(target = "strings", source = "strings"), @Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"), @Mapping(target = "longs", source = "strings"),
@ -36,4 +40,13 @@ public interface DomainDtoWithNvmsNullMapper {
@InheritConfiguration( name = "create" ) @InheritConfiguration( name = "create" )
Domain updateWithReturn(Dto source, @MappingTarget Domain target); Domain updateWithReturn(Dto source, @MappingTarget Domain target);
@ObjectFactory
@Named( "DomainObjectFactory" )
default Domain createNullDomain() {
Domain domain = new Domain();
domain.setLongs( null );
domain.setStrings( null );
return domain;
}
} }

View File

@ -5,11 +5,14 @@
*/ */
package org.mapstruct.ap.test.bugs._913; package org.mapstruct.ap.test.bugs._913;
import org.mapstruct.BeanMapping;
import org.mapstruct.InheritConfiguration; import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget; import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.ObjectFactory;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -22,6 +25,7 @@ public interface DomainDtoWithPresenceCheckMapper {
DomainDtoWithPresenceCheckMapper INSTANCE = Mappers.getMapper( DomainDtoWithPresenceCheckMapper.class ); DomainDtoWithPresenceCheckMapper INSTANCE = Mappers.getMapper( DomainDtoWithPresenceCheckMapper.class );
@BeanMapping( qualifiedByName = "DomainObjectFactory" )
@Mappings({ @Mappings({
@Mapping(target = "strings", source = "strings"), @Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"), @Mapping(target = "longs", source = "strings"),
@ -36,4 +40,13 @@ public interface DomainDtoWithPresenceCheckMapper {
@InheritConfiguration( name = "create" ) @InheritConfiguration( name = "create" )
Domain updateWithReturn(DtoWithPresenceCheck source, @MappingTarget Domain target); Domain updateWithReturn(DtoWithPresenceCheck source, @MappingTarget Domain target);
@ObjectFactory
@Named( "DomainObjectFactory" )
default Domain createNullDomain() {
Domain domain = new Domain();
domain.setLongs( null );
domain.setStrings( null );
return domain;
}
} }

View File

@ -0,0 +1,19 @@
/*
* 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.nullvaluepropertymapping;
public class Address {
private Integer houseNumber;
public Integer getHouseNumber() {
return houseNumber;
}
public void setHouseNumber(Integer houseNumber) {
this.houseNumber = houseNumber;
}
}

View File

@ -0,0 +1,19 @@
/*
* 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.nullvaluepropertymapping;
public class AddressDTO {
private Integer houseNo;
public Integer getHouseNo() {
return houseNo;
}
public void setHouseNo(Integer houseNo) {
this.houseNo = houseNo;
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.nullvaluepropertymapping;
import java.util.List;
public class Customer {
private Address address;
private List<String> details;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public List<String> getDetails() {
return details;
}
public void setDetails(List<String> details) {
this.details = details;
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.nullvaluepropertymapping;
import java.util.List;
public class CustomerDTO {
private AddressDTO address;
private List<String> details;
public AddressDTO getAddress() {
return address;
}
public void setAddress(AddressDTO address) {
this.address = address;
}
public List<String> getDetails() {
return details;
}
public void setDetails(List<String> details) {
this.details = details;
}
}

View File

@ -0,0 +1,26 @@
/*
* 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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
public interface CustomerDefaultMapper {
CustomerDefaultMapper INSTANCE = Mappers.getMapper( CustomerDefaultMapper.class );
@Mapping(source = "address", target = "homeDTO.addressDTO")
void mapCustomer(Customer customer, @MappingTarget UserDTO userDTO);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

View File

@ -0,0 +1,26 @@
/*
* 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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface CustomerMapper {
CustomerMapper INSTANCE = Mappers.getMapper( CustomerMapper.class );
@Mapping(source = "address", target = "homeDTO.addressDTO")
void mapCustomer(Customer customer, @MappingTarget UserDTO userDTO);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

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.nullvaluepropertymapping;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
@Mapper
public interface CustomerNvpmsOnBeanMappingMethodMapper {
CustomerNvpmsOnBeanMappingMethodMapper INSTANCE = Mappers.getMapper( CustomerNvpmsOnBeanMappingMethodMapper.class );
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

View File

@ -0,0 +1,24 @@
/*
* 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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
@Mapper(config = NvpmsConfig.class)
public interface CustomerNvpmsOnConfigMapper {
CustomerNvpmsOnConfigMapper INSTANCE = Mappers.getMapper( CustomerNvpmsOnConfigMapper.class );
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

View File

@ -0,0 +1,24 @@
/*
* 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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface CustomerNvpmsOnMapperMapper {
CustomerNvpmsOnMapperMapper INSTANCE = Mappers.getMapper( CustomerNvpmsOnMapperMapper.class );
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE;
@Mapper
public interface CustomerNvpmsPropertyMappingMapper {
CustomerNvpmsPropertyMappingMapper INSTANCE = Mappers.getMapper( CustomerNvpmsPropertyMappingMapper.class );
@Mapping( target = "address", nullValuePropertyMappingStrategy = IGNORE)
@Mapping( target = "details", nullValuePropertyMappingStrategy = IGNORE)
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE;
@Mapper
public interface ErroneousCustomerMapper1 {
ErroneousCustomerMapper1 INSTANCE = Mappers.getMapper( ErroneousCustomerMapper1.class );
@Mapping(target = "details", defaultValue = "test", nullValuePropertyMappingStrategy = IGNORE)
@Mapping(target = "address", nullValuePropertyMappingStrategy = IGNORE)
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE;
@Mapper
public interface ErroneousCustomerMapper2 {
ErroneousCustomerMapper2 INSTANCE = Mappers.getMapper( ErroneousCustomerMapper2.class );
@Mapping(target = "details", expression = "java(getTest())", nullValuePropertyMappingStrategy = IGNORE)
@Mapping(target = "address", nullValuePropertyMappingStrategy = IGNORE)
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE;
@Mapper
public interface ErroneousCustomerMapper3 {
ErroneousCustomerMapper3 INSTANCE = Mappers.getMapper( ErroneousCustomerMapper3.class );
@Mapping(target = "details", defaultExpression = "java(getTest())", nullValuePropertyMappingStrategy = IGNORE)
@Mapping(target = "address", nullValuePropertyMappingStrategy = IGNORE)
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE;
@Mapper
public interface ErroneousCustomerMapper4 {
ErroneousCustomerMapper4 INSTANCE = Mappers.getMapper( ErroneousCustomerMapper4.class );
@Mapping(target = "details", constant = "test", nullValuePropertyMappingStrategy = IGNORE)
@Mapping(target = "address", nullValuePropertyMappingStrategy = IGNORE)
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

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.nullvaluepropertymapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE;
@Mapper
public interface ErroneousCustomerMapper5 {
ErroneousCustomerMapper5 INSTANCE = Mappers.getMapper( ErroneousCustomerMapper5.class );
@Mapping(target = "details", ignore = true, nullValuePropertyMappingStrategy = IGNORE)
@Mapping(target = "address", nullValuePropertyMappingStrategy = IGNORE)
void map(Customer customer, @MappingTarget CustomerDTO mappingTarget);
@Mapping(source = "houseNumber", target = "houseNo")
void mapCustomerHouse(Address address, @MappingTarget AddressDTO addrDTO);
}

View File

@ -0,0 +1,19 @@
/*
* 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.nullvaluepropertymapping;
public class HomeDTO {
private AddressDTO addressDTO;
public AddressDTO getAddressDTO() {
return addressDTO;
}
public void setAddressDTO(AddressDTO addressDTO) {
this.addressDTO = addressDTO;
}
}

View File

@ -0,0 +1,203 @@
/*
* 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.nullvaluepropertymapping;
import java.util.Arrays;
import java.util.function.BiConsumer;
import org.junit.Ignore;
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.compilation.annotation.CompilationResult;
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Sjaak Derksen
*/
@IssueKey("1306")
@RunWith(AnnotationProcessorTestRunner.class)
@WithClasses({
Address.class,
Customer.class,
CustomerDTO.class,
AddressDTO.class,
HomeDTO.class,
UserDTO.class
})
public class NullValuePropertyMappingTest {
@Test
@WithClasses(CustomerMapper.class)
public void testStrategyAppliedOnForgedMethod() {
Customer customer = new Customer();
customer.setAddress( null );
UserDTO userDTO = new UserDTO();
userDTO.setHomeDTO( new HomeDTO() );
userDTO.getHomeDTO().setAddressDTO( new AddressDTO() );
userDTO.getHomeDTO().getAddressDTO().setHouseNo( 5 );
userDTO.setDetails( Arrays.asList( "green hair" ) );
CustomerMapper.INSTANCE.mapCustomer( customer, userDTO );
assertThat( userDTO.getHomeDTO() ).isNotNull();
assertThat( userDTO.getHomeDTO().getAddressDTO() ).isNotNull();
assertThat( userDTO.getHomeDTO().getAddressDTO().getHouseNo() ).isEqualTo( 5 );
assertThat( userDTO.getDetails() ).isNotNull();
assertThat( userDTO.getDetails() ).containsExactly( "green hair" );
}
@Test
@WithClasses({ NvpmsConfig.class, CustomerNvpmsOnConfigMapper.class })
public void testHierarchyIgnoreOnConfig() {
testConfig( ( Customer s, CustomerDTO t ) -> CustomerNvpmsOnConfigMapper.INSTANCE.map( s, t ) );
}
@Test
@WithClasses(CustomerNvpmsOnMapperMapper.class)
public void testHierarchyIgnoreOnMapping() {
testConfig( ( Customer s, CustomerDTO t ) -> CustomerNvpmsOnMapperMapper.INSTANCE.map( s, t ) );
}
@Test
@WithClasses(CustomerNvpmsOnBeanMappingMethodMapper.class)
public void testHierarchyIgnoreOnBeanMappingMethod() {
testConfig( ( Customer s, CustomerDTO t ) -> CustomerNvpmsOnBeanMappingMethodMapper.INSTANCE.map( s, t ) );
}
@Test
@WithClasses(CustomerNvpmsPropertyMappingMapper.class)
public void testHierarchyIgnoreOnPropertyMappingMehtod() {
testConfig( ( Customer s, CustomerDTO t ) -> CustomerNvpmsPropertyMappingMapper.INSTANCE.map( s, t ) );
}
@Test
@WithClasses(CustomerDefaultMapper.class)
public void testStrategyDefaultAppliedOnForgedMethod() {
Customer customer = new Customer();
customer.setAddress( null );
UserDTO userDTO = new UserDTO();
userDTO.setHomeDTO( new HomeDTO() );
userDTO.getHomeDTO().setAddressDTO( new AddressDTO() );
userDTO.getHomeDTO().getAddressDTO().setHouseNo( 5 );
userDTO.setDetails( Arrays.asList( "green hair" ) );
CustomerDefaultMapper.INSTANCE.mapCustomer( customer, userDTO );
assertThat( userDTO.getHomeDTO() ).isNotNull();
assertThat( userDTO.getHomeDTO().getAddressDTO() ).isNotNull();
assertThat( userDTO.getHomeDTO().getAddressDTO().getHouseNo() ).isNull();
assertThat( userDTO.getDetails() ).isNotNull();
assertThat( userDTO.getDetails() ).isEmpty();
}
@Test
@Ignore // test gives different results for JDK and JDT
@WithClasses(ErroneousCustomerMapper1.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousCustomerMapper1.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 20,
messageRegExp = "Default value and nullValuePropertyMappingStrategy are both defined in @Mapping, " +
"either define a defaultValue or an nullValuePropertyMappingStrategy.")
}
)
public void testBothDefaultValueAndNvpmsDefined() {
}
@Test
@Ignore // test gives different results for JDK and JDT
@WithClasses(ErroneousCustomerMapper2.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousCustomerMapper2.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 20,
messageRegExp = "Expression and nullValuePropertyMappingStrategy are both defined in @Mapping, " +
"either define an expression or an nullValuePropertyMappingStrategy.")
}
)
public void testBothExpressionAndNvpmsDefined() {
}
@Test
@Ignore // test gives different results for JDK and JDT
@WithClasses(ErroneousCustomerMapper3.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousCustomerMapper3.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 20,
messageRegExp = "DefaultExpression and nullValuePropertyMappingStrategy are both defined in " +
"@Mapping, either define a defaultExpression or an nullValuePropertyMappingStrategy.")
}
)
public void testBothDefaultExpressionAndNvpmsDefined() {
}
@Test
@Ignore // test gives different results for JDK and JDT
@WithClasses(ErroneousCustomerMapper4.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousCustomerMapper4.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 20,
messageRegExp = "Constant and nullValuePropertyMappingStrategy are both defined in @Mapping, " +
"either define a constant or an nullValuePropertyMappingStrategy.")
}
)
public void testBothConstantAndNvpmsDefined() {
}
@Test
@Ignore // test gives different results for JDK and JDT
@WithClasses(ErroneousCustomerMapper5.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousCustomerMapper5.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 20,
messageRegExp = "Ignore and nullValuePropertyMappingStrategy are both defined in @Mapping, " +
"either define ignore or an nullValuePropertyMappingStrategy.")
}
)
public void testBothIgnoreAndNvpmsDefined() {
}
private void testConfig(BiConsumer<Customer, CustomerDTO> customerMapper) {
Customer customer = new Customer();
customer.setAddress( null );
CustomerDTO customerDto = new CustomerDTO();
customerDto.setAddress( new AddressDTO() );
customerDto.getAddress().setHouseNo( 5 );
customerDto.setDetails( Arrays.asList( "green hair" ) );
customerMapper.accept( customer, customerDto );
assertThat( customerDto.getAddress() ).isNotNull();
assertThat( customerDto.getAddress().getHouseNo() ).isEqualTo( 5 );
assertThat( customerDto.getDetails() ).isNotNull();
assertThat( customerDto.getDetails() ).containsExactly( "green hair" );
}
}

View File

@ -0,0 +1,13 @@
/*
* 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.nullvaluepropertymapping;
import org.mapstruct.MapperConfig;
import org.mapstruct.NullValuePropertyMappingStrategy;
@MapperConfig( nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE )
public interface NvpmsConfig {
}

View File

@ -0,0 +1,30 @@
/*
* 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.nullvaluepropertymapping;
import java.util.List;
public class UserDTO {
private HomeDTO homeDTO;
private List<String> details;
public HomeDTO getHomeDTO() {
return homeDTO;
}
public void setHomeDTO(HomeDTO homeDTO) {
this.homeDTO = homeDTO;
}
public List<String> getDetails() {
return details;
}
public void setDetails(List<String> details) {
this.details = details;
}
}

View File

@ -174,8 +174,8 @@ public class QualifierTest {
@Diagnostic(type = ErroneousMovieFactoryMapper.class, @Diagnostic(type = ErroneousMovieFactoryMapper.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 24, line = 24,
messageRegExp = "'nullValueMappingStrategy', 'resultType' and 'qualifiedBy' are undefined in " + messageRegExp = "'nullValueMappingStrategy', 'nullValuePropertyMappingStrategy', 'resultType' and " +
"@BeanMapping, define at least one of them."), "'qualifiedBy' are undefined in @BeanMapping, define at least one of them."),
@Diagnostic(type = ErroneousMovieFactoryMapper.class, @Diagnostic(type = ErroneousMovieFactoryMapper.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 24, line = 24,

View File

@ -26,27 +26,18 @@ public class DomainDtoWithNcvsAlwaysMapperImpl implements DomainDtoWithNcvsAlway
return null; return null;
} }
Domain domain = new Domain(); Domain domain = createNullDomain();
if ( source.hasStringsInitialized() ) { if ( source.hasStringsInitialized() ) {
domain.setLongsInitialized( stringListToLongSet( source.getStringsInitialized() ) ); domain.setLongsInitialized( stringListToLongSet( source.getStringsInitialized() ) );
} }
else {
domain.setLongsInitialized( null );
}
if ( source.hasStrings() ) { if ( source.hasStrings() ) {
domain.setLongs( stringListToLongSet( source.getStrings() ) ); domain.setLongs( stringListToLongSet( source.getStrings() ) );
} }
else {
domain.setLongs( null );
}
if ( source.hasStrings() ) { if ( source.hasStrings() ) {
List<String> list = source.getStrings(); List<String> list = source.getStrings();
domain.setStrings( new HashSet<String>( list ) ); domain.setStrings( new HashSet<String>( list ) );
} }
else {
domain.setStrings( null );
}
if ( source.hasStringsWithDefault() ) { if ( source.hasStringsWithDefault() ) {
List<String> list1 = source.getStringsWithDefault(); List<String> list1 = source.getStringsWithDefault();
domain.setStringsWithDefault( new ArrayList<String>( list1 ) ); domain.setStringsWithDefault( new ArrayList<String>( list1 ) );
@ -58,9 +49,6 @@ public class DomainDtoWithNcvsAlwaysMapperImpl implements DomainDtoWithNcvsAlway
List<String> list2 = source.getStringsInitialized(); List<String> list2 = source.getStringsInitialized();
domain.setStringsInitialized( new HashSet<String>( list2 ) ); domain.setStringsInitialized( new HashSet<String>( list2 ) );
} }
else {
domain.setStringsInitialized( null );
}
return domain; return domain;
} }

View File

@ -32,9 +32,6 @@ public class DomainDtoWithNvmsDefaultMapperImpl implements DomainDtoWithNvmsDefa
if ( list != null ) { if ( list != null ) {
domain.setStrings( new HashSet<String>( list ) ); domain.setStrings( new HashSet<String>( list ) );
} }
else {
domain.setStrings( new HashSet<String>() );
}
List<String> list1 = source.getStringsWithDefault(); List<String> list1 = source.getStringsWithDefault();
if ( list1 != null ) { if ( list1 != null ) {
domain.setStringsWithDefault( new ArrayList<String>( list1 ) ); domain.setStringsWithDefault( new ArrayList<String>( list1 ) );
@ -46,9 +43,6 @@ public class DomainDtoWithNvmsDefaultMapperImpl implements DomainDtoWithNvmsDefa
if ( list2 != null ) { if ( list2 != null ) {
domain.setStringsInitialized( new HashSet<String>( list2 ) ); domain.setStringsInitialized( new HashSet<String>( list2 ) );
} }
else {
domain.setStringsInitialized( new HashSet<String>() );
}
} }
return domain; return domain;

View File

@ -26,7 +26,7 @@ public class DomainDtoWithNvmsNullMapperImpl implements DomainDtoWithNvmsNullMap
return null; return null;
} }
Domain domain = new Domain(); Domain domain = createNullDomain();
domain.setLongsInitialized( stringListToLongSet( source.getStringsInitialized() ) ); domain.setLongsInitialized( stringListToLongSet( source.getStringsInitialized() ) );
domain.setLongs( stringListToLongSet( source.getStrings() ) ); domain.setLongs( stringListToLongSet( source.getStrings() ) );
@ -34,9 +34,6 @@ public class DomainDtoWithNvmsNullMapperImpl implements DomainDtoWithNvmsNullMap
if ( list != null ) { if ( list != null ) {
domain.setStrings( new HashSet<String>( list ) ); domain.setStrings( new HashSet<String>( list ) );
} }
else {
domain.setStrings( null );
}
List<String> list1 = source.getStringsWithDefault(); List<String> list1 = source.getStringsWithDefault();
if ( list1 != null ) { if ( list1 != null ) {
domain.setStringsWithDefault( new ArrayList<String>( list1 ) ); domain.setStringsWithDefault( new ArrayList<String>( list1 ) );
@ -48,9 +45,6 @@ public class DomainDtoWithNvmsNullMapperImpl implements DomainDtoWithNvmsNullMap
if ( list2 != null ) { if ( list2 != null ) {
domain.setStringsInitialized( new HashSet<String>( list2 ) ); domain.setStringsInitialized( new HashSet<String>( list2 ) );
} }
else {
domain.setStringsInitialized( null );
}
return domain; return domain;
} }

View File

@ -26,7 +26,7 @@ public class DomainDtoWithPresenceCheckMapperImpl implements DomainDtoWithPresen
return null; return null;
} }
Domain domain = new Domain(); Domain domain = createNullDomain();
domain.setLongsInitialized( stringListToLongSet( source.getStringsInitialized() ) ); domain.setLongsInitialized( stringListToLongSet( source.getStringsInitialized() ) );
domain.setLongs( stringListToLongSet( source.getStrings() ) ); domain.setLongs( stringListToLongSet( source.getStrings() ) );
@ -34,9 +34,6 @@ public class DomainDtoWithPresenceCheckMapperImpl implements DomainDtoWithPresen
List<String> list = source.getStrings(); List<String> list = source.getStrings();
domain.setStrings( new HashSet<String>( list ) ); domain.setStrings( new HashSet<String>( list ) );
} }
else {
domain.setStrings( null );
}
if ( source.hasStringsWithDefault() ) { if ( source.hasStringsWithDefault() ) {
List<String> list1 = source.getStringsWithDefault(); List<String> list1 = source.getStringsWithDefault();
domain.setStringsWithDefault( new ArrayList<String>( list1 ) ); domain.setStringsWithDefault( new ArrayList<String>( list1 ) );
@ -48,9 +45,6 @@ public class DomainDtoWithPresenceCheckMapperImpl implements DomainDtoWithPresen
List<String> list2 = source.getStringsInitialized(); List<String> list2 = source.getStringsInitialized();
domain.setStringsInitialized( new HashSet<String>( list2 ) ); domain.setStringsInitialized( new HashSet<String>( list2 ) );
} }
else {
domain.setStringsInitialized( null );
}
return domain; return domain;
} }