#32 Support for CDI-based mapper implementations

This commit is contained in:
Gunnar Morling 2013-06-29 13:39:21 +02:00
parent a565bed0c7
commit 502780c441
29 changed files with 699 additions and 36 deletions

View File

@ -47,4 +47,19 @@ public @interface Mapper {
* @return The reporting policy for unmapped target properties. * @return The reporting policy for unmapped target properties.
*/ */
ReportingPolicy unmappedTargetPolicy() default ReportingPolicy.WARN; ReportingPolicy unmappedTargetPolicy() default ReportingPolicy.WARN;
/**
* Specifies the component model to which the generated mapper should
* adhere. Supported values are
* <ul>
* <li> {@code default}: the mapper uses no component model, instances are
* typically retrieved via {@link Mappers#getMapper(Class)}</li>
* <li>
* {@code cdi}: the generated mapper is an application-scoped CDI bean and
* can be retrieved via {@code @Inject}</li>
* </ul>
*
* @return The component model for the generated mapper.
*/
String componentModel() default "default";
} }

View File

@ -39,6 +39,7 @@
<artifactId>mapstruct</artifactId> <artifactId>mapstruct</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
@ -49,6 +50,26 @@
<artifactId>fest-assert</artifactId> <artifactId>fest-assert</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.testng</groupId>
<artifactId>arquillian-testng-container</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-weld-se-embedded-1.1</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,37 @@
/**
* Copyright 2012-2013 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 java.util.Date;
import java.util.GregorianCalendar;
public class Source {
private int foo = 42;
private Date date = new GregorianCalendar( 1980, 0, 1 ).getTime();
public int getFoo() {
return foo;
}
public Date getDate() {
return date;
}
}

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2013 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.itest.cdi.other.DateMapper;
@Mapper(componentModel = "cdi", uses = DateMapper.class)
public interface SourceTargetMapper {
Target sourceToTarget(Source source);
}

View File

@ -0,0 +1,42 @@
/**
* Copyright 2012-2013 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;
public class Target {
private Long foo;
private String date;
public void setFoo(Long foo) {
this.foo = foo;
}
public Long getFoo() {
return foo;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}

View File

@ -0,0 +1,41 @@
/**
* Copyright 2012-2013 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.other;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class DateMapper {
public String asString(Date date) {
return date != null ? new SimpleDateFormat( "yyyy" ).format( date ) : null;
}
public Date asDate(String date) {
try {
return date != null ? new SimpleDateFormat( "yyyy" ).parse( date ) : null;
}
catch ( ParseException e ) {
throw new RuntimeException( e );
}
}
}

View File

@ -0,0 +1,61 @@
/**
* Copyright 2012-2013 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.inject.Inject;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.testng.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.mapstruct.itest.cdi.other.DateMapper;
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.assertThat;
/**
* Test for generation of CDI-based mapper implementations.
*
* @author Gunnar Morling
*/
public class CdiBasedMapperTest extends Arquillian {
@Inject
private SourceTargetMapper mapper;
@Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create( JavaArchive.class )
.addPackage( SourceTargetMapper.class.getPackage() )
.addPackage( DateMapper.class.getPackage() )
.addAsManifestResource( EmptyAsset.INSTANCE, "beans.xml" );
}
@Test
public void shouldCreateCdiBasedMapper() {
Source source = new Source();
Target target = mapper.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 42 ) );
assertThat( target.getDate() ).isEqualTo( "1980" );
}
}

View File

@ -117,6 +117,32 @@
<artifactId>hickory</artifactId> <artifactId>hickory</artifactId>
<version>${com.jolira.hickory.version}</version> <version>${com.jolira.hickory.version}</version>
</dependency> </dependency>
<!-- CDI, Weld, Arquillian -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.1-PFD</version>
</dependency>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.0.4.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-weld-se-embedded-1.1</artifactId>
<version>1.0.0.CR3</version>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>1.1.5.Final</version>
</dependency>
<!-- Project modules -->
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>mapstruct</artifactId> <artifactId>mapstruct</artifactId>
@ -127,6 +153,18 @@
<artifactId>mapstruct-processor</artifactId> <artifactId>mapstruct-processor</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<!-- Not directly used but required for dependency convergence -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>ch.qos.cal10n</groupId>
<artifactId>cal10n-api</artifactId>
<version>0.7.4</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -39,6 +39,7 @@ import org.mapstruct.Mappings;
import org.mapstruct.ap.model.Mapper; import org.mapstruct.ap.model.Mapper;
import org.mapstruct.ap.model.Options; import org.mapstruct.ap.model.Options;
import org.mapstruct.ap.model.ReportingPolicy; import org.mapstruct.ap.model.ReportingPolicy;
import org.mapstruct.ap.processor.CdiComponentProcessor;
import org.mapstruct.ap.processor.DefaultModelElementProcessorContext; import org.mapstruct.ap.processor.DefaultModelElementProcessorContext;
import org.mapstruct.ap.processor.MapperCreationProcessor; import org.mapstruct.ap.processor.MapperCreationProcessor;
import org.mapstruct.ap.processor.MapperRenderingProcessor; import org.mapstruct.ap.processor.MapperRenderingProcessor;
@ -146,6 +147,7 @@ public class MappingProcessor extends AbstractProcessor {
return Arrays.<ModelElementProcessor<?, ?>>asList( return Arrays.<ModelElementProcessor<?, ?>>asList(
new MethodRetrievalProcessor(), new MethodRetrievalProcessor(),
new MapperCreationProcessor(), new MapperCreationProcessor(),
new CdiComponentProcessor(),
new MapperRenderingProcessor() new MapperRenderingProcessor()
); );
} }

View File

@ -30,7 +30,7 @@ import org.mapstruct.ap.writer.FreeMarkerModelElementWriter;
* *
* @author Gunnar Morling * @author Gunnar Morling
*/ */
public class AbstractModelElement implements ModelElement { public abstract class AbstractModelElement implements ModelElement {
@Override @Override
public void write(Context context, Writer writer) throws Exception { public void write(Context context, Writer writer) throws Exception {

View File

@ -0,0 +1,41 @@
/**
* Copyright 2012-2013 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.ap.model;
import java.util.Set;
import org.mapstruct.ap.util.Collections;
public class Annotation extends AbstractModelElement {
private Type type;
public Annotation(Type type) {
this.type = type;
}
public Type getType() {
return type;
}
@Override
public Set<Type> getImportTypes() {
return Collections.asSet( type );
}
}

View File

@ -43,12 +43,11 @@ public class BeanMappingMethod extends MappingMethod {
} }
@Override @Override
public Set<Type> getReferencedTypes() { public Set<Type> getImportTypes() {
Set<Type> types = super.getReferencedTypes(); Set<Type> types = super.getImportTypes();
for ( PropertyMapping propertyMapping : propertyMappings ) { for ( PropertyMapping propertyMapping : propertyMappings ) {
types.add( propertyMapping.getSourceType() ); types.addAll( propertyMapping.getImportTypes() );
types.add( propertyMapping.getTargetType() );
} }
return types; return types;

View File

@ -0,0 +1,49 @@
/**
* Copyright 2012-2013 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.ap.model;
import java.util.Set;
import org.mapstruct.ap.util.Collections;
/**
* Mapper reference which is retrieved via CDI-based dependency injection.
* method. Used if "cdi" is specified as component model via
* {@code Mapper#uses()}.
*
* @author Gunnar Morling
*/
public class CdiMapperReference extends AbstractModelElement implements MapperReference {
private Type type;
public CdiMapperReference(Type type) {
this.type = type;
}
@Override
public Type getMapperType() {
return type;
}
@Override
public Set<Type> getImportTypes() {
return Collections.asSet( type, new Type( "javax.inject", "Inject" ) );
}
}

View File

@ -0,0 +1,49 @@
/**
* Copyright 2012-2013 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.ap.model;
import java.util.Set;
import org.mapstruct.ap.util.Collections;
/**
* Mapper reference which is retrieved via the {@code Mappers#getMapper()}
* method. Used by default if no other component model is specified via
* {@code Mapper#uses()}.
*
* @author Gunnar Morling
*/
public class DefaultMapperReference extends AbstractModelElement implements MapperReference {
private Type type;
public DefaultMapperReference(Type type) {
this.type = type;
}
@Override
public Type getMapperType() {
return type;
}
@Override
public Set<Type> getImportTypes() {
return Collections.asSet( type );
}
}

View File

@ -18,6 +18,7 @@
*/ */
package org.mapstruct.ap.model; package org.mapstruct.ap.model;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
@ -29,36 +30,46 @@ public class Mapper extends AbstractModelElement {
private final String packageName; private final String packageName;
private final String interfaceName; private final String interfaceName;
private final String implementationName; private final String implementationName;
private final List<Annotation> annotations;
private final List<MappingMethod> mappingMethods; private final List<MappingMethod> mappingMethods;
private final List<Type> usedMapperTypes; private final List<MapperReference> referencedMappers;
private final Options options; private final Options options;
private final SortedSet<Type> importedTypes;
private final boolean isErroneous; private final boolean isErroneous;
public Mapper(String packageName, String interfaceName, public Mapper(String packageName, String interfaceName, String implementationName,
String implementationName, List<MappingMethod> mappingMethods, List<Type> usedMapperTypes, List<MappingMethod> mappingMethods, List<MapperReference> referencedMappers, Options options,
Options options, boolean isErroneous) { boolean isErroneous) {
this.packageName = packageName; this.packageName = packageName;
this.interfaceName = interfaceName; this.interfaceName = interfaceName;
this.implementationName = implementationName; this.implementationName = implementationName;
this.annotations = new ArrayList<Annotation>();
this.mappingMethods = mappingMethods; this.mappingMethods = mappingMethods;
this.usedMapperTypes = usedMapperTypes; this.referencedMappers = referencedMappers;
this.options = options; this.options = options;
this.importedTypes = determineImportedTypes();
this.isErroneous = isErroneous; this.isErroneous = isErroneous;
} }
private SortedSet<Type> determineImportedTypes() { @Override
public SortedSet<Type> getImportTypes() {
SortedSet<Type> importedTypes = new TreeSet<Type>(); SortedSet<Type> importedTypes = new TreeSet<Type>();
importedTypes.add( Type.forClass( Generated.class ) ); importedTypes.add( Type.forClass( Generated.class ) );
for ( MappingMethod mappingMethod : mappingMethods ) { for ( MappingMethod mappingMethod : mappingMethods ) {
for ( Type type : mappingMethod.getImportTypes() ) {
for ( Type type : mappingMethod.getReferencedTypes() ) {
addWithDependents( importedTypes, type ); addWithDependents( importedTypes, type );
} }
} }
for ( MapperReference mapperReference : referencedMappers ) {
for ( Type type : mapperReference.getImportTypes() ) {
addWithDependents( importedTypes, type );
}
}
for ( Annotation annotation : annotations ) {
addWithDependents( importedTypes, annotation.getType() );
}
return importedTypes; return importedTypes;
} }
@ -91,7 +102,7 @@ public class Mapper extends AbstractModelElement {
sb.append( "\n " + beanMapping.toString().replaceAll( "\n", "\n " ) ); sb.append( "\n " + beanMapping.toString().replaceAll( "\n", "\n " ) );
} }
sb.append( "\n ]" ); sb.append( "\n ]" );
sb.append( "\n usedMapperTypes=" + usedMapperTypes ); sb.append( "\n referencedMappers=" + referencedMappers );
sb.append( "\n}," ); sb.append( "\n}," );
return sb.toString(); return sb.toString();
@ -113,19 +124,23 @@ public class Mapper extends AbstractModelElement {
return mappingMethods; return mappingMethods;
} }
public List<Type> getUsedMapperTypes() { public List<MapperReference> getReferencedMappers() {
return usedMapperTypes; return referencedMappers;
} }
public Options getOptions() { public Options getOptions() {
return options; return options;
} }
public SortedSet<Type> getImportedTypes() {
return importedTypes;
}
public boolean isErroneous() { public boolean isErroneous() {
return isErroneous; return isErroneous;
} }
public void addAnnotation(Annotation annotation) {
annotations.add( annotation );
}
public List<Annotation> getAnnotations() {
return annotations;
}
} }

View File

@ -0,0 +1,30 @@
/**
* Copyright 2012-2013 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.ap.model;
/**
* A reference to another mapper class, which itself may be generated or
* hand-written.
*
* @author Gunnar Morling
*/
public interface MapperReference extends ModelElement {
Type getMapperType();
}

View File

@ -56,7 +56,8 @@ public abstract class MappingMethod extends AbstractModelElement {
return targetType; return targetType;
} }
public Set<Type> getReferencedTypes() { @Override
public Set<Type> getImportTypes() {
Set<Type> types = new HashSet<Type>(); Set<Type> types = new HashSet<Type>();
types.add( getSourceType() ); types.add( getSourceType() );
types.add( getTargetType() ); types.add( getTargetType() );

View File

@ -19,6 +19,7 @@
package org.mapstruct.ap.model; package org.mapstruct.ap.model;
import java.io.Writer; import java.io.Writer;
import java.util.Set;
/** /**
* A model element with the ability to write itself into a given {@link Writer}. * A model element with the ability to write itself into a given {@link Writer}.
@ -54,4 +55,13 @@ public interface ModelElement {
* implementations. * implementations.
*/ */
void write(Context context, Writer writer) throws Exception; void write(Context context, Writer writer) throws Exception;
/**
* Returns a set containing those {@link Type}s referenced by this model
* element for which an import statement needs to be declared.
*
* @return A set with type referenced by this model element. Must not be
* {@code null.}
*/
Set<Type> getImportTypes();
} }

View File

@ -18,6 +18,10 @@
*/ */
package org.mapstruct.ap.model; package org.mapstruct.ap.model;
import java.util.Set;
import org.mapstruct.ap.util.Collections;
/** /**
* Represents the mapping between a source and target property, e.g. from * Represents the mapping between a source and target property, e.g. from
* {@code String Source#foo} to {@code int Target#bar}. Name and type of source * {@code String Source#foo} to {@code int Target#bar}. Name and type of source
@ -100,6 +104,11 @@ public class PropertyMapping extends AbstractModelElement {
return conversion; return conversion;
} }
@Override
public Set<Type> getImportTypes() {
return Collections.asSet( sourceType, targetType );
}
@Override @Override
public String toString() { public String toString() {
return "PropertyMapping {" + return "PropertyMapping {" +

View File

@ -0,0 +1,59 @@
/**
* Copyright 2012-2013 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.ap.processor;
import java.util.ListIterator;
import javax.lang.model.element.TypeElement;
import org.mapstruct.ap.MapperPrism;
import org.mapstruct.ap.model.Annotation;
import org.mapstruct.ap.model.CdiMapperReference;
import org.mapstruct.ap.model.Mapper;
import org.mapstruct.ap.model.MapperReference;
import org.mapstruct.ap.model.Type;
/**
* A {@link ModelElementProcessor} which converts the given {@link Mapper}
* object into an application-scoped CDI bean in case CDI is configured as the
* target component model for this mapper.
*
* @author Gunnar Morling
*/
public class CdiComponentProcessor implements ModelElementProcessor<Mapper, Mapper> {
@Override
public Mapper process(ProcessorContext context, TypeElement mapperTypeElement, Mapper mapper) {
String componentModel = MapperPrism.getInstanceOn( mapperTypeElement ).componentModel();
if ( !componentModel.equals( "cdi" ) ) {
return mapper;
}
mapper.addAnnotation( new Annotation( new Type( "javax.enterprise.context", "ApplicationScoped" ) ) );
ListIterator<MapperReference> iterator = mapper.getReferencedMappers().listIterator();
while ( iterator.hasNext() ) {
MapperReference reference = iterator.next();
iterator.remove();
iterator.add( new CdiMapperReference( reference.getMapperType() ) );
}
return mapper;
}
}

