#1269 use update methods for different sources for nested targets

This commit is contained in:
Filip Hrisafov 2017-08-27 18:59:17 +02:00 committed by GitHub
parent 4d8bc29347
commit 5cead7ae5e
10 changed files with 435 additions and 5 deletions

View File

@ -85,3 +85,9 @@ Instead of configuring everything via the parent method we encourage users to ex
This puts the configuration of the nested mapping into one place (method) where it can be reused from several methods in the upper level,
instead of re-configuring the same things on all of those upper methods.
====
[NOTE]
====
In some cases the `ReportingPolicy` that is going to be used for the generated nested method would be `IGNORE`.
This means that it is possible for MapStruct not to report unmapped target properties in nested mappings.
====

View File

@ -155,7 +155,8 @@ public class NestedTargetPropertyMappingHolder {
entryByTP.getValue(),
groupedByTP.singleTargetReferences.get( targetProperty )
);
boolean forceUpdateMethod = groupedBySourceParam.groupedBySourceParameter.keySet().size() > 1;
boolean multipleSourceParametersForTP =
groupedBySourceParam.groupedBySourceParameter.keySet().size() > 1;
// All not processed mappings that should have been applied to all are part of the unprocessed
// defined targets
@ -180,9 +181,21 @@ public class NestedTargetPropertyMappingHolder {
.groupedBySourceReferences
.entrySet() ) {
PropertyEntry sourceEntry = entryBySP.getKey();
boolean forceUpdateMethodOrNonNestedReferencesPresent =
multipleSourceParametersForTP || !groupedSourceReferences.nonNested.isEmpty();
// If there are multiple source parameters that are mapped to the target reference
// then we restrict the mapping only to the defined mappings. And we create MappingOptions
// for forged methods (which means that any unmapped target properties are ignored)
// MappingOptions for forged methods is also created if we have something like this:
//@Mappings({
// @Mapping(target = "vehicleInfo", source = "vehicleTypeInfo"),
// @Mapping(target = "vehicleInfo.images", source = "images")
//})
// See Issue1269Test, Issue1247Test, AutomappingAndNestedTest for more info as well
MappingOptions sourceMappingOptions = MappingOptions.forMappingsOnly(
groupByTargetName( entryBySP.getValue() ),
forceUpdateMethod
multipleSourceParametersForTP,
forceUpdateMethodOrNonNestedReferencesPresent
);
SourceReference sourceRef = new SourceReference.BuilderFromProperty()
.sourceParameter( sourceParameter )
@ -192,11 +205,14 @@ public class NestedTargetPropertyMappingHolder {
.name( targetProperty.getName() )
.build();
// If we have multiple source parameters that are mapped to the target reference, or
// parts of the nested properties are mapped to different sources (see comment above as well)
// we would force an update method
PropertyMapping propertyMapping = createPropertyMappingForNestedTarget(
sourceMappingOptions,
targetProperty,
sourceRef,
forceUpdateMethod
forceUpdateMethodOrNonNestedReferencesPresent
);
if ( propertyMapping != null ) {
@ -219,11 +235,17 @@ public class NestedTargetPropertyMappingHolder {
.name( targetProperty.getName() )
.build();
boolean forceUpdateMethodForNonNested =
multipleSourceParametersForTP ||
!groupedSourceReferences.groupedBySourceReferences.isEmpty();
// If an update method is forced or there are groupedBySourceReferences then we must create
// an update method. The reason is that they might be for the same reference and we should
// use update for it
PropertyMapping propertyMapping = createPropertyMappingForNestedTarget(
nonNestedOptions,
targetProperty,
reference,
forceUpdateMethod
forceUpdateMethodForNonNested
);
if ( propertyMapping != null ) {
@ -237,7 +259,7 @@ public class NestedTargetPropertyMappingHolder {
groupedSourceReferences.sourceParameterMappings,
targetProperty,
sourceParameter,
forceUpdateMethod
multipleSourceParametersForTP
);
unprocessedDefinedTarget.put( targetProperty, groupedSourceReferences.notProcessedAppliesToAll );

View File

@ -0,0 +1,78 @@
/**
* 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._1269;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mapstruct.ap.test.bugs._1269.dto.VehicleDto;
import org.mapstruct.ap.test.bugs._1269.dto.VehicleImageDto;
import org.mapstruct.ap.test.bugs._1269.dto.VehicleInfoDto;
import org.mapstruct.ap.test.bugs._1269.mapper.VehicleMapper;
import org.mapstruct.ap.test.bugs._1269.model.Vehicle;
import org.mapstruct.ap.test.bugs._1269.model.VehicleImage;
import org.mapstruct.ap.test.bugs._1269.model.VehicleTypeInfo;
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
*/
@IssueKey( "1269" )
@RunWith( AnnotationProcessorTestRunner.class )
@WithClasses( {
VehicleDto.class,
VehicleImageDto.class,
VehicleInfoDto.class,
Vehicle.class,
VehicleImage.class,
VehicleTypeInfo.class,
VehicleMapper.class
} )
public class Issue1269Test {
@Test
public void shouldMapNestedPropertiesCorrectly() {
VehicleTypeInfo sourceTypeInfo = new VehicleTypeInfo( "Opel", "Corsa", 3 );
List<VehicleImage> sourceImages = Arrays.asList(
new VehicleImage( 100, "something" ),
new VehicleImage( 150, "somethingElse" )
);
Vehicle source = new Vehicle( sourceTypeInfo, sourceImages );
VehicleDto target = VehicleMapper.INSTANCE.map( source );
assertThat( target.getVehicleInfo() ).isNotNull();
assertThat( target.getVehicleInfo().getDoors() ).isEqualTo( 3 );
assertThat( target.getVehicleInfo().getType() ).isEqualTo( "Opel" );
assertThat( target.getVehicleInfo().getName() ).isEqualTo( "Corsa" );
assertThat( target.getVehicleInfo().getImages() ).hasSize( 2 );
assertThat( target.getVehicleInfo().getImages().get( 0 ) )
.isEqualToComparingFieldByField( sourceImages.get( 0 ) );
assertThat( target.getVehicleInfo().getImages().get( 1 ) )
.isEqualToComparingFieldByField( sourceImages.get( 1 ) );
}
}

View File

@ -0,0 +1,36 @@
/**
* 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._1269.dto;
/**
* @author Filip Hrisafov
*/
public class VehicleDto {
private VehicleInfoDto vehicleInfo;
public VehicleInfoDto getVehicleInfo() {
return vehicleInfo;
}
public void setVehicleInfo(VehicleInfoDto vehicleInfo) {
this.vehicleInfo = vehicleInfo;
}
}

View File

@ -0,0 +1,45 @@
/**
* 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._1269.dto;
/**
* @author Filip Hrisafov
*/
public class VehicleImageDto {
private Integer pictureSize;
private String src;
public Integer getPictureSize() {
return pictureSize;
}
public void setPictureSize(Integer pictureSize) {
this.pictureSize = pictureSize;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
}

View File

@ -0,0 +1,68 @@
/**
* 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._1269.dto;
import java.util.List;
/**
* @author Filip Hrisafov
*/
public class VehicleInfoDto {
private String type;
private String name;
private Integer doors;
// make sure that mapping on images does not happen based on images mapping
private List<VehicleImageDto> images;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getDoors() {
return doors;
}
public void setDoors(Integer doors) {
this.doors = doors;
}
public List<VehicleImageDto> getImages() {
return images;
}
public void setImages(List<VehicleImageDto> images) {
this.images = images;
}
}

View File

@ -0,0 +1,40 @@
/**
* 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._1269.mapper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.ap.test.bugs._1269.dto.VehicleDto;
import org.mapstruct.ap.test.bugs._1269.model.Vehicle;
import org.mapstruct.factory.Mappers;
/**
* @author Filip Hrisafov
*/
@Mapper
public interface VehicleMapper {
VehicleMapper INSTANCE = Mappers.getMapper( VehicleMapper.class );
@Mappings({
@Mapping(target = "vehicleInfo", source = "vehicleTypeInfo"),
@Mapping(target = "vehicleInfo.images", source = "images")
})
VehicleDto map(Vehicle in);
}

View File

@ -0,0 +1,44 @@
/**
* 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._1269.model;
import java.util.List;
/**
* @author Filip Hrisafov
*/
public class Vehicle {
private final VehicleTypeInfo vehicleTypeInfo;
private final List<VehicleImage> images;
public Vehicle(VehicleTypeInfo vehicleTypeInfo, List<VehicleImage> images) {
this.vehicleTypeInfo = vehicleTypeInfo;
this.images = images;
}
public VehicleTypeInfo getVehicleTypeInfo() {
return vehicleTypeInfo;
}
public List<VehicleImage> getImages() {
return images;
}
}

View File

@ -0,0 +1,42 @@
/**
* 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._1269.model;
/**
* @author Filip Hrisafov
*/
public class VehicleImage {
private final Integer pictureSize;
private final String src;
public VehicleImage(Integer pictureSize, String src) {
this.pictureSize = pictureSize;
this.src = src;
}
public Integer getPictureSize() {
return pictureSize;
}
public String getSrc() {
return src;
}
}

View File

@ -0,0 +1,49 @@
/**
* 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._1269.model;
/**
* @author Filip Hrisafov
*/
public class VehicleTypeInfo {
private final String type;
private final String name;
private final Integer doors;
public VehicleTypeInfo(String type, String name, Integer doors) {
this.type = type;
this.name = name;
this.doors = doors;
}
public String getType() {
return type;
}
public String getName() {
return name;
}
public Integer getDoors() {
return doors;
}
}