diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java index 0cd484122..d7f1c3084 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java @@ -470,6 +470,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod { .sourceMethod( method ) .targetProperty( targetProperty ) .targetPropertyName( mapping.getTargetName() ) + .sourcePropertyName( mapping.getSourceName() ) .sourceReference( sourceRef ) .selectionParameters( mapping.getSelectionParameters() ) .formattingParameters( mapping.getFormattingParameters() ) diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java index c8c0b00cd..cbfe5aa68 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java @@ -105,6 +105,7 @@ public class PropertyMapping extends ModelElement { protected Type targetType; protected Accessor targetReadAccessor; protected String targetPropertyName; + protected String sourcePropertyName; protected List dependsOn; protected Set existingVariableNames; @@ -171,6 +172,11 @@ public class PropertyMapping extends ModelElement { return (T) this; } + public T sourcePropertyName(String sourcePropertyName) { + this.sourcePropertyName = sourcePropertyName; + return (T) this; + } + public T dependsOn(List dependsOn) { this.dependsOn = dependsOn; return (T) this; @@ -468,12 +474,13 @@ public class PropertyMapping extends ModelElement { Assignment result = rightHandSide; + String adderIteratorName = sourcePropertyName == null ? targetPropertyName : sourcePropertyName; if ( result.getSourceType().isCollectionType() ) { - result = new AdderWrapper( result, method.getThrownTypes(), isFieldAssignment(), targetPropertyName ); + result = new AdderWrapper( result, method.getThrownTypes(), isFieldAssignment(), adderIteratorName ); } else if ( result.getSourceType().isStreamType() ) { result = new StreamAdderWrapper( - result, method.getThrownTypes(), isFieldAssignment(), targetPropertyName ); + result, method.getThrownTypes(), isFieldAssignment(), adderIteratorName ); } else { // Possibly adding null to a target collection. So should be surrounded by an null check. diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/AdderWrapper.java b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/AdderWrapper.java index 73dba6234..0cb2a2302 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/AdderWrapper.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/AdderWrapper.java @@ -30,10 +30,10 @@ public class AdderWrapper extends AssignmentWrapper { public AdderWrapper( Assignment rhs, List thrownTypesToExclude, boolean fieldAssignment, - String targetPropertyName ) { + String adderIteratorName ) { super( rhs, fieldAssignment ); this.thrownTypesToExclude = thrownTypesToExclude; - String desiredName = Nouns.singularize( targetPropertyName ); + String desiredName = Nouns.singularize( adderIteratorName ); rhs.setSourceLocalVarName( rhs.createLocalVarName( desiredName ) ); adderType = first( getSourceType().determineTypeArguments( Collection.class ) ); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java index cb2a93b1a..1507f5639 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java @@ -25,12 +25,14 @@ import org.mapstruct.ap.test.collection.adder._target.TargetDali; import org.mapstruct.ap.test.collection.adder._target.TargetHuman; import org.mapstruct.ap.test.collection.adder._target.TargetOnlyGetter; import org.mapstruct.ap.test.collection.adder._target.TargetViaTargetType; +import org.mapstruct.ap.test.collection.adder._target.TargetWithAnimals; import org.mapstruct.ap.test.collection.adder._target.TargetWithoutSetter; import org.mapstruct.ap.test.collection.adder.source.Foo; import org.mapstruct.ap.test.collection.adder.source.SingleElementSource; import org.mapstruct.ap.test.collection.adder.source.Source; import org.mapstruct.ap.test.collection.adder.source.Source2; import org.mapstruct.ap.test.collection.adder.source.SourceTeeth; +import org.mapstruct.ap.test.collection.adder.source.SourceWithPets; import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; @@ -42,15 +44,18 @@ import org.mapstruct.ap.testutil.runner.GeneratedSource; @WithClasses({ Source.class, SourceTeeth.class, + SourceWithPets.class, Target.class, TargetDali.class, TargetHuman.class, TargetOnlyGetter.class, TargetViaTargetType.class, TargetWithoutSetter.class, + TargetWithAnimals.class, SourceTargetMapper.class, SourceTargetMapperStrategyDefault.class, SourceTargetMapperStrategySetterPreferred.class, + SourceTargetMapperWithDifferentProperties.class, SingleElementSource.class, PetMapper.class, TeethMapper.class, @@ -255,4 +260,17 @@ public class AdderTest { assertThat( target ).isNotNull(); assertThat( target.getAttributes().size() ).isEqualTo( 1 ); } + + @IssueKey("1478") + @Test + public void useIterationNameFromSource() { + generatedSource.addComparisonToFixtureFor( SourceTargetMapperWithDifferentProperties.class ); + + SourceWithPets source = new SourceWithPets(); + source.setPets( Arrays.asList( "dog", "cat" ) ); + + TargetWithAnimals target = SourceTargetMapperWithDifferentProperties.INSTANCE.map( source ); + + assertThat( target.getAnimals() ).containsExactly( "dog", "cat" ); + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperWithDifferentProperties.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperWithDifferentProperties.java new file mode 100644 index 000000000..b0460c265 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperWithDifferentProperties.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.collection.adder; + +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.ap.test.collection.adder._target.TargetWithAnimals; +import org.mapstruct.ap.test.collection.adder.source.SourceWithPets; +import org.mapstruct.factory.Mappers; + +/** + * @author Filip Hrisafov + */ +@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) +public interface SourceTargetMapperWithDifferentProperties { + + SourceTargetMapperWithDifferentProperties INSTANCE = + Mappers.getMapper( SourceTargetMapperWithDifferentProperties.class ); + + @Mapping(target = "animals", source = "pets") + TargetWithAnimals map(SourceWithPets source); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/_target/TargetWithAnimals.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/_target/TargetWithAnimals.java new file mode 100644 index 000000000..500525123 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/_target/TargetWithAnimals.java @@ -0,0 +1,29 @@ +/* + * 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.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Filip Hrisafov + */ +public class TargetWithAnimals { + + private List animals = new ArrayList(); + + public List getAnimals() { + return animals; + } + + public void setAnimals(List animals) { + this.animals = animals; + } + + public void addAnimal(String animal) { + animals.add( animal ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/SourceWithPets.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/SourceWithPets.java new file mode 100644 index 000000000..bbb000653 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/SourceWithPets.java @@ -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.collection.adder.source; + +import java.util.List; + +/** + * @author Filip Hrisafov + */ +public class SourceWithPets { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets(List pets) { + this.pets = pets; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/collection/adder/SourceTargetMapperWithDifferentPropertiesImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/collection/adder/SourceTargetMapperWithDifferentPropertiesImpl.java new file mode 100644 index 000000000..3a3f60b32 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/collection/adder/SourceTargetMapperWithDifferentPropertiesImpl.java @@ -0,0 +1,35 @@ +/* + * 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.collection.adder; + +import javax.annotation.Generated; +import org.mapstruct.ap.test.collection.adder._target.TargetWithAnimals; +import org.mapstruct.ap.test.collection.adder.source.SourceWithPets; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2018-10-13T10:43:55+0200", + comments = "version: , compiler: javac, environment: Java 1.8.0_161 (Oracle Corporation)" +) +public class SourceTargetMapperWithDifferentPropertiesImpl implements SourceTargetMapperWithDifferentProperties { + + @Override + public TargetWithAnimals map(SourceWithPets source) { + if ( source == null ) { + return null; + } + + TargetWithAnimals targetWithAnimals = new TargetWithAnimals(); + + if ( source.getPets() != null ) { + for ( String pet : source.getPets() ) { + targetWithAnimals.addAnimal( pet ); + } + } + + return targetWithAnimals; + } +}