mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#3229: Implement InjectionStrategy.SETTER
This commit is contained in:
parent
230e84efd1
commit
0460c373c0
@ -10,6 +10,7 @@ package org.mapstruct;
|
|||||||
* JSR330 / Jakarta.
|
* JSR330 / Jakarta.
|
||||||
*
|
*
|
||||||
* @author Kevin Grüneberg
|
* @author Kevin Grüneberg
|
||||||
|
* @author Lucas Resch
|
||||||
*/
|
*/
|
||||||
public enum InjectionStrategy {
|
public enum InjectionStrategy {
|
||||||
|
|
||||||
@ -17,5 +18,8 @@ public enum InjectionStrategy {
|
|||||||
FIELD,
|
FIELD,
|
||||||
|
|
||||||
/** Annotations are written on the constructor **/
|
/** Annotations are written on the constructor **/
|
||||||
CONSTRUCTOR
|
CONSTRUCTOR,
|
||||||
|
|
||||||
|
/** A dedicated setter method is created */
|
||||||
|
SETTER
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ A mapper which uses other mapper classes (see <<invoking-other-mappers>>) will o
|
|||||||
[[injection-strategy]]
|
[[injection-strategy]]
|
||||||
=== Injection strategy
|
=== Injection strategy
|
||||||
|
|
||||||
When using <<using-dependency-injection,dependency injection>>, you can choose between field and constructor injection.
|
When using <<using-dependency-injection,dependency injection>>, you can choose between constructor, field, or setter injection.
|
||||||
This can be done by either providing the injection strategy via `@Mapper` or `@MapperConfig` annotation.
|
This can be done by either providing the injection strategy via `@Mapper` or `@MapperConfig` annotation.
|
||||||
|
|
||||||
.Using constructor injection
|
.Using constructor injection
|
||||||
@ -120,9 +120,13 @@ public interface CarMapper {
|
|||||||
The generated mapper will inject classes defined in the **uses** attribute if MapStruct has detected that it needs to use an instance of it for a mapping.
|
The generated mapper will inject classes defined in the **uses** attribute if MapStruct has detected that it needs to use an instance of it for a mapping.
|
||||||
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.
|
||||||
|
When `InjectionStrategy#SETTER` is used the annotation is on a generated setter method.
|
||||||
For now, the default injection strategy is field injection, but it can be configured with <<configuration-options>>.
|
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.
|
||||||
|
|
||||||
|
When you define mappers in Spring with circular dependencies compilation may fail.
|
||||||
|
In that case utilize the `InjectionStrategy#SETTER` strategy.
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
For abstract classes or decorators setter injection should be used.
|
For abstract classes or decorators setter injection should be used.
|
||||||
|
@ -13,5 +13,6 @@ package org.mapstruct.ap.internal.gem;
|
|||||||
public enum InjectionStrategyGem {
|
public enum InjectionStrategyGem {
|
||||||
|
|
||||||
FIELD,
|
FIELD,
|
||||||
CONSTRUCTOR;
|
CONSTRUCTOR,
|
||||||
|
SETTER;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.internal.model;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.internal.model.common.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lucas Resch
|
||||||
|
*/
|
||||||
|
public class AnnotatedSetter extends GeneratedTypeMethod {
|
||||||
|
|
||||||
|
private final Field field;
|
||||||
|
private final Collection<Annotation> methodAnnotations;
|
||||||
|
private final Collection<Annotation> parameterAnnotations;
|
||||||
|
|
||||||
|
public AnnotatedSetter(Field field, Collection<Annotation> methodAnnotations,
|
||||||
|
Collection<Annotation> parameterAnnotations) {
|
||||||
|
this.field = field;
|
||||||
|
this.methodAnnotations = methodAnnotations;
|
||||||
|
this.parameterAnnotations = parameterAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Type> getImportTypes() {
|
||||||
|
Set<Type> importTypes = new HashSet<>( field.getImportTypes() );
|
||||||
|
for ( Annotation annotation : methodAnnotations ) {
|
||||||
|
importTypes.addAll( annotation.getImportTypes() );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Annotation annotation : parameterAnnotations ) {
|
||||||
|
importTypes.addAll( annotation.getImportTypes() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return importTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getType() {
|
||||||
|
return field.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldName() {
|
||||||
|
return field.getVariableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getMethodAnnotations() {
|
||||||
|
return methodAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getParameterAnnotations() {
|
||||||
|
return parameterAnnotations;
|
||||||
|
}
|
||||||
|
}
|
@ -82,7 +82,7 @@ public abstract class GeneratedType extends ModelElement {
|
|||||||
private final Type mapperDefinitionType;
|
private final Type mapperDefinitionType;
|
||||||
|
|
||||||
private final List<Annotation> annotations;
|
private final List<Annotation> annotations;
|
||||||
private final List<MappingMethod> methods;
|
private final List<GeneratedTypeMethod> methods;
|
||||||
private final SortedSet<Type> extraImportedTypes;
|
private final SortedSet<Type> extraImportedTypes;
|
||||||
|
|
||||||
private final boolean suppressGeneratorTimestamp;
|
private final boolean suppressGeneratorTimestamp;
|
||||||
@ -110,7 +110,7 @@ public abstract class GeneratedType extends ModelElement {
|
|||||||
this.extraImportedTypes = extraImportedTypes;
|
this.extraImportedTypes = extraImportedTypes;
|
||||||
|
|
||||||
this.annotations = new ArrayList<>();
|
this.annotations = new ArrayList<>();
|
||||||
this.methods = methods;
|
this.methods = new ArrayList<>(methods);
|
||||||
this.fields = fields;
|
this.fields = fields;
|
||||||
|
|
||||||
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
|
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
|
||||||
@ -161,7 +161,7 @@ public abstract class GeneratedType extends ModelElement {
|
|||||||
annotations.add( annotation );
|
annotations.add( annotation );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MappingMethod> getMethods() {
|
public List<GeneratedTypeMethod> getMethods() {
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ public abstract class GeneratedType extends ModelElement {
|
|||||||
|
|
||||||
addIfImportRequired( importedTypes, mapperDefinitionType );
|
addIfImportRequired( importedTypes, mapperDefinitionType );
|
||||||
|
|
||||||
for ( MappingMethod mappingMethod : methods ) {
|
for ( GeneratedTypeMethod mappingMethod : methods ) {
|
||||||
for ( Type type : mappingMethod.getImportTypes() ) {
|
for ( Type type : mappingMethod.getImportTypes() ) {
|
||||||
addIfImportRequired( importedTypes, type );
|
addIfImportRequired( importedTypes, type );
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* 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.internal.model;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.internal.model.common.ModelElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public abstract class GeneratedTypeMethod extends ModelElement {
|
||||||
|
|
||||||
|
}
|
@ -14,7 +14,6 @@ import java.util.Objects;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.model.common.Accessibility;
|
import org.mapstruct.ap.internal.model.common.Accessibility;
|
||||||
import org.mapstruct.ap.internal.model.common.ModelElement;
|
|
||||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||||
import org.mapstruct.ap.internal.model.common.Type;
|
import org.mapstruct.ap.internal.model.common.Type;
|
||||||
import org.mapstruct.ap.internal.model.source.Method;
|
import org.mapstruct.ap.internal.model.source.Method;
|
||||||
@ -27,7 +26,7 @@ import static org.mapstruct.ap.internal.util.Strings.join;
|
|||||||
*
|
*
|
||||||
* @author Gunnar Morling
|
* @author Gunnar Morling
|
||||||
*/
|
*/
|
||||||
public abstract class MappingMethod extends ModelElement {
|
public abstract class MappingMethod extends GeneratedTypeMethod {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final List<Parameter> parameters;
|
private final List<Parameter> parameters;
|
||||||
|
@ -11,10 +11,11 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.model.AnnotatedConstructor;
|
import org.mapstruct.ap.internal.model.AnnotatedConstructor;
|
||||||
|
import org.mapstruct.ap.internal.model.AnnotatedSetter;
|
||||||
import org.mapstruct.ap.internal.model.Annotation;
|
import org.mapstruct.ap.internal.model.Annotation;
|
||||||
import org.mapstruct.ap.internal.model.AnnotationMapperReference;
|
import org.mapstruct.ap.internal.model.AnnotationMapperReference;
|
||||||
import org.mapstruct.ap.internal.model.Decorator;
|
import org.mapstruct.ap.internal.model.Decorator;
|
||||||
@ -77,6 +78,9 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
|
|||||||
if ( injectionStrategy == InjectionStrategyGem.CONSTRUCTOR ) {
|
if ( injectionStrategy == InjectionStrategyGem.CONSTRUCTOR ) {
|
||||||
buildConstructors( mapper );
|
buildConstructors( mapper );
|
||||||
}
|
}
|
||||||
|
else if ( injectionStrategy == InjectionStrategyGem.SETTER ) {
|
||||||
|
buildSetters( mapper );
|
||||||
|
}
|
||||||
|
|
||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
@ -110,6 +114,42 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
|
|||||||
return mapperReferences;
|
return mapperReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void buildSetters(Mapper mapper) {
|
||||||
|
List<MapperReference> mapperReferences = toMapperReferences( mapper.getFields() );
|
||||||
|
for ( MapperReference mapperReference : mapperReferences ) {
|
||||||
|
if ( mapperReference.isUsed() ) {
|
||||||
|
AnnotatedSetter setter = new AnnotatedSetter(
|
||||||
|
mapperReference,
|
||||||
|
getMapperReferenceAnnotations(),
|
||||||
|
Collections.emptyList()
|
||||||
|
);
|
||||||
|
mapper.getMethods().add( setter );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Decorator decorator = mapper.getDecorator();
|
||||||
|
if ( decorator != null ) {
|
||||||
|
List<Annotation> mapperReferenceAnnotations = getMapperReferenceAnnotations();
|
||||||
|
Set<Type> mapperReferenceAnnotationsTypes = mapperReferenceAnnotations
|
||||||
|
.stream()
|
||||||
|
.map( Annotation::getType )
|
||||||
|
.collect( Collectors.toSet() );
|
||||||
|
for ( Field field : decorator.getFields() ) {
|
||||||
|
if ( field instanceof AnnotationMapperReference ) {
|
||||||
|
|
||||||
|
List<Annotation> fieldAnnotations = ( (AnnotationMapperReference) field ).getAnnotations();
|
||||||
|
|
||||||
|
List<Annotation> qualifiers = extractMissingAnnotations(
|
||||||
|
fieldAnnotations,
|
||||||
|
mapperReferenceAnnotationsTypes
|
||||||
|
);
|
||||||
|
|
||||||
|
decorator.getMethods().add( new AnnotatedSetter( field, mapperReferenceAnnotations, qualifiers ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void buildConstructors(Mapper mapper) {
|
private void buildConstructors(Mapper mapper) {
|
||||||
if ( !toMapperReferences( mapper.getFields() ).isEmpty() ) {
|
if ( !toMapperReferences( mapper.getFields() ).isEmpty() ) {
|
||||||
AnnotatedConstructor annotatedConstructor = buildAnnotatedConstructorForMapper( mapper );
|
AnnotatedConstructor annotatedConstructor = buildAnnotatedConstructorForMapper( mapper );
|
||||||
@ -197,17 +237,33 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
|
|||||||
AnnotationMapperReference annotationMapperReference = mapperReferenceIterator.next();
|
AnnotationMapperReference annotationMapperReference = mapperReferenceIterator.next();
|
||||||
mapperReferenceIterator.remove();
|
mapperReferenceIterator.remove();
|
||||||
|
|
||||||
List<Annotation> qualifiers = new ArrayList<>();
|
List<Annotation> qualifiers = extractMissingAnnotations(
|
||||||
for ( Annotation annotation : annotationMapperReference.getAnnotations() ) {
|
annotationMapperReference.getAnnotations(),
|
||||||
if ( !mapperReferenceAnnotationsTypes.contains( annotation.getType() ) ) {
|
mapperReferenceAnnotationsTypes
|
||||||
qualifiers.add( annotation );
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mapperReferenceIterator.add( annotationMapperReference.withNewAnnotations( qualifiers ) );
|
mapperReferenceIterator.add( annotationMapperReference.withNewAnnotations( qualifiers ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract all annotations from {@code annotations} that do not have a type in {@code annotationTypes}.
|
||||||
|
*
|
||||||
|
* @param annotations the annotations from which we need to extract information
|
||||||
|
* @param annotationTypes the annotation types to ignore
|
||||||
|
* @return the annotations that are not in the {@code annotationTypes}
|
||||||
|
*/
|
||||||
|
private List<Annotation> extractMissingAnnotations(List<Annotation> annotations,
|
||||||
|
Set<Type> annotationTypes) {
|
||||||
|
List<Annotation> qualifiers = new ArrayList<>();
|
||||||
|
for ( Annotation annotation : annotations ) {
|
||||||
|
if ( !annotationTypes.contains( annotation.getType() ) ) {
|
||||||
|
qualifiers.add( annotation );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return qualifiers;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean additionalPublicEmptyConstructor() {
|
protected boolean additionalPublicEmptyConstructor() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<#--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.AnnotatedSetter" -->
|
||||||
|
<#list methodAnnotations as annotation>
|
||||||
|
<#nt><@includeModel object=annotation/>
|
||||||
|
</#list>
|
||||||
|
public void set${fieldName?cap_first}(<#list parameterAnnotations as annotation><#nt><@includeModel object=annotation/> </#list><@includeModel object=type/> ${fieldName}) {
|
||||||
|
this.${fieldName} = ${fieldName};
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.decorator.spring.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.DecoratedWith;
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
import org.mapstruct.ap.test.decorator.Address;
|
||||||
|
import org.mapstruct.ap.test.decorator.AddressDto;
|
||||||
|
import org.mapstruct.ap.test.decorator.Person;
|
||||||
|
import org.mapstruct.ap.test.decorator.PersonDto;
|
||||||
|
|
||||||
|
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, injectionStrategy = InjectionStrategy.SETTER)
|
||||||
|
@DecoratedWith(PersonMapperDecorator.class)
|
||||||
|
public interface PersonMapper {
|
||||||
|
|
||||||
|
@Mapping( target = "name", ignore = true )
|
||||||
|
PersonDto personToPersonDto(Person person);
|
||||||
|
|
||||||
|
AddressDto addressToAddressDto(Address address);
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.decorator.spring.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.test.decorator.Person;
|
||||||
|
import org.mapstruct.ap.test.decorator.PersonDto;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
|
public abstract class PersonMapperDecorator implements PersonMapper {
|
||||||
|
|
||||||
|
private PersonMapper decoratorDelegate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PersonDto personToPersonDto(Person person) {
|
||||||
|
PersonDto dto = decoratorDelegate.personToPersonDto( person );
|
||||||
|
dto.setName( person.getFirstName() + " " + person.getLastName() );
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void setDecoratorDelegate(@Qualifier("delegate") PersonMapper decoratorDelegate) {
|
||||||
|
this.decoratorDelegate = decoratorDelegate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* 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.decorator.spring.setter;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.mapstruct.ap.test.decorator.Address;
|
||||||
|
import org.mapstruct.ap.test.decorator.AddressDto;
|
||||||
|
import org.mapstruct.ap.test.decorator.Person;
|
||||||
|
import org.mapstruct.ap.test.decorator.PersonDto;
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.WithSpring;
|
||||||
|
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 org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@WithClasses({
|
||||||
|
Person.class,
|
||||||
|
PersonDto.class,
|
||||||
|
Address.class,
|
||||||
|
AddressDto.class,
|
||||||
|
PersonMapper.class,
|
||||||
|
PersonMapperDecorator.class
|
||||||
|
})
|
||||||
|
@WithSpring
|
||||||
|
@IssueKey("3229")
|
||||||
|
@ComponentScan(basePackageClasses = SpringDecoratorTest.class)
|
||||||
|
@Configuration
|
||||||
|
public class SpringDecoratorTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PersonMapper personMapper;
|
||||||
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void springUp() {
|
||||||
|
context = new AnnotationConfigApplicationContext( getClass() );
|
||||||
|
context.getAutowireCapableBeanFactory().autowireBean( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void springDown() {
|
||||||
|
if ( context != null ) {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldInvokeDecoratorMethods() {
|
||||||
|
//given
|
||||||
|
Calendar birthday = Calendar.getInstance();
|
||||||
|
birthday.set( 1928, Calendar.MAY, 23 );
|
||||||
|
Person person = new Person( "Gary", "Crant", birthday.getTime(), new Address( "42 Ocean View Drive" ) );
|
||||||
|
|
||||||
|
//when
|
||||||
|
PersonDto personDto = personMapper.personToPersonDto( person );
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat( personDto ).isNotNull();
|
||||||
|
assertThat( personDto.getName() ).isEqualTo( "Gary Crant" );
|
||||||
|
assertThat( personDto.getAddress() ).isNotNull();
|
||||||
|
assertThat( personDto.getAddress().getAddressLine() ).isEqualTo( "42 Ocean View Drive" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldDelegateNonDecoratedMethodsToDefaultImplementation() {
|
||||||
|
//given
|
||||||
|
Address address = new Address( "42 Ocean View Drive" );
|
||||||
|
|
||||||
|
//when
|
||||||
|
AddressDto addressDto = personMapper.addressToAddressDto( address );
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat( addressDto ).isNotNull();
|
||||||
|
assertThat( addressDto.getAddressLine() ).isEqualTo( "42 Ocean View Drive" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.jakarta.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper( componentModel = MappingConstants.ComponentModel.JAKARTA,
|
||||||
|
uses = GenderJakartaSetterMapper.class,
|
||||||
|
injectionStrategy = InjectionStrategy.SETTER )
|
||||||
|
public interface CustomerJakartaSetterMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "gender", source = "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.jakarta.setter;
|
||||||
|
|
||||||
|
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 Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper(config = SetterJakartaConfig.class)
|
||||||
|
public interface GenderJakartaSetterMapper {
|
||||||
|
|
||||||
|
@ValueMappings({
|
||||||
|
@ValueMapping(source = "MALE", target = "M"),
|
||||||
|
@ValueMapping(source = "FEMALE", target = "F")
|
||||||
|
})
|
||||||
|
GenderDto mapToDto(Gender gender);
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.jakarta.setter;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
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.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.WithJakartaInject;
|
||||||
|
import org.mapstruct.ap.testutil.runner.GeneratedSource;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static java.lang.System.lineSeparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
CustomerDto.class,
|
||||||
|
CustomerEntity.class,
|
||||||
|
Gender.class,
|
||||||
|
GenderDto.class,
|
||||||
|
CustomerJakartaSetterMapper.class,
|
||||||
|
GenderJakartaSetterMapper.class,
|
||||||
|
SetterJakartaConfig.class
|
||||||
|
})
|
||||||
|
@IssueKey("3229")
|
||||||
|
@Configuration
|
||||||
|
@WithJakartaInject
|
||||||
|
public class JakartaSetterMapperTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
final GeneratedSource generatedSource = new GeneratedSource();
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldHaveSetterInjection() {
|
||||||
|
String method = "@Inject" + lineSeparator() +
|
||||||
|
" public void setGenderJakartaSetterMapper(GenderJakartaSetterMapper genderJakartaSetterMapper) {" +
|
||||||
|
lineSeparator() + " this.genderJakartaSetterMapper = genderJakartaSetterMapper;" +
|
||||||
|
lineSeparator() + " }";
|
||||||
|
generatedSource.forMapper( CustomerJakartaSetterMapper.class )
|
||||||
|
.content()
|
||||||
|
.contains( "import jakarta.inject.Inject;" )
|
||||||
|
.contains( "import jakarta.inject.Named;" )
|
||||||
|
.contains( "import jakarta.inject.Singleton;" )
|
||||||
|
.contains( "private GenderJakartaSetterMapper genderJakartaSetterMapper;" )
|
||||||
|
.doesNotContain( "@Inject" + lineSeparator() + " private GenderJakartaSetterMapper" )
|
||||||
|
.contains( method );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* 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.jakarta.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.MapperConfig;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@MapperConfig(componentModel = MappingConstants.ComponentModel.JAKARTA,
|
||||||
|
injectionStrategy = InjectionStrategy.SETTER)
|
||||||
|
public interface SetterJakartaConfig {
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper( componentModel = MappingConstants.ComponentModel.JSR330,
|
||||||
|
uses = GenderJsr330SetterMapper.class,
|
||||||
|
injectionStrategy = InjectionStrategy.SETTER )
|
||||||
|
public interface CustomerJsr330SetterMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "gender", source = "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.setter;
|
||||||
|
|
||||||
|
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 Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper(config = SetterJsr330Config.class)
|
||||||
|
public interface GenderJsr330SetterMapper {
|
||||||
|
|
||||||
|
@ValueMappings({
|
||||||
|
@ValueMapping(source = "MALE", target = "M"),
|
||||||
|
@ValueMapping(source = "FEMALE", target = "F")
|
||||||
|
})
|
||||||
|
GenderDto mapToDto(Gender gender);
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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.setter;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
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.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.WithJavaxInject;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
CustomerDto.class,
|
||||||
|
CustomerEntity.class,
|
||||||
|
Gender.class,
|
||||||
|
GenderDto.class,
|
||||||
|
CustomerJsr330SetterMapper.class,
|
||||||
|
GenderJsr330SetterMapper.class,
|
||||||
|
SetterJsr330Config.class
|
||||||
|
})
|
||||||
|
@IssueKey("3229")
|
||||||
|
@ComponentScan(basePackageClasses = CustomerJsr330SetterMapper.class)
|
||||||
|
@Configuration
|
||||||
|
@WithJavaxInject
|
||||||
|
public class Jsr330SetterMapperTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
final GeneratedSource generatedSource = new GeneratedSource();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomerJsr330SetterMapper customerMapper;
|
||||||
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void springUp() {
|
||||||
|
context = new AnnotationConfigApplicationContext( getClass() );
|
||||||
|
context.getAutowireCapableBeanFactory().autowireBean( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void springDown() {
|
||||||
|
if ( context != null ) {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldHaveSetterInjection() {
|
||||||
|
String method = "@Inject" + lineSeparator() +
|
||||||
|
" public void setGenderJsr330SetterMapper(GenderJsr330SetterMapper genderJsr330SetterMapper) {" +
|
||||||
|
lineSeparator() + " this.genderJsr330SetterMapper = genderJsr330SetterMapper;" +
|
||||||
|
lineSeparator() + " }";
|
||||||
|
generatedSource.forMapper( CustomerJsr330SetterMapper.class )
|
||||||
|
.content()
|
||||||
|
.contains( "import javax.inject.Inject;" )
|
||||||
|
.contains( "import javax.inject.Named;" )
|
||||||
|
.contains( "import javax.inject.Singleton;" )
|
||||||
|
.contains( "private GenderJsr330SetterMapper genderJsr330SetterMapper;" )
|
||||||
|
.doesNotContain( "@Inject" + lineSeparator() + " private GenderJsr330SetterMapper" )
|
||||||
|
.contains( method );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* 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.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.MapperConfig;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@MapperConfig(componentModel = MappingConstants.ComponentModel.JSR330,
|
||||||
|
injectionStrategy = InjectionStrategy.SETTER)
|
||||||
|
public interface SetterJsr330Config {
|
||||||
|
}
|
@ -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.spring.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerRecordDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerRecordEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lucas Resch
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,
|
||||||
|
uses = { CustomerSpringSetterMapper.class, GenderSpringSetterMapper.class },
|
||||||
|
injectionStrategy = InjectionStrategy.SETTER)
|
||||||
|
public interface CustomerRecordSpringSetterMapper {
|
||||||
|
|
||||||
|
CustomerRecordDto asTarget(CustomerRecordEntity customerRecordEntity);
|
||||||
|
}
|
@ -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.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto;
|
||||||
|
import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lucas Resch
|
||||||
|
*/
|
||||||
|
@Mapper( componentModel = MappingConstants.ComponentModel.SPRING,
|
||||||
|
uses = GenderSpringSetterMapper.class,
|
||||||
|
injectionStrategy = InjectionStrategy.SETTER )
|
||||||
|
public interface CustomerSpringSetterMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "gender", source = "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.setter;
|
||||||
|
|
||||||
|
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 Lucas Resch
|
||||||
|
*/
|
||||||
|
@Mapper(config = SetterSpringConfig.class)
|
||||||
|
public interface GenderSpringSetterMapper {
|
||||||
|
|
||||||
|
@ValueMappings({
|
||||||
|
@ValueMapping(source = "MALE", target = "M"),
|
||||||
|
@ValueMapping(source = "FEMALE", target = "F")
|
||||||
|
})
|
||||||
|
GenderDto mapToDto(Gender gender);
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* 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.setter;
|
||||||
|
|
||||||
|
import org.mapstruct.InjectionStrategy;
|
||||||
|
import org.mapstruct.MapperConfig;
|
||||||
|
import org.mapstruct.MappingConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lucas Resch
|
||||||
|
*/
|
||||||
|
@MapperConfig(componentModel = MappingConstants.ComponentModel.SPRING, injectionStrategy = InjectionStrategy.SETTER)
|
||||||
|
public interface SetterSpringConfig {
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* 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.setter;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junitpioneer.jupiter.DefaultTimeZone;
|
||||||
|
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.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.WithSpring;
|
||||||
|
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 setter injection for component model spring.
|
||||||
|
*
|
||||||
|
* @author Lucas Resch
|
||||||
|
*/
|
||||||
|
@WithClasses( {
|
||||||
|
CustomerRecordDto.class,
|
||||||
|
CustomerRecordEntity.class,
|
||||||
|
CustomerDto.class,
|
||||||
|
CustomerEntity.class,
|
||||||
|
Gender.class,
|
||||||
|
GenderDto.class,
|
||||||
|
CustomerRecordSpringSetterMapper.class,
|
||||||
|
CustomerSpringSetterMapper.class,
|
||||||
|
GenderSpringSetterMapper.class,
|
||||||
|
SetterSpringConfig.class
|
||||||
|
} )
|
||||||
|
@IssueKey( "3229" )
|
||||||
|
@ComponentScan(basePackageClasses = CustomerSpringSetterMapper.class)
|
||||||
|
@Configuration
|
||||||
|
@WithSpring
|
||||||
|
@DefaultTimeZone("Europe/Berlin")
|
||||||
|
public class SpringSetterMapperTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
final GeneratedSource generatedSource = new GeneratedSource();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomerRecordSpringSetterMapper customerRecordMapper;
|
||||||
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void springUp() {
|
||||||
|
context = new AnnotationConfigApplicationContext( getClass() );
|
||||||
|
context.getAutowireCapableBeanFactory().autowireBean( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void springDown() {
|
||||||
|
if ( context != null ) {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
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() ).hasToString( "1982-08-31T10:20:56.000+02:00" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
public void shouldHaveSetterInjection() {
|
||||||
|
String method = "@Autowired" + lineSeparator() +
|
||||||
|
" public void setGenderSpringSetterMapper(GenderSpringSetterMapper genderSpringSetterMapper) {" +
|
||||||
|
lineSeparator() + " this.genderSpringSetterMapper = genderSpringSetterMapper;" +
|
||||||
|
lineSeparator() + " }";
|
||||||
|
generatedSource.forMapper( CustomerSpringSetterMapper.class )
|
||||||
|
.content()
|
||||||
|
.contains( "private GenderSpringSetterMapper genderSpringSetterMapper;" )
|
||||||
|
.contains( method );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date createDate(String date) throws ParseException {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat( "dd-M-yyyy hh:mm:ss" );
|
||||||
|
return sdf.parse( date );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user