mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#3331 Do not handle defined mappings if the result type is abstract due to runtime exception subclass exhaustive strategy (#3487)
This commit is contained in:
parent
8191c850e0
commit
ca1fd0d85d
@ -284,11 +284,16 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
|
|
||||||
initializeMappingReferencesIfNeeded( resultTypeToMap );
|
initializeMappingReferencesIfNeeded( resultTypeToMap );
|
||||||
|
|
||||||
|
boolean shouldHandledDefinedMappings = shouldHandledDefinedMappings( resultTypeToMap );
|
||||||
|
|
||||||
|
|
||||||
|
if ( shouldHandledDefinedMappings ) {
|
||||||
// map properties with mapping
|
// map properties with mapping
|
||||||
boolean mappingErrorOccurred = handleDefinedMappings( resultTypeToMap );
|
boolean mappingErrorOccurred = handleDefinedMappings( resultTypeToMap );
|
||||||
if ( mappingErrorOccurred ) {
|
if ( mappingErrorOccurred ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean applyImplicitMappings = !mappingReferences.isRestrictToDefinedMappings();
|
boolean applyImplicitMappings = !mappingReferences.isRestrictToDefinedMappings();
|
||||||
if ( applyImplicitMappings ) {
|
if ( applyImplicitMappings ) {
|
||||||
@ -1045,6 +1050,36 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
return (List<AnnotationValue>) av.getValue();
|
return (List<AnnotationValue>) av.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether defined mappings should be handled on the result type.
|
||||||
|
* They should be, if any of the following is true:
|
||||||
|
* <ul>
|
||||||
|
* <li>The {@code resultTypeToMap} is not abstract</li>
|
||||||
|
* <li>There is a factory method</li>
|
||||||
|
* <li>The method is an update method</li>
|
||||||
|
* </ul>
|
||||||
|
* Otherwise, it means that we have reached this because subclass mappings are being used
|
||||||
|
* and the chosen strategy is runtime exception.
|
||||||
|
*
|
||||||
|
* @param resultTypeToMap the type in which the defined target properties are defined
|
||||||
|
* @return {@code true} if defined mappings should be handled for the result type, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
private boolean shouldHandledDefinedMappings(Type resultTypeToMap) {
|
||||||
|
if ( !resultTypeToMap.isAbstract() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( hasFactoryMethod ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( method.isUpdateMethod() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates over all defined mapping methods ({@code @Mapping(s)}), either directly given or inherited from the
|
* Iterates over all defined mapping methods ({@code @Mapping(s)}), either directly given or inherited from the
|
||||||
* inverse mapping method.
|
* inverse mapping method.
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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._3331;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.SubclassExhaustiveStrategy;
|
||||||
|
import org.mapstruct.SubclassMapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper(subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION)
|
||||||
|
public interface Issue3331Mapper {
|
||||||
|
|
||||||
|
Issue3331Mapper INSTANCE = Mappers.getMapper( Issue3331Mapper.class );
|
||||||
|
|
||||||
|
@SubclassMapping(source = Vehicle.Car.class, target = VehicleDto.Car.class)
|
||||||
|
@SubclassMapping(source = Vehicle.Motorbike.class, target = VehicleDto.Motorbike.class)
|
||||||
|
@Mapping(target = "name", constant = "noname")
|
||||||
|
VehicleDto map(Vehicle vehicle);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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._3331;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@IssueKey("3331")
|
||||||
|
@WithClasses({
|
||||||
|
Issue3331Mapper.class,
|
||||||
|
Vehicle.class,
|
||||||
|
VehicleDto.class,
|
||||||
|
})
|
||||||
|
class Issue3331Test {
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
void shouldCorrectCompileAndThrowExceptionOnRuntime() {
|
||||||
|
VehicleDto target = Issue3331Mapper.INSTANCE.map( new Vehicle.Car( "Test car", 4 ) );
|
||||||
|
|
||||||
|
assertThat( target.getName() ).isEqualTo( "noname" );
|
||||||
|
assertThat( target )
|
||||||
|
.isInstanceOfSatisfying( VehicleDto.Car.class, car -> {
|
||||||
|
assertThat( car.getNumOfDoors() ).isEqualTo( 4 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
target = Issue3331Mapper.INSTANCE.map( new Vehicle.Motorbike( "Test bike", true ) );
|
||||||
|
|
||||||
|
assertThat( target.getName() ).isEqualTo( "noname" );
|
||||||
|
assertThat( target )
|
||||||
|
.isInstanceOfSatisfying( VehicleDto.Motorbike.class, bike -> {
|
||||||
|
assertThat( bike.isAllowedForMinor() ).isTrue();
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertThatThrownBy( () -> Issue3331Mapper.INSTANCE.map( new Vehicle.Truck( "Test truck", 3 ) ) )
|
||||||
|
.isInstanceOf( IllegalArgumentException.class )
|
||||||
|
.hasMessage( "Not all subclasses are supported for this mapping. Missing for " + Vehicle.Truck.class );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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._3331;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public abstract class Vehicle {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
protected Vehicle(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Car extends Vehicle {
|
||||||
|
|
||||||
|
private final int numOfDoors;
|
||||||
|
|
||||||
|
public Car(String name, int numOfDoors) {
|
||||||
|
super( name );
|
||||||
|
this.numOfDoors = numOfDoors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumOfDoors() {
|
||||||
|
return numOfDoors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Motorbike extends Vehicle {
|
||||||
|
|
||||||
|
private final boolean allowedForMinor;
|
||||||
|
|
||||||
|
public Motorbike(String name, boolean allowedForMinor) {
|
||||||
|
super( name );
|
||||||
|
this.allowedForMinor = allowedForMinor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowedForMinor() {
|
||||||
|
return allowedForMinor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Truck extends Vehicle {
|
||||||
|
|
||||||
|
private final int numOfAxis;
|
||||||
|
|
||||||
|
public Truck(String name, int numOfAxis) {
|
||||||
|
super( name );
|
||||||
|
this.numOfAxis = numOfAxis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumOfAxis() {
|
||||||
|
return numOfAxis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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._3331;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public abstract class VehicleDto {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
protected VehicleDto(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Car extends VehicleDto {
|
||||||
|
|
||||||
|
private final int numOfDoors;
|
||||||
|
|
||||||
|
public Car(String name, int numOfDoors) {
|
||||||
|
super( name );
|
||||||
|
this.numOfDoors = numOfDoors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumOfDoors() {
|
||||||
|
return numOfDoors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Motorbike extends VehicleDto {
|
||||||
|
|
||||||
|
private final boolean allowedForMinor;
|
||||||
|
|
||||||
|
public Motorbike(String name, boolean allowedForMinor) {
|
||||||
|
super( name );
|
||||||
|
this.allowedForMinor = allowedForMinor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowedForMinor() {
|
||||||
|
return allowedForMinor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user