diff --git a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java index dd433a6a0..e14ee8241 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java @@ -39,7 +39,7 @@ public class PropertyMapping extends AbstractModelElement { private final String targetName; private final String targetAccessorName; private final Type targetType; - private final boolean isHasTargetSetter; + private final boolean isTargetAccessorSetter; private final MappingMethodReference mappingMethod; private final TypeConversion conversion; @@ -56,7 +56,7 @@ public class PropertyMapping extends AbstractModelElement { this.targetName = targetName; this.targetAccessorName = targetAccessorName; this.targetType = targetType; - this.isHasTargetSetter = targetAccessorName.startsWith( "set" ); + this.isTargetAccessorSetter = targetAccessorName.startsWith( "set" ); this.mappingMethod = mappingMethod; this.conversion = conversion; @@ -98,8 +98,15 @@ public class PropertyMapping extends AbstractModelElement { return conversion; } - public boolean isHasTargetSetter() { - return isHasTargetSetter; + /** + * Whether the target accessor is a setter method or not. The only case where it is not a setter but a getter is a + * collection-typed property without a getter, to which elements are set by adding the source elements to the + * collection retrieved via the getter. + * + * @return {@code true} if the target accessor is a setter, {@code false} otherwise + */ + public boolean isTargetAccessorSetter() { + return isTargetAccessorSetter; } @Override diff --git a/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl b/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl index 84660f74c..a2ce497f5 100644 --- a/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl +++ b/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl @@ -20,11 +20,11 @@ --> <#-- a) invoke mapping method --> <#if mappingMethod??> -<#if hasTargetSetter> +<#if targetAccessorSetter> ${ext.targetBeanName}.${targetAccessorName}( <@includeModel object=mappingMethod input="${sourceBeanName}.${sourceAccessorName}()"/> ); -<#else> -if ( ${sourceBeanName}.${sourceAccessorName}() != null ) { -${ext.targetBeanName}.${targetAccessorName}().addAll( <@includeModel object=mappingMethod input="${sourceBeanName}.${sourceAccessorName}()"/> ); +<#elseif targetType.collectionType> +if ( ${sourceBeanName}.${sourceAccessorName}() != null && ${ext.targetBeanName}.${targetAccessorName}() != null ) { + ${ext.targetBeanName}.${targetAccessorName}().addAll( <@includeModel object=mappingMethod input="${sourceBeanName}.${sourceAccessorName}()"/> ); } <#-- b) simple conversion --> @@ -39,13 +39,15 @@ if ( ${sourceBeanName}.${sourceAccessorName}() != null ) { <#-- c) simply set --> <#else> <#if targetType.collectionType || targetType.mapType> + <#if targetAccessorSetter> if ( ${sourceBeanName}.${sourceAccessorName}() != null ) { -<#if hasTargetSetter> ${ext.targetBeanName}.${targetAccessorName}( new <#if targetType.implementationType??><@includeModel object=targetType.implementationType/><#else><@includeModel object=targetType/>( ${sourceBeanName}.${sourceAccessorName}() ) ); -<#else> - ${ext.targetBeanName}.${targetAccessorName}().addAll( new <#if targetType.implementationType??><@includeModel object=targetType.implementationType/><#else><@includeModel object=targetType/>( ${sourceBeanName}.${sourceAccessorName}() ) ); - } + <#else> +if ( ${sourceBeanName}.${sourceAccessorName}() != null && ${ext.targetBeanName}.${targetAccessorName}() != null ) { + ${ext.targetBeanName}.${targetAccessorName}().addAll( ${sourceBeanName}.${sourceAccessorName}() ); +} + <#else> ${ext.targetBeanName}.${targetAccessorName}( ${sourceBeanName}.${sourceAccessorName}() );