From 6187a72a2b6d55674c2026dbf1028ef31d1b721c Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Wed, 24 May 2017 22:32:05 +0200 Subject: [PATCH] #1148 Always add the generated MappingMethod if the MappingOptions are restricted to the defined mappings --- .../internal/model/AbstractBaseBuilder.java | 5 +- .../internal/model/source/PropertyEntry.java | 4 + .../mapstruct/ap/test/bugs/_1148/Entity.java | 115 +++++++++++++ .../ap/test/bugs/_1148/Issue1148Mapper.java | 57 +++++++ .../ap/test/bugs/_1148/Issue1148Test.java | 157 ++++++++++++++++++ .../nestedbeans/mixed/FishTankMapperImpl.java | 30 +++- 6 files changed, 364 insertions(+), 4 deletions(-) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Entity.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Mapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Test.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractBaseBuilder.java b/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractBaseBuilder.java index 55b0885b7..a7bc1b77b 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractBaseBuilder.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/AbstractBaseBuilder.java @@ -117,7 +117,10 @@ class AbstractBaseBuilder> { if ( mappingMethod == null ) { return null; } - if ( !ctx.getMappingsToGenerate().contains( mappingMethod ) ) { + if (methodRef.getMappingOptions().isRestrictToDefinedMappings() || + !ctx.getMappingsToGenerate().contains( mappingMethod )) { + // If the mapping options are restricted only to the defined mappings, then use the mapping method. + // See https://github.com/mapstruct/mapstruct/issues/1148 ctx.getMappingsToGenerate().add( mappingMethod ); } else { diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/PropertyEntry.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/PropertyEntry.java index b88b3cbe0..4e189015c 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/PropertyEntry.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/PropertyEntry.java @@ -142,4 +142,8 @@ public class PropertyEntry { return true; } + @Override + public String toString() { + return type + " " + Strings.join( Arrays.asList( fullName ), "." ); + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Entity.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Entity.java new file mode 100644 index 000000000..6ed4f1e48 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Entity.java @@ -0,0 +1,115 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.bugs._1148; + +/** + * @author Filip Hrisafov + */ +class Entity { + + static class NestedClient { + //CHECKSTYLE:OFF + public long id; + //CHECKSTYLE:ON + } + + static class Client { + + //CHECKSTYLE:OFF + public NestedClient nestedClient; + //CHECKSTYLE:ON + } + + static class Dto { + + //CHECKSTYLE:OFF + public long recipientId; + public long senderId; + public NestedDto nestedDto; + public NestedDto nestedDto2; + public ClientDto sameLevel; + public ClientDto sameLevel2; + public ClientDto level; + public ClientDto level2; + //CHECKSTYLE:ON + } + + static class ClientDto { + //CHECKSTYLE:OFF + public NestedDto client; + + //CHECKSTYLE:ON + ClientDto(NestedDto client) { + this.client = client; + } + } + + static class NestedDto { + //CHECKSTYLE:OFF + public long id; + //CHECKSTYLE:ON + + NestedDto(long id) { + this.id = id; + } + } + + //CHECKSTYLE:OFF + public Client client; + public Client client2; + public NestedClient nested; + public NestedClient nested2; + private Client recipient; + private Client sender; + private long id; + private long id2; + //CHECKSTYLE:OFF + + public Client getRecipient() { + return recipient; + } + + public void setRecipient(Client recipient) { + this.recipient = recipient; + } + + public Client getSender() { + return sender; + } + + public void setSender(Client sender) { + this.sender = sender; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public long getId2() { + return id2; + } + + public void setId2(long id2) { + this.id2 = id2; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Mapper.java new file mode 100644 index 000000000..f4ae218ca --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Mapper.java @@ -0,0 +1,57 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.bugs._1148; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author Filip Hrisafov + */ +@Mapper +public interface Issue1148Mapper { + + Issue1148Mapper INSTANCE = Mappers.getMapper( Issue1148Mapper.class ); + + @Mappings({ + @Mapping(source = "senderId", target = "sender.nestedClient.id"), + @Mapping(source = "recipientId", target = "recipient.nestedClient.id"), + @Mapping(source = "sameLevel.client.id", target = "client.nestedClient.id"), + @Mapping(source = "sameLevel2.client.id", target = "client2.nestedClient.id"), + @Mapping(source = "level.client.id", target = "nested.id"), + @Mapping(source = "level2.client.id", target = "nested2.id"), + @Mapping(source = "nestedDto.id", target = "id"), + @Mapping(source = "nestedDto2.id", target = "id2") + }) + Entity toEntity(Entity.Dto dto); + + @Mappings({ + @Mapping(source = "dto2.senderId", target = "sender.nestedClient.id"), + @Mapping(source = "dto1.recipientId", target = "recipient.nestedClient.id"), + @Mapping(source = "dto1.sameLevel.client.id", target = "client.nestedClient.id"), + @Mapping(source = "dto2.sameLevel2.client.id", target = "client2.nestedClient.id"), + @Mapping(source = "dto1.level.client.id", target = "nested.id"), + @Mapping(source = "dto2.level2.client.id", target = "nested2.id"), + @Mapping(source = "dto1.nestedDto.id", target = "id"), + @Mapping(source = "dto2.nestedDto2.id", target = "id2") + }) + Entity toEntity(Entity.Dto dto1, Entity.Dto dto2); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Test.java new file mode 100644 index 000000000..5997b93d6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_1148/Issue1148Test.java @@ -0,0 +1,157 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.bugs._1148; + +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; + +/** + * @author Filip Hrisafov + */ +@WithClasses({ + Entity.class, + Issue1148Mapper.class +}) +@RunWith(AnnotationProcessorTestRunner.class) +@IssueKey("1148") +public class Issue1148Test { + + @Test + public void shouldNotUseSameMethodForDifferentMappingsNestedSource() throws Exception { + Entity.Dto dto = new Entity.Dto(); + dto.nestedDto = new Entity.NestedDto( 30 ); + dto.nestedDto2 = new Entity.NestedDto( 40 ); + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto ); + + assertThat( entity.getId() ).isEqualTo( 30 ); + assertThat( entity.getId2() ).isEqualTo( 40 ); + } + + @Test + public void shouldNotUseSameMethodForDifferentMappingsNestedTarget() throws Exception { + Entity.Dto dto = new Entity.Dto(); + dto.recipientId = 10; + dto.senderId = 20; + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto ); + + assertThat( entity.getRecipient() ).isNotNull(); + assertThat( entity.getRecipient().nestedClient ).isNotNull(); + assertThat( entity.getRecipient().nestedClient.id ).isEqualTo( 10 ); + + assertThat( entity.getSender() ).isNotNull(); + assertThat( entity.getSender().nestedClient ).isNotNull(); + assertThat( entity.getSender().nestedClient.id ).isEqualTo( 20 ); + } + + @Test + public void shouldNotUseSameMethodForDifferentMappingsSymmetric() throws Exception { + Entity.Dto dto = new Entity.Dto(); + dto.sameLevel = new Entity.ClientDto(new Entity.NestedDto( 30 )); + dto.sameLevel2 = new Entity.ClientDto(new Entity.NestedDto( 40 )); + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto ); + + assertThat( entity.client ).isNotNull(); + assertThat( entity.client.nestedClient ).isNotNull(); + assertThat( entity.client.nestedClient.id ).isEqualTo( 30 ); + + assertThat( entity.client2 ).isNotNull(); + assertThat( entity.client2.nestedClient ).isNotNull(); + assertThat( entity.client2.nestedClient.id ).isEqualTo( 40 ); + } + + @Test + public void shouldNotUseSameMethodForDifferentMappingsHalfSymmetric() throws Exception { + Entity.Dto dto = new Entity.Dto(); + dto.level = new Entity.ClientDto(new Entity.NestedDto( 80 )); + dto.level2 = new Entity.ClientDto(new Entity.NestedDto( 90 )); + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto ); + + assertThat( entity.nested ).isNotNull(); + assertThat( entity.nested.id ).isEqualTo( 80 ); + + assertThat( entity.nested2 ).isNotNull(); + assertThat( entity.nested2.id ).isEqualTo( 90 ); + } + + @Test + public void shouldNotUseSameMethodForDifferentMappingsNestedSourceMultiple() throws Exception { + Entity.Dto dto1 = new Entity.Dto(); + dto1.nestedDto = new Entity.NestedDto( 30 ); + Entity.Dto dto2 = new Entity.Dto(); + dto2.nestedDto2 = new Entity.NestedDto( 40 ); + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto1, dto2 ); + + assertThat( entity.getId() ).isEqualTo( 30 ); + assertThat( entity.getId2() ).isEqualTo( 40 ); + } + + @Test + public void shouldNotUseSameMethodForDifferentMappingsNestedTargetMultiple() throws Exception { + Entity.Dto dto1 = new Entity.Dto(); + dto1.recipientId = 10; + Entity.Dto dto2 = new Entity.Dto(); + dto2.senderId = 20; + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto1, dto2 ); + + assertThat( entity.getRecipient() ).isNotNull(); + assertThat( entity.getRecipient().nestedClient ).isNotNull(); + assertThat( entity.getRecipient().nestedClient.id ).isEqualTo( 10 ); + + assertThat( entity.getSender() ).isNotNull(); + assertThat( entity.getSender().nestedClient ).isNotNull(); + assertThat( entity.getSender().nestedClient.id ).isEqualTo( 20 ); + } + + @Test + public void shouldNotUseSameMethodForDifferentMappingsSymmetricMultiple() throws Exception { + Entity.Dto dto1 = new Entity.Dto(); + dto1.sameLevel = new Entity.ClientDto(new Entity.NestedDto( 30 )); + Entity.Dto dto2 = new Entity.Dto(); + dto2.sameLevel2 = new Entity.ClientDto(new Entity.NestedDto( 40 )); + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto1, dto2 ); + + assertThat( entity.client ).isNotNull(); + assertThat( entity.client.nestedClient ).isNotNull(); + assertThat( entity.client.nestedClient.id ).isEqualTo( 30 ); + + assertThat( entity.client2 ).isNotNull(); + assertThat( entity.client2.nestedClient ).isNotNull(); + assertThat( entity.client2.nestedClient.id ).isEqualTo( 40 ); + } + + @Test + public void shouldNotUseSameMethodForDifferentMappingsHalfSymmetricMultiple() { + Entity.Dto dto1 = new Entity.Dto(); + dto1.level = new Entity.ClientDto(new Entity.NestedDto( 80 )); + Entity.Dto dto2 = new Entity.Dto(); + dto2.level2 = new Entity.ClientDto(new Entity.NestedDto( 90 )); + Entity entity = Issue1148Mapper.INSTANCE.toEntity( dto1, dto2 ); + + assertThat( entity.nested ).isNotNull(); + assertThat( entity.nested.id ).isEqualTo( 80 ); + + assertThat( entity.nested2 ).isNotNull(); + assertThat( entity.nested2.id ).isEqualTo( 90 ); + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/nestedbeans/mixed/FishTankMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/nestedbeans/mixed/FishTankMapperImpl.java index 40b8254e2..b2bd75206 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/nestedbeans/mixed/FishTankMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/nestedbeans/mixed/FishTankMapperImpl.java @@ -39,8 +39,8 @@ import org.mapstruct.ap.test.nestedbeans.mixed.source.WaterQualityReport; @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2017-02-19T16:25:02+0100", - comments = "version: , compiler: javac, environment: Java 1.8.0_112 (Oracle Corporation)" + date = "2017-04-24T17:26:46+0200", + comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)" ) public class FishTankMapperImpl implements FishTankMapper { @@ -74,7 +74,7 @@ public class FishTankMapperImpl implements FishTankMapper { FishTankDto fishTankDto = new FishTankDto(); fishTankDto.setFish( fishToFishDto( source.getFish() ) ); - fishTankDto.setMaterial( fishTankToMaterialDto( source ) ); + fishTankDto.setMaterial( fishTankToMaterialDto1( source ) ); fishTankDto.setQuality( waterQualityToWaterQualityDto( source.getQuality() ) ); Ornament ornament = sourceInteriorOrnament( source ); if ( ornament != null ) { @@ -219,6 +219,30 @@ public class FishTankMapperImpl implements FishTankMapper { return waterPlantDto; } + protected MaterialDto fishTankToMaterialDto1(FishTank fishTank) { + if ( fishTank == null ) { + return null; + } + + MaterialDto materialDto = new MaterialDto(); + + materialDto.setMaterialType( materialTypeToMaterialTypeDto( fishTank.getMaterial() ) ); + + return materialDto; + } + + protected WaterQualityOrganisationDto waterQualityReportToWaterQualityOrganisationDto1(WaterQualityReport waterQualityReport) { + if ( waterQualityReport == null ) { + return null; + } + + WaterQualityOrganisationDto waterQualityOrganisationDto = new WaterQualityOrganisationDto(); + + waterQualityOrganisationDto.setName( waterQualityReport.getOrganisationName() ); + + return waterQualityOrganisationDto; + } + protected Fish fishDtoToFish(FishDto fishDto) { if ( fishDto == null ) { return null;