mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#3126 Apply target this references in the BeanMappingMethod
This commit is contained in:
parent
51f4e7eba9
commit
c2eed45df1
@ -117,6 +117,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
private final Map<String, Set<MappingReference>> unprocessedDefinedTargets = new LinkedHashMap<>();
|
||||
|
||||
private MappingReferences mappingReferences;
|
||||
private List<MappingReference> targetThisReferences;
|
||||
private MethodReference factoryMethod;
|
||||
private boolean hasFactoryMethod;
|
||||
|
||||
@ -1068,6 +1069,14 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
for ( MappingReference mapping : mappingReferences.getMappingReferences() ) {
|
||||
if ( mapping.isValid() ) {
|
||||
String target = mapping.getTargetReference().getShallowestPropertyName();
|
||||
if ( target == null ) {
|
||||
// When the shallowest property name is null then it is for @Mapping(target = ".")
|
||||
if ( this.targetThisReferences == null ) {
|
||||
this.targetThisReferences = new ArrayList<>();
|
||||
}
|
||||
this.targetThisReferences.add( mapping );
|
||||
continue;
|
||||
}
|
||||
if ( !handledTargets.contains( target ) ) {
|
||||
if ( handleDefinedMapping( mapping, resultTypeToMap, handledTargets ) ) {
|
||||
errorOccurred = true;
|
||||
@ -1435,8 +1444,11 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
* duplicates will be handled by {@link #applyPropertyNameBasedMapping(List)}
|
||||
*/
|
||||
private void applyTargetThisMapping() {
|
||||
if ( this.targetThisReferences == null ) {
|
||||
return;
|
||||
}
|
||||
Set<String> handledTargetProperties = new HashSet<>();
|
||||
for ( MappingReference targetThis : mappingReferences.getTargetThisReferences() ) {
|
||||
for ( MappingReference targetThis : this.targetThisReferences ) {
|
||||
|
||||
// handle all prior unprocessed target properties, but let duplicates fall through
|
||||
List<SourceReference> sourceRefs = targetThis
|
||||
|
@ -5,10 +5,8 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model.beanmapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@ -23,7 +21,6 @@ public class MappingReferences {
|
||||
private static final MappingReferences EMPTY = new MappingReferences( Collections.emptySet(), false );
|
||||
|
||||
private final Set<MappingReference> mappingReferences;
|
||||
private final List<MappingReference> targetThisReferences;
|
||||
private final boolean restrictToDefinedMappings;
|
||||
private final boolean forForgedMethods;
|
||||
|
||||
@ -38,7 +35,6 @@ public class MappingReferences {
|
||||
TypeFactory typeFactory) {
|
||||
|
||||
Set<MappingReference> references = new LinkedHashSet<>();
|
||||
List<MappingReference> targetThisReferences = new ArrayList<>( );
|
||||
|
||||
for ( MappingOptions mapping : sourceMethod.getOptions().getMappings() ) {
|
||||
|
||||
@ -61,30 +57,16 @@ public class MappingReferences {
|
||||
// add when inverse is also valid
|
||||
MappingReference mappingReference = new MappingReference( mapping, targetReference, sourceReference );
|
||||
if ( isValidWhenInversed( mappingReference ) ) {
|
||||
if ( ".".equals( mapping.getTargetName() ) ) {
|
||||
targetThisReferences.add( mappingReference );
|
||||
}
|
||||
else {
|
||||
references.add( mappingReference );
|
||||
}
|
||||
references.add( mappingReference );
|
||||
}
|
||||
}
|
||||
return new MappingReferences( references, targetThisReferences, false );
|
||||
}
|
||||
|
||||
public MappingReferences(Set<MappingReference> mappingReferences, List<MappingReference> targetThisReferences,
|
||||
boolean restrictToDefinedMappings) {
|
||||
this.mappingReferences = mappingReferences;
|
||||
this.restrictToDefinedMappings = restrictToDefinedMappings;
|
||||
this.forForgedMethods = restrictToDefinedMappings;
|
||||
this.targetThisReferences = targetThisReferences;
|
||||
return new MappingReferences( references, false );
|
||||
}
|
||||
|
||||
public MappingReferences(Set<MappingReference> mappingReferences, boolean restrictToDefinedMappings) {
|
||||
this.mappingReferences = mappingReferences;
|
||||
this.restrictToDefinedMappings = restrictToDefinedMappings;
|
||||
this.forForgedMethods = restrictToDefinedMappings;
|
||||
this.targetThisReferences = Collections.emptyList();
|
||||
}
|
||||
|
||||
public MappingReferences(Set<MappingReference> mappingReferences, boolean restrictToDefinedMappings,
|
||||
@ -92,7 +74,6 @@ public class MappingReferences {
|
||||
this.mappingReferences = mappingReferences;
|
||||
this.restrictToDefinedMappings = restrictToDefinedMappings;
|
||||
this.forForgedMethods = forForgedMethods;
|
||||
this.targetThisReferences = Collections.emptyList();
|
||||
}
|
||||
|
||||
public Set<MappingReference> getMappingReferences() {
|
||||
@ -136,10 +117,6 @@ public class MappingReferences {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<MappingReference> getTargetThisReferences() {
|
||||
return targetThisReferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
@ -160,9 +137,6 @@ public class MappingReferences {
|
||||
if ( !Objects.equals( mappingReferences, that.mappingReferences ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( Objects.equals( targetThisReferences, that.targetThisReferences ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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._3126;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.SubclassExhaustiveStrategy;
|
||||
import org.mapstruct.SubclassMapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper(subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION)
|
||||
public interface Issue3126Mapper {
|
||||
|
||||
Issue3126Mapper INSTANCE = Mappers.getMapper( Issue3126Mapper.class );
|
||||
|
||||
@SubclassMapping(target = HomeAddressDto.class, source = HomeAddress.class)
|
||||
@SubclassMapping(target = OfficeAddressDto.class, source = OfficeAddress.class)
|
||||
@Mapping(target = ".", source = "auditable")
|
||||
AddressDto map(Address address);
|
||||
|
||||
interface AddressDto {
|
||||
|
||||
}
|
||||
|
||||
class HomeAddressDto implements AddressDto {
|
||||
private String createdBy;
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
}
|
||||
|
||||
class OfficeAddressDto implements AddressDto {
|
||||
private String createdBy;
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
}
|
||||
|
||||
class HomeAddress extends Address {
|
||||
|
||||
public HomeAddress(Auditable auditable) {
|
||||
super( auditable );
|
||||
}
|
||||
}
|
||||
|
||||
class OfficeAddress extends Address {
|
||||
|
||||
public OfficeAddress(Auditable auditable) {
|
||||
super( auditable );
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Address {
|
||||
|
||||
private final Auditable auditable;
|
||||
|
||||
protected Address(Auditable auditable) {
|
||||
this.auditable = auditable;
|
||||
}
|
||||
|
||||
public Auditable getAuditable() {
|
||||
return auditable;
|
||||
}
|
||||
}
|
||||
|
||||
class Auditable {
|
||||
|
||||
private final String createdBy;
|
||||
|
||||
public Auditable(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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._3126;
|
||||
|
||||
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;
|
||||
|
||||
@IssueKey("3126")
|
||||
@WithClasses(Issue3126Mapper.class)
|
||||
class Issue3126Test {
|
||||
|
||||
@ProcessorTest
|
||||
void shouldCompile() {
|
||||
Issue3126Mapper.Auditable auditable = new Issue3126Mapper.Auditable( "home-user" );
|
||||
Issue3126Mapper.Address address = new Issue3126Mapper.HomeAddress( auditable );
|
||||
Issue3126Mapper.AddressDto addressDto = Issue3126Mapper.INSTANCE.map( address );
|
||||
|
||||
assertThat( addressDto ).isInstanceOfSatisfying( Issue3126Mapper.HomeAddressDto.class, homeAddress -> {
|
||||
assertThat( homeAddress.getCreatedBy() ).isEqualTo( "home-user" );
|
||||
} );
|
||||
}
|
||||
}
|
@ -57,9 +57,9 @@ public class FishTankMapperImpl implements FishTankMapper {
|
||||
|
||||
FishTankDto fishTankDto = new FishTankDto();
|
||||
|
||||
fishTankDto.setFish( fishToFishDto1( source.getFish() ) );
|
||||
fishTankDto.setFish( fishToFishDto( source.getFish() ) );
|
||||
fishTankDto.setMaterial( fishTankToMaterialDto1( source ) );
|
||||
fishTankDto.setQuality( waterQualityToWaterQualityDto1( source.getQuality() ) );
|
||||
fishTankDto.setQuality( waterQualityToWaterQualityDto( source.getQuality() ) );
|
||||
fishTankDto.setOrnament( ornamentToOrnamentDto( sourceInteriorOrnament( source ) ) );
|
||||
fishTankDto.setPlant( waterPlantToWaterPlantDto( source.getPlant() ) );
|
||||
fishTankDto.setName( source.getName() );
|
||||
@ -190,18 +190,6 @@ public class FishTankMapperImpl implements FishTankMapper {
|
||||
return waterPlantDto;
|
||||
}
|
||||
|
||||
protected FishDto fishToFishDto1(Fish fish) {
|
||||
if ( fish == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FishDto fishDto = new FishDto();
|
||||
|
||||
fishDto.setKind( fish.getType() );
|
||||
|
||||
return fishDto;
|
||||
}
|
||||
|
||||
protected MaterialDto fishTankToMaterialDto1(FishTank fishTank) {
|
||||
if ( fishTank == null ) {
|
||||
return null;
|
||||
@ -226,31 +214,6 @@ public class FishTankMapperImpl implements FishTankMapper {
|
||||
return waterQualityOrganisationDto;
|
||||
}
|
||||
|
||||
protected WaterQualityReportDto waterQualityReportToWaterQualityReportDto1(WaterQualityReport waterQualityReport) {
|
||||
if ( waterQualityReport == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
WaterQualityReportDto waterQualityReportDto = new WaterQualityReportDto();
|
||||
|
||||
waterQualityReportDto.setOrganisation( waterQualityReportToWaterQualityOrganisationDto1( waterQualityReport ) );
|
||||
waterQualityReportDto.setVerdict( waterQualityReport.getVerdict() );
|
||||
|
||||
return waterQualityReportDto;
|
||||
}
|
||||
|
||||
protected WaterQualityDto waterQualityToWaterQualityDto1(WaterQuality waterQuality) {
|
||||
if ( waterQuality == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
WaterQualityDto waterQualityDto = new WaterQualityDto();
|
||||
|
||||
waterQualityDto.setReport( waterQualityReportToWaterQualityReportDto1( waterQuality.getReport() ) );
|
||||
|
||||
return waterQualityDto;
|
||||
}
|
||||
|
||||
protected Fish fishDtoToFish(FishDto fishDto) {
|
||||
if ( fishDto == null ) {
|
||||
return null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user