diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java index f742e1ba0..54305cffc 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java @@ -821,12 +821,6 @@ public class Type extends ModelElement implements Comparable { candidate = adderMethod; } - if ( cmStrategy == CollectionMappingStrategyGem.TARGET_IMMUTABLE - && candidate.getAccessorType() == AccessorType.GETTER ) { - // If the collection mapping strategy is target immutable - // then the getter method cannot be used as a setter - continue; - } } else if ( candidate.getAccessorType() == AccessorType.FIELD && ( Executables.isFinal( candidate ) || result.containsKey( targetPropertyName ) ) ) { @@ -834,6 +828,16 @@ public class Type extends ModelElement implements Comparable { continue; } + if ( candidate.getAccessorType() == AccessorType.GETTER ) { + // When the candidate is a getter then it can't be used in the following cases: + // 1. The collection mapping strategy is target immutable + // 2. The target type is a stream (streams are immutable) + if ( cmStrategy == CollectionMappingStrategyGem.TARGET_IMMUTABLE || + targetType != null && targetType.isStreamType() ) { + continue; + } + } + Accessor previousCandidate = result.get( targetPropertyName ); if ( previousCandidate == null || preferredType == null || ( targetType != null && typeUtils.isAssignable( preferredType.getTypeMirror(), targetType.getTypeMirror() ) ) ) { diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_3462/Issue3462Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_3462/Issue3462Mapper.java new file mode 100644 index 000000000..1bf87672c --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_3462/Issue3462Mapper.java @@ -0,0 +1,56 @@ +/* + * 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._3462; + +import java.util.List; +import java.util.stream.Stream; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author Filip Hrisafov + */ +@Mapper +public interface Issue3462Mapper { + + Issue3462Mapper INSTANCE = Mappers.getMapper( Issue3462Mapper.class ); + + Target map(Source source); + + class Source { + private final List values; + + public Source(List values) { + this.values = values; + } + + public List getValues() { + return values; + } + + public Stream getValuesStream() { + return values != null ? values.stream() : Stream.empty(); + } + } + + class Target { + private List values; + + public List getValues() { + return values; + } + + public void setValues(List values) { + this.values = values; + } + + public Stream getValuesStream() { + return values != null ? values.stream() : Stream.empty(); + } + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_3462/Issue3462Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_3462/Issue3462Test.java new file mode 100644 index 000000000..16be4f441 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_3462/Issue3462Test.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._3462; + +import java.util.Arrays; + +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Filip Hrisafov + */ +@IssueKey("3462") +@WithClasses(Issue3462Mapper.class) +class Issue3462Test { + + @ProcessorTest + void shouldNotTreatStreamGettersAsAlternativeSetter() { + + Issue3462Mapper.Source source = new Issue3462Mapper.Source( Arrays.asList( "first", "second" ) ); + Issue3462Mapper.Target target = Issue3462Mapper.INSTANCE.map( source ); + + assertThat( target ).isNotNull(); + assertThat( target.getValues() ).containsExactly( "first", "second" ); + assertThat( target.getValuesStream() ).containsExactly( "first", "second" ); + + } +}