diff --git a/copyright.txt b/copyright.txt index 6757936ad..826b627d4 100644 --- a/copyright.txt +++ b/copyright.txt @@ -23,6 +23,7 @@ Gervais Blaise - https://github.com/gervaisb Gunnar Morling - https://github.com/gunnarmorling Ivo Smid - https://github.com/bedla Jeff Smyth - https://github.com/smythie86 +Jonathan Kraska - https://github.com/jakraska Joshua Spoerri - https://github.com/spoerri Kevin Grüneberg - https://github.com/kevcodez Michael Pardo - https://github.com/pardom diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl index e50e55bc3..22dc2d8c3 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl @@ -12,7 +12,7 @@ } <#list propertyEntries as entry> <#if entry.presenceCheckerName?? > - if ( !<@localVarName index=entry_index/>.${entry.presenceCheckerName}() ) { + if ( <#if entry_index != 0><@localVarName index=entry_index/> == null || !<@localVarName index=entry_index/>.${entry.presenceCheckerName}() ) { return ${returnType.null}; } diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Issue1826Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Issue1826Mapper.java new file mode 100644 index 000000000..126837cbf --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Issue1826Mapper.java @@ -0,0 +1,20 @@ +/* + * 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.bugs._1826; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface Issue1826Mapper { + + Issue1826Mapper INSTANCE = Mappers.getMapper( Issue1826Mapper.class ); + + @Mapping(target = "content", source = "sourceChild.content") + Target sourceAToTarget(SourceParent sourceParent); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Issue1826Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Issue1826Test.java new file mode 100644 index 000000000..66f6cb14f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Issue1826Test.java @@ -0,0 +1,34 @@ +/* + * 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.bugs._1826; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(AnnotationProcessorTestRunner.class) +@IssueKey("1826") +@WithClasses({ + SourceParent.class, + SourceChild.class, + Target.class, + Issue1826Mapper.class +}) +public class Issue1826Test { + + @Test + public void testNestedPropertyMappingChecksForNull() { + SourceParent sourceParent = new SourceParent(); + sourceParent.setSourceChild( null ); + + Target result = Issue1826Mapper.INSTANCE.sourceAToTarget( sourceParent ); + assertThat( result.getContent() ).isNull(); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/SourceChild.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/SourceChild.java new file mode 100644 index 000000000..4243d444e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/SourceChild.java @@ -0,0 +1,25 @@ +/* + * 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.bugs._1826; + +public class SourceChild { + + private String content; + private Boolean hasContent = false; + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + hasContent = true; + } + + public Boolean hasContent() { + return hasContent; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/SourceParent.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/SourceParent.java new file mode 100644 index 000000000..65f737d15 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/SourceParent.java @@ -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.bugs._1826; + +public class SourceParent { + + private SourceChild sourceChild; + private Boolean hasSourceChild = false; + + public SourceChild getSourceChild() { + return sourceChild; + } + + public void setSourceChild(SourceChild sourceChild) { + this.sourceChild = sourceChild; + this.hasSourceChild = true; + } + + public Boolean hasSourceChild() { + return hasSourceChild; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Target.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Target.java new file mode 100644 index 000000000..9d2ec717f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1826/Target.java @@ -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.bugs._1826; + +public class Target { + + private String content; + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +}