This commit is contained in:
Gunnar Morling 2015-02-24 23:46:18 +01:00
parent ec614a6e25
commit bbeaa2117c
27 changed files with 96 additions and 104 deletions

View File

@ -31,8 +31,8 @@ import java.lang.annotation.Target;
*
* @author Sjaak Derksen
*/
@Target( ElementType.METHOD )
@Retention( RetentionPolicy.SOURCE )
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface BeanMapping {
/**
@ -42,7 +42,7 @@ public @interface BeanMapping {
*/
Class<?> resultType() default void.class;
/**
/**
* A qualifier can be specified to aid the selection process of a suitable factory method. This is useful in
* case multiple factory method (hand written of internal) qualify and result in an 'Ambiguous factory methods'
* error.

View File

@ -27,19 +27,19 @@ public enum CollectionMappingStrategy {
/**
* The setter of the target property will be used to propagate the value:
* {@code orderDto.setOrderLines( order.getOrderLines )}.
* {@code orderDto.setOrderLines(order.getOrderLines)}.
* <p>
* If no setter is available but a getter method, this will be used, under the assumption it has been initialized:
* {@code orderDto.getOrderLines().addAll( order.getOrderLines )}.
* {@code orderDto.getOrderLines().addAll(order.getOrderLines)}.
*/
ACCESSOR_ONLY,
/**
* If present, the setter of the target property will be used to propagate the value:
* {@code orderDto.setOrderLines( order.getOrderLines )}.
* {@code orderDto.setOrderLines(order.getOrderLines)}.
* <p>
* If no setter but and adder method is present, that adder will be invoked for each element of the source
* collection: {@code order.addOrderLine( orderLine() )}.
* collection: {@code order.addOrderLine(orderLine() )}.
* <p>
* If neither a setter nor an adder method but a getter for the target property is present, that getter will be
* used, assuming it returns an initialized collection: If no setter is available, MapStruct will first look for an

View File

@ -49,8 +49,8 @@ import java.lang.annotation.Target;
*
* @author Sjaak Derksen
*/
@Target( ElementType.METHOD )
@Retention( RetentionPolicy.SOURCE )
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface InheritConfiguration {
/**

View File

@ -37,8 +37,8 @@ import java.lang.annotation.Target;
*
* @author Sjaak Derksen
*/
@Target( ElementType.METHOD )
@Retention( RetentionPolicy.SOURCE )
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface InheritInverseConfiguration {
/**

View File

@ -79,7 +79,8 @@ public @interface MapMapping {
/**
* Specifies the type of the key to be used in the result of the mapping method in case multiple mapping
* methods qualify.
* *
*
*
* @return the resultType to select
*/
Class<?> keyTargetType() default void.class;
@ -87,7 +88,8 @@ public @interface MapMapping {
/**
* Specifies the type of the value to be used in the result of the mapping method in case multiple mapping
* methods qualify.
* *
*
*
* @return the resultType to select
*/
Class<?> valueTargetType() default void.class;

View File

@ -123,7 +123,7 @@ public @interface Mapper {
* applied, using {@link MappingInheritanceStrategy#EXPLICIT} as default.
*
* @return The strategy to use for applying {@code @Mapping} configurations of prototype methods in the interface
* specified with {@link #config()}.
* specified with {@link #config()}.
*/
MappingInheritanceStrategy mappingInheritanceStrategy() default MappingInheritanceStrategy.DEFAULT;
}

View File

@ -109,7 +109,7 @@ public @interface MapperConfig {
* If no strategy is configured, {@link MappingInheritanceStrategy#EXPLICIT} will be used as default.
*
* @return The strategy to use for applying {@code @Mapping} configurations of prototype methods in the interface
* annotated with this annotation.
* annotated with this annotation.
*/
MappingInheritanceStrategy mappingInheritanceStrategy()
default MappingInheritanceStrategy.EXPLICIT;

View File

@ -44,7 +44,7 @@ import java.lang.annotation.Target;
*
* @author Sjaak Derksen
*/
@Target( ElementType.ANNOTATION_TYPE )
@Retention( RetentionPolicy.CLASS )
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Qualifier {
}

View File

@ -55,6 +55,7 @@ public class Mappers {
*
* @param clazz The type of the mapper to return.
* @param <T> The type of the mapper to create.
*
* @return An instance of the given mapper type.
*/
public static <T> T getMapper(Class<T> clazz) {

View File

@ -45,7 +45,7 @@ public class MappingOptions {
/**
* @return the {@link Mapping}s configured for this method, keyed by target property name. Only for enum mapping
* methods a target will be mapped by several sources.
* methods a target will be mapped by several sources.
*/
public Map<String, List<Mapping>> getMappings() {
return mappings;
@ -73,7 +73,7 @@ public class MappingOptions {
/**
* @return the {@code true}, iff the options have been fully initialized by applying all available inheritance
* options
* options
*/
public boolean isFullyInitialized() {
return fullyInitialized;

View File

@ -412,7 +412,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
* per the source/target type and optionally the name given via {@code @InheritInverseConfiguration}).
*/
private MappingOptions getInverseMappingOptions(List<SourceMethod> rawMethods, SourceMethod method,
List<SourceMethod> initializingMethods, MapperConfiguration mapperConfig) {
List<SourceMethod> initializingMethods,
MapperConfiguration mapperConfig) {
SourceMethod resultMethod = null;
InheritInverseConfigurationPrism reversePrism = InheritInverseConfigurationPrism.getInstanceOn(
method.getExecutable()

View File

@ -29,8 +29,6 @@ import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.mapstruct.Mapper;
import org.mapstruct.MapperConfig;
import org.mapstruct.ap.option.ReportingPolicy;
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
import org.mapstruct.ap.prism.MapperConfigPrism;
@ -40,12 +38,12 @@ import org.mapstruct.ap.prism.NullValueMappingPrism;
import org.mapstruct.ap.prism.NullValueMappingStrategyPrism;
/**
* Provides an aggregated view to the settings given via {@link Mapper} and {@link MapperConfig} for a specific mapper
* class.
* Provides an aggregated view to the settings given via {@link org.mapstruct.Mapper} and
* {@link org.mapstruct.MapperConfig} for a specific mapper class.
* <p>
* Settings given via {@code Mapper} will generally take precedence over settings inherited from a referenced config
* class. The lists of referenced mappers given via {@link Mapper#uses()} and {@link MapperConfig#uses() } will be
* merged.
* class. The lists of referenced mappers given via {@link org.mapstruct.Mapper#uses()} and
* {@link org.mapstruct.MapperConfig#uses() } will be merged.
*
* @author Sjaak Derksen
*/

View File

@ -32,9 +32,9 @@ import org.mapstruct.ReportingPolicy;
unmappedTargetPolicy = ReportingPolicy.ERROR
)
public interface AutoInheritedConfig {
@Mappings( {
@Mapping( target = "primaryKey", source = "id" ),
@Mapping( target = "auditTrail", ignore = true )
} )
@Mappings({
@Mapping(target = "primaryKey", source = "id"),
@Mapping(target = "auditTrail", ignore = true)
})
BaseVehicleEntity baseDtoToEntity(BaseVehicleDto dto);
}

View File

@ -32,10 +32,10 @@ import org.mapstruct.ReportingPolicy;
unmappedTargetPolicy = ReportingPolicy.ERROR
)
public interface AutoInheritedDriverConfig {
@Mappings( {
@Mapping( target = "primaryKey", source = "dto.id" ),
@Mapping( target = "auditTrail", ignore = true ),
@Mapping( target = "driverName", source = "drv.name" )
} )
@Mappings({
@Mapping(target = "primaryKey", source = "dto.id"),
@Mapping(target = "auditTrail", ignore = true),
@Mapping(target = "driverName", source = "drv.name")
})
CarWithDriverEntity baseDtoToEntity(DriverDto drv, BaseVehicleDto dto);
}

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.test.inheritfromconfig;
/**
* @author Andreas Gudian
*
*/
public abstract class BaseVehicleDto {
private long id;

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.test.inheritfromconfig;
/**
* @author Andreas Gudian
*
*/
public abstract class BaseVehicleEntity {
private long primaryKey;

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.test.inheritfromconfig;
/**
* @author Andreas Gudian
*
*/
public class CarDto extends BaseVehicleDto {
private String colour;

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.test.inheritfromconfig;
/**
* @author Andreas Gudian
*
*/
public class CarEntity extends BaseVehicleEntity {
private String color;

View File

@ -28,7 +28,6 @@ import org.mapstruct.factory.Mappers;
/**
* @author Andreas Gudian
*
*/
@Mapper(
config = AutoInheritedConfig.class
@ -36,21 +35,21 @@ import org.mapstruct.factory.Mappers;
public interface CarMapperWithAutoInheritance {
CarMapperWithAutoInheritance INSTANCE = Mappers.getMapper( CarMapperWithAutoInheritance.class );
@Mapping( target = "color", source = "colour" )
@Mapping(target = "color", source = "colour")
CarEntity toCarEntity(CarDto carDto);
@InheritInverseConfiguration( name = "toCarEntity" )
@InheritInverseConfiguration(name = "toCarEntity")
CarDto toCarDto(CarEntity entity);
@Mappings( {
@Mapping( target = "color", source = "colour" ),
@Mapping( target = "auditTrail", constant = "fixed" )
} )
@Mappings({
@Mapping(target = "color", source = "colour"),
@Mapping(target = "auditTrail", constant = "fixed")
})
CarEntity toCarEntityWithFixedAuditTrail(CarDto carDto);
@Mapping( target = "color", source = "colour" )
@Mapping(target = "color", source = "colour")
void intoCarEntityOnItsOwn(CarDto carDto, @MappingTarget CarEntity entity);
@InheritConfiguration( name = "toCarEntity" )
@InheritConfiguration(name = "toCarEntity")
void intoCarEntity(CarDto carDto, @MappingTarget CarEntity entity);
}

View File

@ -27,7 +27,6 @@ import org.mapstruct.factory.Mappers;
/**
* @author Andreas Gudian
*
*/
@Mapper(
config = AutoInheritedConfig.class,
@ -36,14 +35,14 @@ import org.mapstruct.factory.Mappers;
public interface CarMapperWithExplicitInheritance {
CarMapperWithExplicitInheritance INSTANCE = Mappers.getMapper( CarMapperWithExplicitInheritance.class );
@InheritConfiguration( name = "baseDtoToEntity" )
@Mapping( target = "color", source = "colour" )
@InheritConfiguration(name = "baseDtoToEntity")
@Mapping(target = "color", source = "colour")
CarEntity toCarEntity(CarDto carDto);
@InheritInverseConfiguration( name = "toCarEntity" )
@InheritInverseConfiguration(name = "toCarEntity")
CarDto toCarDto(CarEntity entity);
@InheritConfiguration( name = "toCarEntity" )
@Mapping( target = "auditTrail", constant = "fixed" )
@InheritConfiguration(name = "toCarEntity")
@Mapping(target = "auditTrail", constant = "fixed")
CarEntity toCarEntityWithFixedAuditTrail(CarDto carDto);
}

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.test.inheritfromconfig;
/**
* @author Andreas Gudian
*
*/
public class CarWithDriverEntity extends CarEntity {
private String driverName;

View File

@ -24,7 +24,6 @@ import org.mapstruct.factory.Mappers;
/**
* @author Andreas Gudian
*
*/
@Mapper(
config = AutoInheritedDriverConfig.class
@ -32,6 +31,6 @@ import org.mapstruct.factory.Mappers;
public interface CarWithDriverMapperWithAutoInheritance {
CarWithDriverMapperWithAutoInheritance INSTANCE = Mappers.getMapper( CarWithDriverMapperWithAutoInheritance.class );
@Mapping( target = "color", source = "carDto.colour" )
@Mapping(target = "color", source = "carDto.colour")
CarWithDriverEntity toCarWithDriverEntity(CarDto carDto, DriverDto driverDto);
}

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.test.inheritfromconfig;
/**
* @author Andreas Gudian
*
*/
public class DriverDto {
private String name;

View File

@ -34,12 +34,12 @@ import org.mapstruct.ReportingPolicy;
unmappedTargetPolicy = ReportingPolicy.WARN
)
public interface Erroneous1Config {
@Mappings( {
@Mapping( target = "primaryKey", source = "id" ),
@Mapping( target = "auditTrail", ignore = true )
} )
@Mappings({
@Mapping(target = "primaryKey", source = "id"),
@Mapping(target = "auditTrail", ignore = true)
})
BaseVehicleEntity baseDtoToEntity(BaseVehicleDto dto);
@Mapping( target = "primaryKey", ignore = true )
@Mapping(target = "primaryKey", ignore = true)
BaseVehicleEntity anythingToEntity(Object anyting);
}

View File

@ -25,7 +25,6 @@ import org.mapstruct.factory.Mappers;
/**
* @author Andreas Gudian
*
*/
@Mapper(
config = Erroneous1Config.class
@ -33,12 +32,12 @@ import org.mapstruct.factory.Mappers;
public interface Erroneous1Mapper {
Erroneous1Mapper INSTANCE = Mappers.getMapper( Erroneous1Mapper.class );
@Mapping( target = "color", source = "colour" )
@Mapping(target = "color", source = "colour")
CarEntity toCarEntity(CarDto carDto);
@Mappings( {
@Mapping( target = "color", source = "colour" ),
@Mapping( target = "auditTrail", constant = "fixed" )
} )
@Mappings({
@Mapping(target = "color", source = "colour"),
@Mapping(target = "auditTrail", constant = "fixed")
})
CarEntity toCarEntityWithFixedAuditTrail(CarDto carDto);
}

View File

@ -27,7 +27,6 @@ import org.mapstruct.factory.Mappers;
/**
* @author Andreas Gudian
*
*/
@Mapper(
config = AutoInheritedConfig.class
@ -35,17 +34,17 @@ import org.mapstruct.factory.Mappers;
public interface Erroneous2Mapper {
Erroneous2Mapper INSTANCE = Mappers.getMapper( Erroneous2Mapper.class );
@InheritConfiguration( name = "toCarEntity2" )
@InheritConfiguration(name = "toCarEntity2")
CarEntity toCarEntity1(CarDto carDto);
@InheritConfiguration( name = "toCarEntity3" )
@InheritConfiguration(name = "toCarEntity3")
CarEntity toCarEntity2(CarDto carDto);
@InheritConfiguration( name = "toCarEntity1" )
@Mappings( {
@Mapping( target = "color", ignore = true ),
@Mapping( target = "auditTrail", ignore = true ),
@Mapping( target = "primaryKey", ignore = true )
} )
@InheritConfiguration(name = "toCarEntity1")
@Mappings({
@Mapping(target = "color", ignore = true),
@Mapping(target = "auditTrail", ignore = true),
@Mapping(target = "primaryKey", ignore = true)
})
void toCarEntity3(CarDto carDto, @MappingTarget CarEntity entity);
}

View File

@ -18,6 +18,8 @@
*/
package org.mapstruct.ap.test.inheritfromconfig;
import static org.fest.assertions.Assertions.assertThat;
import javax.tools.Diagnostic.Kind;
import org.junit.Test;
@ -29,22 +31,20 @@ import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.fest.assertions.Assertions.assertThat;
/**
* @author Andreas Gudian
*
*/
@RunWith( AnnotationProcessorTestRunner.class )
@WithClasses( {
@RunWith(AnnotationProcessorTestRunner.class)
@WithClasses({
BaseVehicleDto.class,
BaseVehicleEntity.class,
CarDto.class,
CarEntity.class,
CarMapperWithAutoInheritance.class,
CarMapperWithExplicitInheritance.class,
AutoInheritedConfig.class } )
@IssueKey( "168" )
AutoInheritedConfig.class
})
@IssueKey("168")
public class InheritFromConfigTest {
@Test
@ -145,11 +145,12 @@ public class InheritFromConfigTest {
}
@Test
@WithClasses( {
@WithClasses({
DriverDto.class,
CarWithDriverEntity.class,
CarWithDriverMapperWithAutoInheritance.class,
AutoInheritedDriverConfig.class } )
AutoInheritedDriverConfig.class
})
public void autoInheritedFromMultipleSources() {
CarDto carDto = newTestDto();
DriverDto driverDto = new DriverDto();
@ -163,32 +164,32 @@ public class InheritFromConfigTest {
}
@Test
@WithClasses( { Erroneous1Mapper.class, Erroneous1Config.class } )
@WithClasses({ Erroneous1Mapper.class, Erroneous1Config.class })
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic( type = Erroneous1Mapper.class,
@Diagnostic(type = Erroneous1Mapper.class,
kind = Kind.ERROR,
line = 37,
line = 36,
messageRegExp = "More than one configuration prototype method is applicable. Use @InheritConfiguration"
+ " to select one of them explicitly:"
+ " .*BaseVehicleEntity baseDtoToEntity\\(.*BaseVehicleDto dto\\),"
+ " .*BaseVehicleEntity anythingToEntity\\(java.lang.Object anyting\\)\\." ),
@Diagnostic( type = Erroneous1Mapper.class,
+ " .*BaseVehicleEntity anythingToEntity\\(java.lang.Object anyting\\)\\."),
@Diagnostic(type = Erroneous1Mapper.class,
kind = Kind.WARNING,
line = 37,
messageRegExp = "Unmapped target properties: \"auditTrail, primaryKey\"\\." ),
@Diagnostic( type = Erroneous1Mapper.class,
line = 36,
messageRegExp = "Unmapped target properties: \"auditTrail, primaryKey\"\\."),
@Diagnostic(type = Erroneous1Mapper.class,
kind = Kind.ERROR,
line = 43,
line = 42,
messageRegExp = "More than one configuration prototype method is applicable. Use @InheritConfiguration"
+ " to select one of them explicitly:"
+ " .*BaseVehicleEntity baseDtoToEntity\\(.*BaseVehicleDto dto\\),"
+ " .*BaseVehicleEntity anythingToEntity\\(java.lang.Object anyting\\)\\." ),
@Diagnostic( type = Erroneous1Mapper.class,
+ " .*BaseVehicleEntity anythingToEntity\\(java.lang.Object anyting\\)\\."),
@Diagnostic(type = Erroneous1Mapper.class,
kind = Kind.WARNING,
line = 43,
messageRegExp = "Unmapped target property: \"primaryKey\"\\." )
line = 42,
messageRegExp = "Unmapped target property: \"primaryKey\"\\.")
}
)
public void erroneous1MultiplePrototypeMethodsMatch() {
@ -196,18 +197,18 @@ public class InheritFromConfigTest {
}
@Test
@WithClasses( { Erroneous2Mapper.class } )
@WithClasses({ Erroneous2Mapper.class })
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic( type = Erroneous2Mapper.class,
@Diagnostic(type = Erroneous2Mapper.class,
kind = Kind.ERROR,
line = 39,
line = 38,
messageRegExp = "Cycle detected while evaluating inherited configurations. Inheritance path:"
+ " .*CarEntity toCarEntity1\\(.*CarDto carDto\\)"
+ " -> .*CarEntity toCarEntity2\\(.*CarDto carDto\\)"
+ " -> void toCarEntity3\\(.*CarDto carDto, @MappingTarget .*CarEntity entity\\)"
+ " -> .*CarEntity toCarEntity1\\(.*CarDto carDto\\)" )
+ " -> .*CarEntity toCarEntity1\\(.*CarDto carDto\\)")
}
)
public void erroneous2InheritanceCycle() {