View File

@ -41,8 +41,10 @@ import org.mapstruct.ap.MapperPrism;
import org.mapstruct.ap.conversion.Conversion; import org.mapstruct.ap.conversion.Conversion;
import org.mapstruct.ap.conversion.Conversions; import org.mapstruct.ap.conversion.Conversions;
import org.mapstruct.ap.model.BeanMappingMethod; import org.mapstruct.ap.model.BeanMappingMethod;
import org.mapstruct.ap.model.DefaultMapperReference;
import org.mapstruct.ap.model.IterableMappingMethod; import org.mapstruct.ap.model.IterableMappingMethod;
import org.mapstruct.ap.model.Mapper; import org.mapstruct.ap.model.Mapper;
import org.mapstruct.ap.model.MapperReference;
import org.mapstruct.ap.model.MappingMethod; import org.mapstruct.ap.model.MappingMethod;
import org.mapstruct.ap.model.MappingMethodReference; import org.mapstruct.ap.model.MappingMethodReference;
import org.mapstruct.ap.model.Options; import org.mapstruct.ap.model.Options;
@ -91,17 +93,17 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
return getMapper( mapperTypeElement, sourceElement ); return getMapper( mapperTypeElement, sourceElement );
} }
public Mapper getMapper(TypeElement element, List<Method> methods) { private Mapper getMapper(TypeElement element, List<Method> methods) {
List<Type> usedMapperTypes = getUsedMapperTypes( element );
ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element ); ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element );
List<MappingMethod> mappingMethods = getMappingMethods( methods, unmappedTargetPolicy );
List<MapperReference> mapperReferences = getReferencedMappers( element );
return new Mapper( return new Mapper(
elementUtils.getPackageOf( element ).getQualifiedName().toString(), elementUtils.getPackageOf( element ).getQualifiedName().toString(),
element.getSimpleName().toString(), element.getSimpleName().toString(),
element.getSimpleName() + IMPLEMENTATION_SUFFIX, element.getSimpleName() + IMPLEMENTATION_SUFFIX,
getMappingMethods( methods, unmappedTargetPolicy ), mappingMethods,
usedMapperTypes, mapperReferences,
options, options,
isErroneous isErroneous
); );
@ -132,13 +134,15 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
} }
} }
private List<Type> getUsedMapperTypes(TypeElement element) { private List<MapperReference> getReferencedMappers(TypeElement element) {
List<Type> usedMapperTypes = new LinkedList<Type>(); List<MapperReference> mapperReferences = new LinkedList<MapperReference>();
MapperPrism mapperPrism = MapperPrism.getInstanceOn( element ); MapperPrism mapperPrism = MapperPrism.getInstanceOn( element );
for ( TypeMirror usedMapper : mapperPrism.uses() ) { for ( TypeMirror usedMapper : mapperPrism.uses() ) {
usedMapperTypes.add( typeUtil.retrieveType( usedMapper ) ); mapperReferences.add( new DefaultMapperReference( typeUtil.retrieveType( usedMapper ) ) );
} }
return usedMapperTypes;
return mapperReferences;
} }
private List<MappingMethod> getMappingMethods(List<Method> methods, ReportingPolicy unmappedTargetPolicy) { private List<MappingMethod> getMappingMethods(List<Method> methods, ReportingPolicy unmappedTargetPolicy) {

View File

@ -0,0 +1,43 @@
/**
* Copyright 2012-2013 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.ap.util;
import java.util.HashSet;
import java.util.Set;
/**
* Provides utility methods around collections.
*
* @author Gunnar Morling
*/
public class Collections {
private Collections() {
}
public static <T> Set<T> asSet(T... elements) {
Set<T> set = new HashSet<T>();
for ( T element : elements ) {
set.add( element );
}
return set;
}
}

View File

@ -0,0 +1,21 @@
<#--
Copyright 2012-2013 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.
-->
@${type.name}

View File

@ -0,0 +1,22 @@
<#--
Copyright 2012-2013 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.
-->
@Inject
private ${mapperType.name} ${mapperType.name?uncap_first};

View File

@ -0,0 +1,21 @@
<#--
Copyright 2012-2013 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.
-->
private final ${mapperType.name} ${mapperType.name?uncap_first} = new ${mapperType.name}();

View File

@ -20,7 +20,7 @@
--> -->
package ${packageName}; package ${packageName};
<#list importedTypes as importedType> <#list importTypes as importedType>
import ${importedType.fullyQualifiedName}; import ${importedType.fullyQualifiedName};
</#list> </#list>
@ -28,10 +28,13 @@ import ${importedType.fullyQualifiedName};
value = "org.mapstruct.ap.MappingProcessor"<#if options.suppressGeneratorTimestamp == false>, value = "org.mapstruct.ap.MappingProcessor"<#if options.suppressGeneratorTimestamp == false>,
date = "${.now?string("yyyy-MM-dd'T'HH:mm:ssZ")}"</#if> date = "${.now?string("yyyy-MM-dd'T'HH:mm:ssZ")}"</#if>
) )
<#list annotations as annotation>
<@includeModel object=annotation/>
</#list>
public class ${implementationName} implements ${interfaceName} { public class ${implementationName} implements ${interfaceName} {
<#list usedMapperTypes as mapperType> <#list referencedMappers as mapper>
private final ${mapperType.name} ${mapperType.name?uncap_first} = new ${mapperType.name}(); <@includeModel object=mapper/>
</#list> </#list>
<#list mappingMethods as mappingMethod> <#list mappingMethods as mappingMethod>

View File

@ -24,6 +24,7 @@ import org.mapstruct.Mapper;
import org.mapstruct.Mappers; import org.mapstruct.Mappers;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.ap.test.complex.other.DateMapper;
import org.mapstruct.ap.test.complex.source.Car; import org.mapstruct.ap.test.complex.source.Car;
import org.mapstruct.ap.test.complex.source.Person; import org.mapstruct.ap.test.complex.source.Person;
import org.mapstruct.ap.test.complex.target.CarDto; import org.mapstruct.ap.test.complex.target.CarDto;

View File

@ -23,6 +23,7 @@ import java.util.Arrays;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import org.mapstruct.ap.test.complex.other.DateMapper;
import org.mapstruct.ap.test.complex.source.Car; import org.mapstruct.ap.test.complex.source.Car;
import org.mapstruct.ap.test.complex.source.Category; import org.mapstruct.ap.test.complex.source.Category;
import org.mapstruct.ap.test.complex.source.Person; import org.mapstruct.ap.test.complex.source.Person;

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.mapstruct.ap.test.complex; package org.mapstruct.ap.test.complex.other;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;