#272 Allowing to inject decorated mapper in Spring without qualifier

This commit is contained in:
Gunnar Morling 2015-06-03 21:47:20 +02:00
parent 2ad77b5aa0
commit daaa99d143
9 changed files with 65 additions and 25 deletions

View File

@ -23,7 +23,6 @@ import org.mapstruct.DecoratedWith;
import org.mapstruct.itest.cdi.other.DateMapper;
@Mapper( componentModel = "cdi", uses = DateMapper.class )
@DecoratedWith( SourceTargetMapperDecorator.class )
public interface DecoratedSourceTargetMapper {
Target sourceToTarget(Source source);

View File

@ -20,13 +20,15 @@ package org.mapstruct.itest.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
@Primary
public class SourceTargetMapperDecorator implements DecoratedSourceTargetMapper {
@Autowired
@Qualifier( "decoratedSourceTargetMapperImpl_" )
@Qualifier( "delegate" )
private DecoratedSourceTargetMapper delegate;
public SourceTargetMapperDecorator() {

View File

@ -38,6 +38,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration(classes = SpringTestConfig.class )
@RunWith( SpringJUnit4ClassRunner.class )
public class SpringBasedMapperTest {
@Configuration
@ComponentScan(basePackageClasses = SpringBasedMapperTest.class)
public static class SpringTestConfig {
@ -47,7 +48,6 @@ public class SpringBasedMapperTest {
private SourceTargetMapper mapper;
@Autowired
@Qualifier( "sourceTargetMapperDecorator" )
private DecoratedSourceTargetMapper decoratedMapper;
@Test
@ -70,5 +70,4 @@ public class SpringBasedMapperTest {
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 43 ) );
}
}
}

View File

@ -19,6 +19,7 @@
package org.mapstruct.ap.internal.model;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.common.ModelElement;
@ -33,8 +34,18 @@ public class Annotation extends ModelElement {
private final Type type;
/**
* List of annotation attributes. Quite simplistic, but it's sufficient for now.
*/
private List<String> properties;
public Annotation(Type type) {
this( type, Collections.<String>emptyList() );
}
public Annotation(Type type, List<String> properties) {
this.type = type;
this.properties = properties;
}
public Type getType() {
@ -45,4 +56,8 @@ public class Annotation extends ModelElement {
public Set<Type> getImportTypes() {
return Collections.singleton( type );
}
public List<String> getProperties() {
return properties;
}
}

View File

@ -18,6 +18,7 @@
*/
package org.mapstruct.ap.internal.processor;
import java.util.List;
import java.util.ListIterator;
import javax.lang.model.element.TypeElement;
@ -56,11 +57,13 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
return mapper;
}
if ( shouldDecoratorBeRemoved() ) {
mapper.removeDecorator();
for ( Annotation typeAnnotation : getTypeAnnotations( mapper ) ) {
mapper.addAnnotation( typeAnnotation );
}
mapper.addAnnotation( getTypeAnnotation() );
if ( !requiresGenerationOfDecoratorClass() ) {
mapper.removeDecorator();
}
ListIterator<MapperReference> iterator = mapper.getReferencedMappers().listIterator();
while ( iterator.hasNext() ) {
@ -92,9 +95,9 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
protected abstract String getComponentModelIdentifier();
/**
* @return the annotation of the mapper implementation
* @return the annotation(s) to be added at the mapper type implementation
*/
protected abstract Annotation getTypeAnnotation();
protected abstract List<Annotation> getTypeAnnotations(Mapper mapper);
/**
* @return the annotation of the field for the mapper reference
@ -102,9 +105,9 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
protected abstract Annotation getMapperReferenceAnnotation();
/**
* @return if generated decorator class should be removed
* @return if a decorator (sub-)class needs to be generated or not
*/
protected abstract boolean shouldDecoratorBeRemoved();
protected abstract boolean requiresGenerationOfDecoratorClass();
@Override
public int getPriority() {

View File

@ -18,6 +18,9 @@
*/
package org.mapstruct.ap.internal.processor;
import java.util.Collections;
import java.util.List;
import org.mapstruct.ap.internal.model.Annotation;
import org.mapstruct.ap.internal.model.Mapper;
@ -36,8 +39,10 @@ public class CdiComponentProcessor extends AnnotationBasedComponentModelProcesso
}
@Override
protected Annotation getTypeAnnotation() {
return new Annotation( getTypeFactory().getType( "javax.enterprise.context.ApplicationScoped" ) );
protected List<Annotation> getTypeAnnotations(Mapper mapper) {
return Collections.singletonList(
new Annotation( getTypeFactory().getType( "javax.enterprise.context.ApplicationScoped" ) )
);
}
@Override
@ -46,7 +51,7 @@ public class CdiComponentProcessor extends AnnotationBasedComponentModelProcesso
}
@Override
protected boolean shouldDecoratorBeRemoved() {
return true;
protected boolean requiresGenerationOfDecoratorClass() {
return false;
}
}

View File

@ -20,6 +20,8 @@ package org.mapstruct.ap.internal.processor;
import org.mapstruct.ap.internal.model.Annotation;
import org.mapstruct.ap.internal.model.Mapper;
import java.util.Collections;
import java.util.List;
/**
* A {@link ModelElementProcessor} which converts the given {@link Mapper}
@ -36,8 +38,8 @@ public class Jsr330ComponentProcessor extends AnnotationBasedComponentModelProce
}
@Override
protected Annotation getTypeAnnotation() {
return new Annotation( getTypeFactory().getType( "javax.inject.Named" ) );
protected List<Annotation> getTypeAnnotations(Mapper mapper) {
return Collections.singletonList( new Annotation( getTypeFactory().getType( "javax.inject.Named" ) ) );
}
@Override
@ -46,7 +48,7 @@ public class Jsr330ComponentProcessor extends AnnotationBasedComponentModelProce
}
@Override
protected boolean shouldDecoratorBeRemoved() {
return false;
protected boolean requiresGenerationOfDecoratorClass() {
return true;
}
}

View File

@ -18,6 +18,10 @@
*/
package org.mapstruct.ap.internal.processor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.mapstruct.ap.internal.model.Annotation;
import org.mapstruct.ap.internal.model.Mapper;
@ -36,8 +40,19 @@ public class SpringComponentProcessor extends AnnotationBasedComponentModelProce
}
@Override
protected Annotation getTypeAnnotation() {
return new Annotation( getTypeFactory().getType( "org.springframework.stereotype.Component" ) );
protected List<Annotation> getTypeAnnotations(Mapper mapper) {
List<Annotation> typeAnnotations = new ArrayList<Annotation>();
typeAnnotations.add( new Annotation( getTypeFactory().getType( "org.springframework.stereotype.Component" ) ) );
if ( mapper.getDecorator() != null ) {
Annotation qualifier = new Annotation(
getTypeFactory().getType( "org.springframework.beans.factory.annotation.Qualifier" ),
Arrays.asList( "\"delegate\"" )
);
typeAnnotations.add( qualifier );
}
return typeAnnotations;
}
@Override
@ -46,7 +61,7 @@ public class SpringComponentProcessor extends AnnotationBasedComponentModelProce
}
@Override
protected boolean shouldDecoratorBeRemoved() {
return true;
protected boolean requiresGenerationOfDecoratorClass() {
return false;
}
}

View File

@ -18,4 +18,4 @@
limitations under the License.
-->
@<@includeModel object=type/>
@<@includeModel object=type/><#if (properties?size > 0) >(<#list properties as property>${property}<#if property_has_next>, </#if></#list>)</#if>