mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1792 Annotation processor option for default injection strategy
This commit is contained in:
parent
d018aed251
commit
750ce48023
@ -254,6 +254,19 @@ Supported values are:
|
|||||||
If a component model is given for a specific mapper via `@Mapper#componentModel()`, the value from the annotation takes precedence.
|
If a component model is given for a specific mapper via `@Mapper#componentModel()`, the value from the annotation takes precedence.
|
||||||
|`default`
|
|`default`
|
||||||
|
|
||||||
|
|`mapstruct.defaultInjectionStrategy`
|
||||||
|
| The type of the injection in mapper via parameter `uses`. This is only used on annotated based component models
|
||||||
|
such as CDI, Spring and JSR 330.
|
||||||
|
|
||||||
|
Supported values are:
|
||||||
|
|
||||||
|
* `field`: dependencies will be injected in fields
|
||||||
|
* `constructor`: will be generated constructor. Dependencies will be injected via constructor.
|
||||||
|
|
||||||
|
When CDI `componentModel` a default constructor will also be generated.
|
||||||
|
If a injection strategy is given for a specific mapper via `@Mapper#injectionStrategy()`, the value from the annotation takes precedence over the option.
|
||||||
|
|`field`
|
||||||
|
|
||||||
|`mapstruct.unmappedTargetPolicy`
|
|`mapstruct.unmappedTargetPolicy`
|
||||||
|The default reporting policy to be applied in case an attribute of the target object of a mapping method is not populated with a source value.
|
|The default reporting policy to be applied in case an attribute of the target object of a mapping method is not populated with a source value.
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ public interface CarMapper {
|
|||||||
The generated mapper will inject all classes defined in the **uses** attribute.
|
The generated mapper will inject all classes defined in the **uses** attribute.
|
||||||
When `InjectionStrategy#CONSTRUCTOR` is used, the constructor will have the appropriate annotation and the fields won't.
|
When `InjectionStrategy#CONSTRUCTOR` is used, the constructor will have the appropriate annotation and the fields won't.
|
||||||
When `InjectionStrategy#FIELD` is used, the annotation is on the field itself.
|
When `InjectionStrategy#FIELD` is used, the annotation is on the field itself.
|
||||||
For now, the default injection strategy is field injection.
|
For now, the default injection strategy is field injection, but it can be configured with <<configuration-options>>.
|
||||||
It is recommended to use constructor injection to simplify testing.
|
It is recommended to use constructor injection to simplify testing.
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
|
@ -83,6 +83,7 @@ import static javax.lang.model.element.ElementKind.CLASS;
|
|||||||
MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT,
|
MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT,
|
||||||
MappingProcessor.UNMAPPED_TARGET_POLICY,
|
MappingProcessor.UNMAPPED_TARGET_POLICY,
|
||||||
MappingProcessor.DEFAULT_COMPONENT_MODEL,
|
MappingProcessor.DEFAULT_COMPONENT_MODEL,
|
||||||
|
MappingProcessor.DEFAULT_INJECTION_STRATEGY,
|
||||||
MappingProcessor.VERBOSE
|
MappingProcessor.VERBOSE
|
||||||
})
|
})
|
||||||
public class MappingProcessor extends AbstractProcessor {
|
public class MappingProcessor extends AbstractProcessor {
|
||||||
@ -97,6 +98,7 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
"mapstruct.suppressGeneratorVersionInfoComment";
|
"mapstruct.suppressGeneratorVersionInfoComment";
|
||||||
protected static final String UNMAPPED_TARGET_POLICY = "mapstruct.unmappedTargetPolicy";
|
protected static final String UNMAPPED_TARGET_POLICY = "mapstruct.unmappedTargetPolicy";
|
||||||
protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel";
|
protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel";
|
||||||
|
protected static final String DEFAULT_INJECTION_STRATEGY = "mapstruct.defaultInjectionStrategy";
|
||||||
protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile";
|
protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile";
|
||||||
protected static final String VERBOSE = "mapstruct.verbose";
|
protected static final String VERBOSE = "mapstruct.verbose";
|
||||||
|
|
||||||
@ -136,6 +138,7 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ),
|
Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ),
|
||||||
unmappedTargetPolicy != null ? ReportingPolicyPrism.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
|
unmappedTargetPolicy != null ? ReportingPolicyPrism.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
|
||||||
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
|
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
|
||||||
|
processingEnv.getOptions().get( DEFAULT_INJECTION_STRATEGY ),
|
||||||
Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ),
|
Boolean.valueOf( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ),
|
||||||
Boolean.valueOf( processingEnv.getOptions().get( VERBOSE ) )
|
Boolean.valueOf( processingEnv.getOptions().get( VERBOSE ) )
|
||||||
);
|
);
|
||||||
|
@ -19,15 +19,18 @@ public class Options {
|
|||||||
private final ReportingPolicyPrism unmappedTargetPolicy;
|
private final ReportingPolicyPrism unmappedTargetPolicy;
|
||||||
private final boolean alwaysGenerateSpi;
|
private final boolean alwaysGenerateSpi;
|
||||||
private final String defaultComponentModel;
|
private final String defaultComponentModel;
|
||||||
|
private final String defaultInjectionStrategy;
|
||||||
private final boolean verbose;
|
private final boolean verbose;
|
||||||
|
|
||||||
public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment,
|
public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment,
|
||||||
ReportingPolicyPrism unmappedTargetPolicy,
|
ReportingPolicyPrism unmappedTargetPolicy,
|
||||||
String defaultComponentModel, boolean alwaysGenerateSpi, boolean verbose) {
|
String defaultComponentModel, String defaultInjectionStrategy,
|
||||||
|
boolean alwaysGenerateSpi, boolean verbose) {
|
||||||
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
|
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
|
||||||
this.suppressGeneratorVersionComment = suppressGeneratorVersionComment;
|
this.suppressGeneratorVersionComment = suppressGeneratorVersionComment;
|
||||||
this.unmappedTargetPolicy = unmappedTargetPolicy;
|
this.unmappedTargetPolicy = unmappedTargetPolicy;
|
||||||
this.defaultComponentModel = defaultComponentModel;
|
this.defaultComponentModel = defaultComponentModel;
|
||||||
|
this.defaultInjectionStrategy = defaultInjectionStrategy;
|
||||||
this.alwaysGenerateSpi = alwaysGenerateSpi;
|
this.alwaysGenerateSpi = alwaysGenerateSpi;
|
||||||
this.verbose = verbose;
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
@ -48,6 +51,10 @@ public class Options {
|
|||||||
return defaultComponentModel;
|
return defaultComponentModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDefaultInjectionStrategy() {
|
||||||
|
return defaultInjectionStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAlwaysGenerateSpi() {
|
public boolean isAlwaysGenerateSpi() {
|
||||||
return alwaysGenerateSpi;
|
return alwaysGenerateSpi;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
|
|||||||
MapperConfiguration mapperConfiguration = MapperConfiguration.getInstanceOn( mapperTypeElement );
|
MapperConfiguration mapperConfiguration = MapperConfiguration.getInstanceOn( mapperTypeElement );
|
||||||
|
|
||||||
String componentModel = mapperConfiguration.componentModel( context.getOptions() );
|
String componentModel = mapperConfiguration.componentModel( context.getOptions() );
|
||||||
InjectionStrategyPrism injectionStrategy = mapperConfiguration.getInjectionStrategy();
|
InjectionStrategyPrism injectionStrategy = mapperConfiguration.getInjectionStrategy( context.getOptions() );
|
||||||
|
|
||||||
if ( !getComponentModelIdentifier().equalsIgnoreCase( componentModel ) ) {
|
if ( !getComponentModelIdentifier().equalsIgnoreCase( componentModel ) ) {
|
||||||
return mapper;
|
return mapper;
|
||||||
|
@ -202,13 +202,21 @@ public class MapperConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InjectionStrategyPrism getInjectionStrategy() {
|
public InjectionStrategyPrism getInjectionStrategy(Options options) {
|
||||||
if ( mapperConfigPrism != null && mapperPrism.values.injectionStrategy() == null ) {
|
if ( mapperPrism.values.injectionStrategy() != null ) {
|
||||||
return InjectionStrategyPrism.valueOf( mapperConfigPrism.injectionStrategy() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return InjectionStrategyPrism.valueOf( mapperPrism.injectionStrategy() );
|
return InjectionStrategyPrism.valueOf( mapperPrism.injectionStrategy() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( mapperConfigPrism != null && mapperConfigPrism.values.injectionStrategy() != null ) {
|
||||||
|
return InjectionStrategyPrism.valueOf( mapperConfigPrism.injectionStrategy() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( options.getDefaultInjectionStrategy() != null ) {
|
||||||
|
return InjectionStrategyPrism.valueOf( options.getDefaultInjectionStrategy().toUpperCase() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall back to default defined in the annotation
|
||||||
|
return InjectionStrategyPrism.valueOf( mapperPrism.injectionStrategy() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public NullValueMappingStrategyPrism getNullValueMappingStrategy() {
|
public NullValueMappingStrategyPrism getNullValueMappingStrategy() {
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.jsr330._default;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = "jsr330", uses = GenderJsr330DefaultCompileOptionFieldMapper.class)
|
||||||
|
public interface CustomerJsr330DefaultCompileOptionFieldMapper {
|
||||||
|
|
||||||
|
CustomerDto asTarget(CustomerEntity customerEntity);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.jsr330._default;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.ValueMapping;
|
||||||
|
import org.mapstruct.ValueMappings;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.Gender;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = "jsr330")
|
||||||
|
public interface GenderJsr330DefaultCompileOptionFieldMapper {
|
||||||
|
|
||||||
|
@ValueMappings({
|
||||||
|
@ValueMapping(source = "MALE", target = "M"),
|
||||||
|
@ValueMapping(source = "FEMALE", target = "F")
|
||||||
|
})
|
||||||
|
GenderDto mapToDto(Gender gender);
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.jsr330._default;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.Gender;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
import org.mapstruct.ap.testutil.runner.GeneratedSource;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static java.lang.System.lineSeparator;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test field injection for component model jsr330.
|
||||||
|
* Default value option mapstruct.defaultInjectionStrategy is "field"
|
||||||
|
*
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
CustomerDto.class,
|
||||||
|
CustomerEntity.class,
|
||||||
|
Gender.class,
|
||||||
|
GenderDto.class,
|
||||||
|
CustomerJsr330DefaultCompileOptionFieldMapper.class,
|
||||||
|
GenderJsr330DefaultCompileOptionFieldMapper.class
|
||||||
|
})
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
@ComponentScan(basePackageClasses = CustomerJsr330DefaultCompileOptionFieldMapper.class)
|
||||||
|
@Configuration
|
||||||
|
public class Jsr330DefaultCompileOptionFieldMapperTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final GeneratedSource generatedSource = new GeneratedSource();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Named
|
||||||
|
private CustomerJsr330DefaultCompileOptionFieldMapper customerMapper;
|
||||||
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void springUp() {
|
||||||
|
context = new AnnotationConfigApplicationContext( getClass() );
|
||||||
|
context.getAutowireCapableBeanFactory().autowireBean( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void springDown() {
|
||||||
|
if ( context != null ) {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldConvertToTarget() {
|
||||||
|
// given
|
||||||
|
CustomerEntity customerEntity = new CustomerEntity();
|
||||||
|
customerEntity.setName( "Samuel" );
|
||||||
|
customerEntity.setGender( Gender.MALE );
|
||||||
|
|
||||||
|
// when
|
||||||
|
CustomerDto customerDto = customerMapper.asTarget( customerEntity );
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat( customerDto ).isNotNull();
|
||||||
|
assertThat( customerDto.getName() ).isEqualTo( "Samuel" );
|
||||||
|
assertThat( customerDto.getGender() ).isEqualTo( GenderDto.M );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldHaveFieldInjection() {
|
||||||
|
generatedSource.forMapper( CustomerJsr330DefaultCompileOptionFieldMapper.class )
|
||||||
|
.content()
|
||||||
|
.contains( "@Inject" + lineSeparator() + " private GenderJsr330DefaultCompileOptionFieldMapper" )
|
||||||
|
.doesNotContain( "public CustomerJsr330DefaultCompileOptionFieldMapperImpl(" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.jsr330.compileoptionconstructor;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@Mapper( componentModel = "jsr330",
|
||||||
|
uses = GenderJsr330CompileOptionConstructorMapper.class )
|
||||||
|
public interface CustomerJsr330CompileOptionConstructorMapper {
|
||||||
|
|
||||||
|
@Mapping(source = "gender", target = "gender")
|
||||||
|
CustomerDto asTarget(CustomerEntity customerEntity);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.jsr330.compileoptionconstructor;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.ValueMapping;
|
||||||
|
import org.mapstruct.ValueMappings;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.Gender;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = "jsr330")
|
||||||
|
public interface GenderJsr330CompileOptionConstructorMapper {
|
||||||
|
|
||||||
|
@ValueMappings({
|
||||||
|
@ValueMapping(source = "MALE", target = "M"),
|
||||||
|
@ValueMapping(source = "FEMALE", target = "F")
|
||||||
|
})
|
||||||
|
GenderDto mapToDto(Gender gender);
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.jsr330.compileoptionconstructor;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.Gender;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
import org.mapstruct.ap.testutil.runner.GeneratedSource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static java.lang.System.lineSeparator;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test constructor injection for component model jsr330 with compile option
|
||||||
|
* mapstruct.defaultInjectionStrategy=constructor
|
||||||
|
*
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
CustomerDto.class,
|
||||||
|
CustomerEntity.class,
|
||||||
|
Gender.class,
|
||||||
|
GenderDto.class,
|
||||||
|
CustomerJsr330CompileOptionConstructorMapper.class,
|
||||||
|
GenderJsr330CompileOptionConstructorMapper.class
|
||||||
|
})
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
@ProcessorOption( name = "mapstruct.defaultInjectionStrategy", value = "constructor")
|
||||||
|
@ComponentScan(basePackageClasses = CustomerJsr330CompileOptionConstructorMapper.class)
|
||||||
|
@Configuration
|
||||||
|
public class Jsr330CompileOptionConstructorMapperTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final GeneratedSource generatedSource = new GeneratedSource();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomerJsr330CompileOptionConstructorMapper customerMapper;
|
||||||
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void springUp() {
|
||||||
|
context = new AnnotationConfigApplicationContext( getClass() );
|
||||||
|
context.getAutowireCapableBeanFactory().autowireBean( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void springDown() {
|
||||||
|
if ( context != null ) {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldConvertToTarget() {
|
||||||
|
// given
|
||||||
|
CustomerEntity customerEntity = new CustomerEntity();
|
||||||
|
customerEntity.setName( "Samuel" );
|
||||||
|
customerEntity.setGender( Gender.MALE );
|
||||||
|
|
||||||
|
// when
|
||||||
|
CustomerDto customerDto = customerMapper.asTarget( customerEntity );
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat( customerDto ).isNotNull();
|
||||||
|
assertThat( customerDto.getName() ).isEqualTo( "Samuel" );
|
||||||
|
assertThat( customerDto.getGender() ).isEqualTo( GenderDto.M );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldHaveConstructorInjectionFromCompileOption() {
|
||||||
|
generatedSource.forMapper( CustomerJsr330CompileOptionConstructorMapper.class )
|
||||||
|
.content()
|
||||||
|
.contains( "private final GenderJsr330CompileOptionConstructorMapper" )
|
||||||
|
.contains( "@Inject" + lineSeparator() +
|
||||||
|
" public CustomerJsr330CompileOptionConstructorMapperImpl" +
|
||||||
|
"(GenderJsr330CompileOptionConstructorMapper" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.spring.compileoptionconstructor;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerRecordDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerRecordEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = "spring",
|
||||||
|
uses = { CustomerSpringCompileOptionConstructorMapper.class, GenderSpringCompileOptionConstructorMapper.class },
|
||||||
|
disableSubMappingMethodsGeneration = true)
|
||||||
|
public interface CustomerRecordSpringCompileOptionConstructorMapper {
|
||||||
|
|
||||||
|
CustomerRecordDto asTarget(CustomerRecordEntity customerRecordEntity);
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.spring.compileoptionconstructor;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@Mapper( componentModel = "spring",
|
||||||
|
uses = GenderSpringCompileOptionConstructorMapper.class)
|
||||||
|
public interface CustomerSpringCompileOptionConstructorMapper {
|
||||||
|
|
||||||
|
@Mapping( source = "gender", target = "gender" )
|
||||||
|
CustomerDto asTarget(CustomerEntity customerEntity);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.spring.compileoptionconstructor;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.ValueMapping;
|
||||||
|
import org.mapstruct.ValueMappings;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.Gender;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = "spring")
|
||||||
|
public interface GenderSpringCompileOptionConstructorMapper {
|
||||||
|
|
||||||
|
@ValueMappings({
|
||||||
|
@ValueMapping(source = "MALE", target = "M"),
|
||||||
|
@ValueMapping(source = "FEMALE", target = "F")
|
||||||
|
})
|
||||||
|
GenderDto mapToDto(Gender gender);
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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.injectionstrategy.spring.compileoptionconstructor;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerRecordDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerRecordEntity;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.Gender;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
import org.mapstruct.ap.testutil.runner.GeneratedSource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static java.lang.System.lineSeparator;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test constructor injection for component model spring with
|
||||||
|
* compile option mapstruct.defaultInjectStrategy=constructor
|
||||||
|
*
|
||||||
|
* @author Andrei Arlou
|
||||||
|
*/
|
||||||
|
@WithClasses( {
|
||||||
|
CustomerRecordDto.class,
|
||||||
|
CustomerRecordEntity.class,
|
||||||
|
CustomerDto.class,
|
||||||
|
CustomerEntity.class,
|
||||||
|
Gender.class,
|
||||||
|
GenderDto.class,
|
||||||
|
CustomerRecordSpringCompileOptionConstructorMapper.class,
|
||||||
|
CustomerSpringCompileOptionConstructorMapper.class,
|
||||||
|
GenderSpringCompileOptionConstructorMapper.class
|
||||||
|
} )
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
@ProcessorOption( name = "mapstruct.defaultInjectionStrategy", value = "constructor")
|
||||||
|
@ComponentScan(basePackageClasses = CustomerSpringCompileOptionConstructorMapper.class)
|
||||||
|
@Configuration
|
||||||
|
public class SpringCompileOptionConstructorMapperTest {
|
||||||
|
|
||||||
|
private static TimeZone originalTimeZone;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final GeneratedSource generatedSource = new GeneratedSource();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomerRecordSpringCompileOptionConstructorMapper customerRecordMapper;
|
||||||
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setDefaultTimeZoneToCet() {
|
||||||
|
originalTimeZone = TimeZone.getDefault();
|
||||||
|
TimeZone.setDefault( TimeZone.getTimeZone( "Europe/Berlin" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void restoreOriginalTimeZone() {
|
||||||
|
TimeZone.setDefault( originalTimeZone );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void springUp() {
|
||||||
|
context = new AnnotationConfigApplicationContext( getClass() );
|
||||||
|
context.getAutowireCapableBeanFactory().autowireBean( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void springDown() {
|
||||||
|
if ( context != null ) {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldConvertToTarget() throws Exception {
|
||||||
|
// given
|
||||||
|
CustomerEntity customerEntity = new CustomerEntity();
|
||||||
|
customerEntity.setName( "Samuel" );
|
||||||
|
customerEntity.setGender( Gender.MALE );
|
||||||
|
CustomerRecordEntity customerRecordEntity = new CustomerRecordEntity();
|
||||||
|
customerRecordEntity.setCustomer( customerEntity );
|
||||||
|
customerRecordEntity.setRegistrationDate( createDate( "31-08-1982 10:20:56" ) );
|
||||||
|
|
||||||
|
// when
|
||||||
|
CustomerRecordDto customerRecordDto = customerRecordMapper.asTarget( customerRecordEntity );
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat( customerRecordDto ).isNotNull();
|
||||||
|
assertThat( customerRecordDto.getCustomer() ).isNotNull();
|
||||||
|
assertThat( customerRecordDto.getCustomer().getName() ).isEqualTo( "Samuel" );
|
||||||
|
assertThat( customerRecordDto.getCustomer().getGender() ).isEqualTo( GenderDto.M );
|
||||||
|
assertThat( customerRecordDto.getRegistrationDate() ).isNotNull();
|
||||||
|
assertThat( customerRecordDto.getRegistrationDate().toString() ).isEqualTo( "1982-08-31T10:20:56.000+02:00" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date createDate(String date) throws ParseException {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat( "dd-M-yyyy hh:mm:ss" );
|
||||||
|
return sdf.parse( date );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldConstructorInjectionFromCompileOption() {
|
||||||
|
generatedSource.forMapper( CustomerSpringCompileOptionConstructorMapper.class )
|
||||||
|
.content()
|
||||||
|
.contains( "private final GenderSpringCompileOptionConstructorMapper" )
|
||||||
|
.contains( "@Autowired" + lineSeparator() +
|
||||||
|
" public CustomerSpringCompileOptionConstructorMapperImpl" +
|
||||||
|
"(GenderSpringCompileOptionConstructorMapper" );
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user