#12 Allowing delegation to other mapper classes

This commit is contained in:
Gunnar Morling 2013-04-07 13:06:35 +02:00
parent 8f4b45c4f2
commit 458718e346
18 changed files with 186 additions and 154 deletions

View File

@ -29,4 +29,5 @@ import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Mapper {
Class<?>[] uses() default { };
}

View File

@ -15,15 +15,9 @@
*/
package org.mapstruct;
import org.mapstruct.converter.Converter;
import org.mapstruct.converter.NoOpConverter;
public @interface Mapping {
String source();
String target();
Class<? extends Converter<?, ?>> converter() default NoOpConverter.class;
}

View File

@ -1,23 +0,0 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.converter;
public interface Converter<S, T> {
T from(S source);
S to(T target);
}

View File

@ -1,29 +0,0 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.converter;
public class NoOpConverter implements Converter<Object, Object> {
@Override
public Object from(Object source) {
return source;
}
@Override
public Object to(Object target) {
return target;
}
}

View File

@ -16,7 +16,6 @@
package org.mapstruct;
import org.mapstruct.Mappers;
import org.mapstruct.test.model.Foo;
import org.testng.annotations.Test;

View File

@ -29,7 +29,9 @@ import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementKindVisitor6;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
@ -91,18 +93,34 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
}
private Mapper retrieveModel(TypeElement element) {
List<Method> methods = retrieveMethods( element );
Set<Method> processedMethods = new HashSet<Method>();
List<BeanMapping> mappings = new ArrayList<BeanMapping>();
List<Method> methods = retrieveMethods( null, element );
List<BeanMapping> mappings = getMappings( methods );
List<Type> usedMapperTypes = getUsedMapperTypes( element );
Mapper mapper = new Mapper(
elementUtils.getPackageOf( element ).getQualifiedName().toString(),
element.getSimpleName().toString(),
element.getSimpleName() + IMPLEMENTATION_SUFFIX,
mappings,
usedMapperTypes
);
return mapper;
}
private List<BeanMapping> getMappings(List<Method> methods) {
Conversions conversions = new Conversions( elementUtils, typeUtils, typeUtil );
List<BeanMapping> mappings = new ArrayList<BeanMapping>();
Set<Method> processedMethods = new HashSet<Method>();
for ( Method method : methods ) {
if ( processedMethods.contains( method ) ) {
continue;
}
MappingMethod mappingMethod = new MappingMethod(
method.getDeclaringMapper(),
method.getName(),
method.getParameterName(),
getElementMappingMethod( methods, method )
@ -114,6 +132,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
processedMethods.add( rawReverseMappingMethod );
reverseMappingMethod = new MappingMethod(
rawReverseMappingMethod.getDeclaringMapper(),
rawReverseMappingMethod.getName(),
rawReverseMappingMethod.getParameterName(),
getElementMappingMethod( methods, rawReverseMappingMethod )
@ -134,12 +153,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
property.getSourceType(),
property.getTargetName(),
property.getTargetType(),
property.getConverterType(),
propertyMappingMethod != null ? new MappingMethod(
propertyMappingMethod.getDeclaringMapper(),
propertyMappingMethod.getName(),
propertyMappingMethod.getParameterName()
) : null,
reversePropertyMappingMethod != null ? new MappingMethod(
reversePropertyMappingMethod.getDeclaringMapper(),
reversePropertyMappingMethod.getName(),
reversePropertyMappingMethod.getParameterName()
) : null,
@ -168,15 +188,16 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
mappings.add( mapping );
}
return mappings;
}
Mapper mapper = new Mapper(
elementUtils.getPackageOf( element ).getQualifiedName().toString(),
element.getSimpleName().toString(),
element.getSimpleName() + IMPLEMENTATION_SUFFIX,
mappings
);
return mapper;
private List<Type> getUsedMapperTypes(TypeElement element) {
List<Type> usedMapperTypes = new LinkedList<Type>();
MapperPrism mapperPrism = MapperPrism.getInstanceOn( element );
for ( TypeMirror usedMapper : mapperPrism.uses() ) {
usedMapperTypes.add( typeUtil.retrieveType( usedMapper ) );
}
return usedMapperTypes;
}
private String getAccessor(String name) {
@ -196,6 +217,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
}
}
return elementMappingMethod == null ? null : new MappingMethod(
elementMappingMethod.getDeclaringMapper(),
elementMappingMethod.getName(),
elementMappingMethod.getParameterName()
);
@ -231,7 +253,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
return null;
}
private List<Method> retrieveMethods(TypeElement element) {
private List<Method> retrieveMethods(Type declaringMapper, Element element) {
List<Method> methods = new ArrayList<Method>();
for ( ExecutableElement method : methodsIn( element.getEnclosedElements() ) ) {
@ -241,6 +263,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
methods.add(
new Method(
declaringMapper,
method.getSimpleName().toString(),
parameter.getName(),
parameter.getType(),
@ -250,6 +273,21 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
);
}
List<Type> usedMapperTypes = new LinkedList<Type>();
MapperPrism mapperPrism = MapperPrism.getInstanceOn( element );
if ( mapperPrism != null ) {
for ( TypeMirror usedMapper : mapperPrism.uses() ) {
methods.addAll(
retrieveMethods(
typeUtil.retrieveType( usedMapper ),
( (DeclaredType) usedMapper ).asElement()
)
);
}
}
return methods;
}
@ -291,8 +329,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
sourcePropertyName,
retrieveReturnType( getterMethod ),
mapping != null ? mapping.getTargetName() : targetPropertyName,
retrieveParameter( setterMethod ).getType(),
mapping != null ? mapping.getConverterType() : null
retrieveParameter( setterMethod ).getType()
)
);
}
@ -320,12 +357,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
}
private Mapping getMapping(MappingPrism mapping) {
Type converterType = typeUtil.retrieveType( mapping.converter() );
return new Mapping(
mapping.source(),
mapping.target(),
converterType.getName().equals( "NoOpConverter" ) ? null : converterType
);
return new Mapping( mapping.source(), mapping.target() );
}
private Parameter retrieveParameter(ExecutableElement method) {

View File

@ -20,19 +20,18 @@ import java.util.List;
public class Mapper {
private final String packageName;
private final String interfaceName;
private final String implementationName;
private final List<BeanMapping> beanMappings;
private final List<Type> usedMapperTypes;
public Mapper(String packageName, String interfaceName,
String implementationName, List<BeanMapping> beanMappings) {
String implementationName, List<BeanMapping> beanMappings, List<Type> usedMapperTypes) {
this.packageName = packageName;
this.interfaceName = interfaceName;
this.implementationName = implementationName;
this.beanMappings = beanMappings;
this.usedMapperTypes = usedMapperTypes;
}
public String getPackageName() {
@ -50,4 +49,8 @@ public class Mapper {
public List<BeanMapping> getBeanMappings() {
return beanMappings;
}
public List<Type> getUsedMapperTypes() {
return usedMapperTypes;
}
}

View File

@ -17,22 +17,29 @@ package org.mapstruct.ap.model;
public class MappingMethod {
private final Type declaringMapper;
private final String name;
private final String parameterName;
private final MappingMethod elementMappingMethod;
public MappingMethod(String name, String parameterName) {
public MappingMethod(Type declaringMapper, String name, String parameterName) {
this.declaringMapper = declaringMapper;
this.name = name;
this.parameterName = parameterName;
this.elementMappingMethod = null;
}
public MappingMethod(String name, String parameterName, MappingMethod elementMappingMethod) {
public MappingMethod(Type declaringMapper, String name, String parameterName, MappingMethod elementMappingMethod) {
this.declaringMapper = declaringMapper;
this.name = name;
this.parameterName = parameterName;
this.elementMappingMethod = elementMappingMethod;
}
public Type getDeclaringMapper() {
return declaringMapper;
}
public String getName() {
return name;
}
@ -44,4 +51,8 @@ public class MappingMethod {
public MappingMethod getElementMappingMethod() {
return elementMappingMethod;
}
public boolean isGenerationRequired() {
return declaringMapper == null;
}
}

View File

@ -21,18 +21,16 @@ public class PropertyMapping {
private final Type sourceType;
private final String targetName;
private final Type targetType;
private final Type converterType;
private final MappingMethod mappingMethod;
private final MappingMethod reverseMappingMethod;
private final String toConversion;
private final String fromConversion;
public PropertyMapping(String sourceName, Type sourceType, String targetName, Type targetType, Type converterType, MappingMethod mappingMethod, MappingMethod reverseMappingMethod, String toConversion, String fromConversion) {
public PropertyMapping(String sourceName, Type sourceType, String targetName, Type targetType, MappingMethod mappingMethod, MappingMethod reverseMappingMethod, String toConversion, String fromConversion) {
this.sourceName = sourceName;
this.sourceType = sourceType;
this.targetName = targetName;
this.targetType = targetType;
this.converterType = converterType;
this.mappingMethod = mappingMethod;
this.reverseMappingMethod = reverseMappingMethod;
this.toConversion = toConversion;
@ -55,10 +53,6 @@ public class PropertyMapping {
return targetType;
}
public Type getConverterType() {
return converterType;
}
public MappingMethod getMappingMethod() {
return mappingMethod;
}

View File

@ -23,15 +23,12 @@ public class MappedProperty {
private final Type sourceType;
private final String targetName;
private final Type targetType;
private final Type converterType;
public MappedProperty(String sourceName, Type sourceType, String targetName,
Type targetType, Type converterType) {
public MappedProperty(String sourceName, Type sourceType, String targetName, Type targetType) {
this.sourceName = sourceName;
this.sourceType = sourceType;
this.targetName = targetName;
this.targetType = targetType;
this.converterType = converterType;
}
public String getSourceName() {
@ -50,12 +47,8 @@ public class MappedProperty {
return targetType;
}
public Type getConverterType() {
return converterType;
}
@Override
public String toString() {
return sourceType + " " + sourceName + " <=> " + targetType + " " + targetName + " (" + ( converterType != null ? converterType : "no converter" ) + ")";
return sourceType + " " + sourceName + " <=> " + targetType + " " + targetName;
}
}

View File

@ -15,18 +15,14 @@
*/
package org.mapstruct.ap.model.source;
import org.mapstruct.ap.model.Type;
public class Mapping {
private final String sourceName;
private final String targetName;
private final Type converterType;
public Mapping(String sourceName, String targetName, Type converterType) {
public Mapping(String sourceName, String targetName) {
this.sourceName = sourceName;
this.targetName = targetName;
this.converterType = converterType;
}
public String getSourceName() {
@ -36,8 +32,4 @@ public class Mapping {
public String getTargetName() {
return targetName;
}
public Type getConverterType() {
return converterType;
}
}

View File

@ -22,6 +22,7 @@ import org.mapstruct.ap.model.Type;
public class Method {
private final Type declaringMapper;
private final String name;
private final String parameterName;
private final Type sourceType;
@ -29,6 +30,11 @@ public class Method {
private final List<MappedProperty> mappedProperties;
public Method(String name, String parameterName, Type sourceType, Type targetType, List<MappedProperty> mappedProperties) {
this( null, name, parameterName, sourceType, targetType, mappedProperties );
}
public Method(Type declaringMapper, String name, String parameterName, Type sourceType, Type targetType, List<MappedProperty> mappedProperties) {
this.declaringMapper = declaringMapper;
this.name = name;
this.parameterName = parameterName;
this.sourceType = sourceType;
@ -36,6 +42,10 @@ public class Method {
this.mappedProperties = mappedProperties;
}
public Type getDeclaringMapper() {
return declaringMapper;
}
public String getName() {
return name;
}
@ -63,7 +73,7 @@ public class Method {
}
private boolean equals(Object o1, Object o2) {
return (o1 == null && o2 == null) || (o1 != null) && o1.equals( o2 );
return ( o1 == null && o2 == null ) || ( o1 != null ) && o1.equals( o2 );
}
@Override

View File

@ -20,6 +20,7 @@ package ${packageName};
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import java.util.Date;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
@ -27,7 +28,12 @@ import javax.annotation.Generated;
)
public class ${implementationName} implements ${interfaceName} {
<#list usedMapperTypes as mapperType>
private final ${mapperType.name} ${mapperType.name?uncap_first} = new ${mapperType.name}();
</#list>
<#list beanMappings as beanMapping>
<#if beanMapping.mappingMethod.generationRequired == true>
<#if beanMapping.iterableMapping == true>
@Override
public ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.mappingMethod.parameterName}) {
@ -53,6 +59,7 @@ public class ${implementationName} implements ${interfaceName} {
${beanMapping.targetType.name} ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}();
<#list beanMapping.propertyMappings as propertyMapping>
<#-- primitive conversion -->
<#if propertyMapping.toConversion??>
<#if propertyMapping.targetType.primitive == true>
if( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() != null ) {
@ -63,8 +70,9 @@ public class ${implementationName} implements ${interfaceName} {
</#if>
<#elseif propertyMapping.converterType??>
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( new ${propertyMapping.converterType.name}().from( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() ) );
<#-- invoke mapping method -->
<#elseif propertyMapping.mappingMethod??>
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( ${propertyMapping.mappingMethod.name}( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() ) );
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( <#if propertyMapping.mappingMethod.declaringMapper??>${propertyMapping.mappingMethod.declaringMapper.name?uncap_first}.</#if>${propertyMapping.mappingMethod.name}( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() ) );
<#else>
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() );
</#if>
@ -73,8 +81,10 @@ public class ${implementationName} implements ${interfaceName} {
return ${beanMapping.targetType.name?uncap_first};
}
</#if>
</#if>
<#if beanMapping.reverseMappingMethod??>
<#if beanMapping.reverseMappingMethod.generationRequired == true>
<#if beanMapping.iterableMapping == true>
@Override
public ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.reverseMappingMethod.parameterName}) {
@ -110,8 +120,9 @@ public class ${implementationName} implements ${interfaceName} {
</#if>
<#elseif propertyMapping.converterType??>
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( new ${propertyMapping.converterType.name}().to( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() ) );
<#-- invoke mapping method -->
<#elseif propertyMapping.reverseMappingMethod??>
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( ${propertyMapping.reverseMappingMethod.name}( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() ) );
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( <#if propertyMapping.reverseMappingMethod.declaringMapper??>${propertyMapping.reverseMappingMethod.declaringMapper.name?uncap_first}.</#if>${propertyMapping.reverseMappingMethod.name}( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() ) );
<#else>
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() );
</#if>
@ -121,6 +132,7 @@ public class ${implementationName} implements ${interfaceName} {
}
</#if>
</#if>
</#if>
</#list>
}

View File

@ -18,6 +18,7 @@ package org.mapstruct.ap.test;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.List;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
@ -26,7 +27,7 @@ import org.mapstruct.ap.test.model.Car;
import org.mapstruct.ap.test.model.CarDto;
import org.mapstruct.ap.test.model.CarMapper;
import org.mapstruct.ap.test.model.Category;
import org.mapstruct.ap.test.model.IntToStringConverter;
import org.mapstruct.ap.test.model.DateMapper;
import org.mapstruct.ap.test.model.Person;
import org.mapstruct.ap.test.model.PersonDto;
import org.testng.annotations.BeforeMethod;
@ -51,8 +52,8 @@ public class CarMapperTest extends MapperTestBase {
Person.class,
PersonDto.class,
CarMapper.class,
IntToStringConverter.class,
Category.class
Category.class,
DateMapper.class
);
boolean compilationSuccessful = compile( diagnostics, sourceFiles );
@ -69,7 +70,13 @@ public class CarMapperTest extends MapperTestBase {
@Test
public void shouldMapAttributeByName() {
//given
Car car = new Car( "Morris", 2, 1980, new Person( "Bob" ), new ArrayList<Person>() );
Car car = new Car(
"Morris",
2,
new GregorianCalendar( 1980, 0, 1 ).getTime(),
new Person( "Bob" ),
new ArrayList<Person>()
);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
@ -82,7 +89,13 @@ public class CarMapperTest extends MapperTestBase {
@Test
public void shouldMapReferenceAttribute() {
//given
Car car = new Car( "Morris", 2, 1980, new Person( "Bob" ), new ArrayList<Person>() );
Car car = new Car(
"Morris",
2,
new GregorianCalendar( 1980, 0, 1 ).getTime(),
new Person( "Bob" ),
new ArrayList<Person>()
);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
@ -110,7 +123,13 @@ public class CarMapperTest extends MapperTestBase {
@Test
public void shouldMapAttributeWithCustomMapping() {
//given
Car car = new Car( "Morris", 2, 1980, new Person( "Bob" ), new ArrayList<Person>() );
Car car = new Car(
"Morris",
2,
new GregorianCalendar( 1980, 0, 1 ).getTime(),
new Person( "Bob" ),
new ArrayList<Person>()
);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
@ -136,7 +155,13 @@ public class CarMapperTest extends MapperTestBase {
@Test
public void shouldApplyConverter() {
//given
Car car = new Car( "Morris", 2, 1980, new Person( "Bob" ), new ArrayList<Person>() );
Car car = new Car(
"Morris",
2,
new GregorianCalendar( 1980, 0, 1 ).getTime(),
new Person( "Bob" ),
new ArrayList<Person>()
);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
@ -156,14 +181,26 @@ public class CarMapperTest extends MapperTestBase {
//then
assertThat( car ).isNotNull();
assertThat( car.getYearOfManufacture() ).isEqualTo( 1980 );
assertThat( car.getManufacturingDate() ).isEqualTo( new GregorianCalendar( 1980, 0, 1 ).getTime() );
}
@Test
public void shouldMapIterable() {
//given
Car car1 = new Car( "Morris", 2, 1980, new Person( "Bob" ), new ArrayList<Person>() );
Car car2 = new Car( "Railton", 4, 1934, new Person( "Bill" ), new ArrayList<Person>() );
Car car1 = new Car(
"Morris",
2,
new GregorianCalendar( 1980, 0, 1 ).getTime(),
new Person( "Bob" ),
new ArrayList<Person>()
);
Car car2 = new Car(
"Railton",
4,
new GregorianCalendar( 1934, 0, 1 ).getTime(),
new Person( "Bill" ),
new ArrayList<Person>()
);
//when
List<CarDto> dtos = CarMapper.INSTANCE.carsToCarDtos( new ArrayList<Car>( Arrays.asList( car1, car2 ) ) );
@ -198,12 +235,12 @@ public class CarMapperTest extends MapperTestBase {
assertThat( cars.get( 0 ).getMake() ).isEqualTo( "Morris" );
assertThat( cars.get( 0 ).getNumberOfSeats() ).isEqualTo( 2 );
assertThat( cars.get( 0 ).getYearOfManufacture() ).isEqualTo( 1980 );
assertThat( cars.get( 0 ).getManufacturingDate() ).isEqualTo( new GregorianCalendar( 1980, 0, 1 ).getTime() );
assertThat( cars.get( 0 ).getDriver().getName() ).isEqualTo( "Bob" );
assertThat( cars.get( 1 ).getMake() ).isEqualTo( "Railton" );
assertThat( cars.get( 1 ).getNumberOfSeats() ).isEqualTo( 4 );
assertThat( cars.get( 1 ).getYearOfManufacture() ).isEqualTo( 1934 );
assertThat( cars.get( 1 ).getManufacturingDate() ).isEqualTo( new GregorianCalendar( 1934, 0, 1 ).getTime() );
assertThat( cars.get( 1 ).getDriver().getName() ).isEqualTo( "Bill" );
}
@ -213,7 +250,7 @@ public class CarMapperTest extends MapperTestBase {
Car car = new Car(
"Morris",
2,
1980,
new GregorianCalendar( 1980, 0, 1 ).getTime(),
new Person( "Bob" ),
new ArrayList<Person>( Arrays.asList( new Person( "Alice" ), new Person( "Bill" ) ) )
);

View File

@ -16,12 +16,13 @@
package org.mapstruct.ap.test.model;
import java.util.ArrayList;
import java.util.Date;
public class Car {
private String make;
private int numberOfSeats;
private int yearOfManufacture;
private Date manufacturingDate;
private Person driver;
private ArrayList<Person> passengers;
private int price;
@ -30,10 +31,10 @@ public class Car {
public Car() {
}
public Car(String make, int numberOfSeats, int yearOfManufacture, Person driver, ArrayList<Person> passengers) {
public Car(String make, int numberOfSeats, Date manufacturingDate, Person driver, ArrayList<Person> passengers) {
this.make = make;
this.numberOfSeats = numberOfSeats;
this.yearOfManufacture = yearOfManufacture;
this.manufacturingDate = manufacturingDate;
this.driver = driver;
this.passengers = passengers;
}
@ -54,12 +55,12 @@ public class Car {
this.numberOfSeats = numberOfSeats;
}
public int getYearOfManufacture() {
return yearOfManufacture;
public Date getManufacturingDate() {
return manufacturingDate;
}
public void setYearOfManufacture(int yearOfManufacture) {
this.yearOfManufacture = yearOfManufacture;
public void setManufacturingDate(Date manufacturingDate) {
this.manufacturingDate = manufacturingDate;
}
public Person getDriver() {

View File

@ -22,14 +22,14 @@ import org.mapstruct.Mappers;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@Mapper
@Mapper(uses = DateMapper.class)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mappings({
@Mapping(source = "numberOfSeats", target = "seatCount"),
@Mapping(source = "yearOfManufacture", target = "manufacturingYear", converter = IntToStringConverter.class)
@Mapping(source = "manufacturingDate", target = "manufacturingYear")
})
CarDto carToCarDto(Car car);

View File

@ -15,17 +15,22 @@
*/
package org.mapstruct.ap.test.model;
import org.mapstruct.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class IntToStringConverter implements Converter<Integer, String> {
public class DateMapper {
@Override
public String from(Integer source) {
return source != null ? source.toString() : null;
public String asString(Date date) {
return date != null ? new SimpleDateFormat( "yyyy" ).format( date ) : null;
}
@Override
public Integer to(String target) {
return target != null ? Integer.valueOf( target ) : null;
public Date asDate(String date) {
try {
return date != null ? new SimpleDateFormat( "yyyy" ).parse( date ) : null;
}
catch ( ParseException e ) {
throw new RuntimeException( e );
}
}
}