#272 Basic decorator implementation for CDI and Spring

This commit is contained in:
sonata82 2015-04-18 01:32:25 +02:00 committed by Gunnar Morling
parent 174c53cb48
commit b37a1d24d9
11 changed files with 205 additions and 5 deletions

View File

@ -0,0 +1,30 @@
/**
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.itest.cdi;
import org.mapstruct.Mapper;
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

@ -0,0 +1,41 @@
/**
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.itest.cdi;
import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;
@Decorator
public class SourceTargetMapperDecorator implements DecoratedSourceTargetMapper {
@Delegate
@Inject
private DecoratedSourceTargetMapper delegate;
public SourceTargetMapperDecorator() {
}
@Override
public Target sourceToTarget(Source source) {
Target t = delegate.sourceToTarget( source );
t.setFoo( 43L );
return t;
}
}

View File

@ -25,7 +25,7 @@ import javax.inject.Inject;
import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -42,12 +42,17 @@ public class CdiBasedMapperTest {
@Inject @Inject
private SourceTargetMapper mapper; private SourceTargetMapper mapper;
@Inject
private DecoratedSourceTargetMapper decoratedMapper;
@Deployment @Deployment
public static JavaArchive createDeployment() { public static JavaArchive createDeployment() {
return ShrinkWrap.create( JavaArchive.class ) return ShrinkWrap.create( JavaArchive.class )
.addPackage( SourceTargetMapper.class.getPackage() ) .addPackage( SourceTargetMapper.class.getPackage() )
.addPackage( DateMapper.class.getPackage() ) .addPackage( DateMapper.class.getPackage() )
.addAsManifestResource( EmptyAsset.INSTANCE, "beans.xml" ); .addAsManifestResource(
new StringAsset("<decorators><class>org.mapstruct.itest.cdi.SourceTargetMapperDecorator</class></decorators>"),
"beans.xml" );
} }
@Test @Test
@ -60,4 +65,14 @@ public class CdiBasedMapperTest {
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 42 ) ); assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 42 ) );
assertThat( target.getDate() ).isEqualTo( "1980" ); assertThat( target.getDate() ).isEqualTo( "1980" );
} }
}
@Test
public void shouldInjectDecorator() {
Source source = new Source();
Target target = decoratedMapper.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 43 ) );
}
}

View File

@ -0,0 +1,30 @@
/**
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.itest.spring;
import org.mapstruct.Mapper;
import org.mapstruct.DecoratedWith;
import org.mapstruct.itest.spring.other.DateMapper;
@Mapper( componentModel = "spring", uses = DateMapper.class )
@DecoratedWith( SourceTargetMapperDecorator.class )
public interface DecoratedSourceTargetMapper {
Target sourceToTarget(Source source);
}

View File

@ -0,0 +1,41 @@
/**
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.itest.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class SourceTargetMapperDecorator implements DecoratedSourceTargetMapper {
@Autowired
@Qualifier( "decoratedSourceTargetMapperImpl_" )
private DecoratedSourceTargetMapper delegate;
public SourceTargetMapperDecorator() {
}
@Override
public Target sourceToTarget(Source source) {
Target t = delegate.sourceToTarget( source );
t.setFoo( 43L );
return t;
}
}

View File

@ -24,6 +24,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mapstruct.itest.spring.SpringBasedMapperTest.SpringTestConfig; import org.mapstruct.itest.spring.SpringBasedMapperTest.SpringTestConfig;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
@ -45,6 +46,9 @@ public class SpringBasedMapperTest {
@Autowired @Autowired
private SourceTargetMapper mapper; private SourceTargetMapper mapper;
@Autowired
@Qualifier( "sourceTargetMapperDecorator" )
private DecoratedSourceTargetMapper decoratedMapper;
@Test @Test
public void shouldCreateSpringBasedMapper() { public void shouldCreateSpringBasedMapper() {
@ -56,4 +60,15 @@ public class SpringBasedMapperTest {
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 42 ) ); assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 42 ) );
assertThat( target.getDate() ).isEqualTo( "1980" ); assertThat( target.getDate() ).isEqualTo( "1980" );
} }
}
@Test
public void shouldInjectDecorator() {
Source source = new Source();
Target target = decoratedMapper.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 43 ) );
}
}

View File

@ -43,7 +43,7 @@ public class Mapper extends GeneratedType {
private static final String DECORATED_IMPLEMENTATION_SUFFIX = "Impl_"; private static final String DECORATED_IMPLEMENTATION_SUFFIX = "Impl_";
private final List<MapperReference> referencedMappers; private final List<MapperReference> referencedMappers;
private final Decorator decorator; private Decorator decorator;
@SuppressWarnings( "checkstyle:parameternumber" ) @SuppressWarnings( "checkstyle:parameternumber" )
private Mapper(TypeFactory typeFactory, String packageName, String name, String superClassName, private Mapper(TypeFactory typeFactory, String packageName, String name, String superClassName,
@ -158,6 +158,10 @@ public class Mapper extends GeneratedType {
return decorator; return decorator;
} }
public void removeDecorator() {
this.decorator = null;
}
@Override @Override
protected String getTemplateName() { protected String getTemplateName() {
return getTemplateNameForClass( GeneratedType.class ); return getTemplateNameForClass( GeneratedType.class );

View File

@ -56,6 +56,10 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
return mapper; return mapper;
} }
if ( shouldDecoratorBeRemoved() ) {
mapper.removeDecorator();
}
mapper.addAnnotation( getTypeAnnotation() ); mapper.addAnnotation( getTypeAnnotation() );
ListIterator<MapperReference> iterator = mapper.getReferencedMappers().listIterator(); ListIterator<MapperReference> iterator = mapper.getReferencedMappers().listIterator();
@ -97,6 +101,11 @@ public abstract class AnnotationBasedComponentModelProcessor implements ModelEle
*/ */
protected abstract Annotation getMapperReferenceAnnotation(); protected abstract Annotation getMapperReferenceAnnotation();
/**
* @return if generated decorator class should be removed
*/
protected abstract boolean shouldDecoratorBeRemoved();
@Override @Override
public int getPriority() { public int getPriority() {
return 1100; return 1100;

View File

@ -44,4 +44,9 @@ public class CdiComponentProcessor extends AnnotationBasedComponentModelProcesso
protected Annotation getMapperReferenceAnnotation() { protected Annotation getMapperReferenceAnnotation() {
return new Annotation( getTypeFactory().getType( "javax.inject.Inject" ) ); return new Annotation( getTypeFactory().getType( "javax.inject.Inject" ) );
} }
@Override
protected boolean shouldDecoratorBeRemoved() {
return true;
}
} }

View File

@ -44,4 +44,9 @@ public class Jsr330ComponentProcessor extends AnnotationBasedComponentModelProce
protected Annotation getMapperReferenceAnnotation() { protected Annotation getMapperReferenceAnnotation() {
return new Annotation( getTypeFactory().getType( "javax.inject.Inject" ) ); return new Annotation( getTypeFactory().getType( "javax.inject.Inject" ) );
} }
@Override
protected boolean shouldDecoratorBeRemoved() {
return false;
}
} }

View File

@ -44,4 +44,9 @@ public class SpringComponentProcessor extends AnnotationBasedComponentModelProce
protected Annotation getMapperReferenceAnnotation() { protected Annotation getMapperReferenceAnnotation() {
return new Annotation( getTypeFactory().getType( "org.springframework.beans.factory.annotation.Autowired" ) ); return new Annotation( getTypeFactory().getType( "org.springframework.beans.factory.annotation.Autowired" ) );
} }
@Override
protected boolean shouldDecoratorBeRemoved() {
return true;
}
} }