From e07add7d4341fcf69bc55e79dfb45e0196f6da35 Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Mon, 28 May 2012 23:15:13 +0200 Subject: [PATCH] Adding support for multiple bindings, adding converters --- .../src/main/java/de/moapa/maple/Mapping.java | 5 + .../main/java/de/moapa/maple/Mappings.java | 22 +++ .../de/moapa/maple/converter/Converter.java | 23 +++ .../moapa/maple/converter/NoOpConverter.java | 29 ++++ .../maple/ap/MapperGenerationVisitor.java | 147 ++++++++++++++++-- .../java/de/moapa/maple/ap/model/Binding.java | 23 ++- .../de/moapa/maple/ap/model/Converter.java | 42 +++++ .../java/de/moapa/maple/ap/model/Mapper.java | 29 ++++ .../resources/dozer-mapper-implementation.ftl | 28 +++- .../de/moapa/maple/ap/test/CarMapperTest.java | 37 ++++- .../de/moapa/maple/ap/test/model/Car.java | 13 +- .../de/moapa/maple/ap/test/model/CarDto.java | 13 +- .../moapa/maple/ap/test/model/CarMapper.java | 6 +- .../ap/test/model/IntToStringConverter.java | 31 ++++ 14 files changed, 423 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/de/moapa/maple/Mappings.java create mode 100644 core/src/main/java/de/moapa/maple/converter/Converter.java create mode 100644 core/src/main/java/de/moapa/maple/converter/NoOpConverter.java create mode 100644 processor/src/main/java/de/moapa/maple/ap/model/Converter.java create mode 100644 processor/src/test/java/de/moapa/maple/ap/test/model/IntToStringConverter.java diff --git a/core/src/main/java/de/moapa/maple/Mapping.java b/core/src/main/java/de/moapa/maple/Mapping.java index 36b675d32..dd4fcf160 100644 --- a/core/src/main/java/de/moapa/maple/Mapping.java +++ b/core/src/main/java/de/moapa/maple/Mapping.java @@ -15,10 +15,15 @@ */ package de.moapa.maple; +import de.moapa.maple.converter.Converter; +import de.moapa.maple.converter.NoOpConverter; + public @interface Mapping { String source(); String target(); + Class> converter() default NoOpConverter.class; + } diff --git a/core/src/main/java/de/moapa/maple/Mappings.java b/core/src/main/java/de/moapa/maple/Mappings.java new file mode 100644 index 000000000..3dcc96fe9 --- /dev/null +++ b/core/src/main/java/de/moapa/maple/Mappings.java @@ -0,0 +1,22 @@ +/** + * Copyright 2012 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 de.moapa.maple; + + +public @interface Mappings { + + Mapping[] value(); +} diff --git a/core/src/main/java/de/moapa/maple/converter/Converter.java b/core/src/main/java/de/moapa/maple/converter/Converter.java new file mode 100644 index 000000000..764e3fec9 --- /dev/null +++ b/core/src/main/java/de/moapa/maple/converter/Converter.java @@ -0,0 +1,23 @@ +/** + * Copyright 2012 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 de.moapa.maple.converter; + +public interface Converter { + + T from(S source); + + S to(T target); +} diff --git a/core/src/main/java/de/moapa/maple/converter/NoOpConverter.java b/core/src/main/java/de/moapa/maple/converter/NoOpConverter.java new file mode 100644 index 000000000..9872b6b8c --- /dev/null +++ b/core/src/main/java/de/moapa/maple/converter/NoOpConverter.java @@ -0,0 +1,29 @@ +/** + * Copyright 2012 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 de.moapa.maple.converter; + +public class NoOpConverter implements Converter { + + @Override + public Object from(Object source) { + return source; + } + + @Override + public Object to(Object target) { + return target; + } +} diff --git a/processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java b/processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java index 2b62b8019..01ff575e0 100644 --- a/processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java +++ b/processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java @@ -17,6 +17,7 @@ package de.moapa.maple.ap; import java.io.BufferedWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map.Entry; import javax.annotation.processing.ProcessingEnvironment; @@ -26,8 +27,13 @@ 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.TypeMirror; import javax.lang.model.util.ElementKindVisitor6; +import javax.lang.model.util.Elements; import javax.lang.model.util.SimpleAnnotationValueVisitor6; +import javax.lang.model.util.TypeKindVisitor6; +import javax.lang.model.util.Types; import javax.tools.JavaFileObject; import de.moapa.maple.ap.model.Binding; @@ -48,12 +54,24 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { private final static String MAPPING_ANNOTATION = "de.moapa.maple.Mapping"; + private final static String MAPPINGS_ANNOTATION = "de.moapa.maple.Mappings"; + + private final static String CONVERTER_TYPE = "de.moapa.maple.converter.Converter"; + private final ProcessingEnvironment processingEnvironment; private final Configuration configuration; + private final Types typeUtils; + + private final Elements elementUtils; + public MapperGenerationVisitor(ProcessingEnvironment processingEnvironment, Configuration configuration) { + this.processingEnvironment = processingEnvironment; + this.typeUtils = processingEnvironment.getTypeUtils(); + this.elementUtils = processingEnvironment.getElementUtils(); + this.configuration = configuration; } @@ -86,7 +104,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { private Mapper retrieveModel(TypeElement element) { return new Mapper( - processingEnvironment.getElementUtils().getPackageOf( element ).getQualifiedName().toString(), + elementUtils.getPackageOf( element ).getQualifiedName().toString(), element.getSimpleName() + IMPLEMENTATION_SUFFIX, element.getSimpleName().toString(), retrieveMethods( element ) @@ -128,6 +146,33 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { if ( MAPPING_ANNOTATION.equals( annotationName ) ) { bindings.add( retrieveBinding( annotationMirror ) ); } + else if ( MAPPINGS_ANNOTATION.equals( annotationName ) ) { + bindings.addAll( retrieveBindings( annotationMirror ) ); + } + } + + return bindings; + } + + private List retrieveBindings(AnnotationMirror annotationMirror) { + + List bindings = new ArrayList(); + + for ( Entry oneAttribute : annotationMirror.getElementValues() + .entrySet() ) { + + if ( oneAttribute.getKey().getSimpleName().contentEquals( "value" ) ) { + List values = oneAttribute.getValue() + .accept( new AnnotationValueListRetrievingVisitor(), null ); + + for ( AnnotationValue oneAnnotationValue : values ) { + AnnotationMirror oneAnnotation = oneAnnotationValue.accept( + new AnnotationRetrievingVisitor(), + null + ); + bindings.add( retrieveBinding( oneAnnotation ) ); + } + } } return bindings; @@ -137,19 +182,60 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { String sourcePropertyName = null; String targetPropertyName = null; + Type converterType = null; + Type sourceType = null; + Type targetType = null; for ( Entry oneAttribute : annotationMirror.getElementValues() .entrySet() ) { if ( oneAttribute.getKey().getSimpleName().contentEquals( "source" ) ) { - sourcePropertyName = oneAttribute.getValue().accept( new ValueRetrievingVisitor(), null ); + sourcePropertyName = oneAttribute.getValue().accept( new StringValueRetrievingVisitor(), null ); } else if ( oneAttribute.getKey().getSimpleName().contentEquals( "target" ) ) { - targetPropertyName = oneAttribute.getValue().accept( new ValueRetrievingVisitor(), null ); + targetPropertyName = oneAttribute.getValue().accept( new StringValueRetrievingVisitor(), null ); + } + else if ( oneAttribute.getKey().getSimpleName().contentEquals( "converter" ) ) { + TypeMirror converterTypeMirror = oneAttribute.getValue() + .accept( + new TypeRetrievingVisitor(), null + ); + + converterType = getType( typeUtils.asElement( converterTypeMirror ) ); + + List converterTypeParameters = getTypeParameters( + converterTypeMirror, + CONVERTER_TYPE + ); + + sourceType = getType( typeUtils.asElement( converterTypeParameters.get( 0 ) ) ); + targetType = getType( typeUtils.asElement( converterTypeParameters.get( 1 ) ) ); } } - return new Binding( sourcePropertyName, targetPropertyName ); + return new Binding( sourceType, sourcePropertyName, targetType, targetPropertyName, converterType ); + } + + private Type getType(Element sourceTypeElement) { + return new Type( + elementUtils.getPackageOf( sourceTypeElement ).toString(), + sourceTypeElement.getSimpleName().toString() + ); + } + + //TODO: consider complete type hierarchy + private List getTypeParameters(TypeMirror type, String superTypeName) { + + for ( TypeMirror oneSuperType : typeUtils.directSupertypes( type ) ) { + String oneSuperTypeName = typeUtils.asElement( oneSuperType ) + .accept( new NameDeterminationVisitor(), null ); + + if ( oneSuperTypeName.equals( superTypeName ) ) { + return oneSuperType.accept( new TypeParameterDeterminationVisitor(), null ); + } + } + + return Collections.emptyList(); } private Parameter retrieveParameter(ExecutableElement method) { @@ -161,31 +247,35 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { return null; } + VariableElement parameter = parameters.get( 0 ); + return new Parameter( - parameters.get( 0 ).getSimpleName().toString(), + parameter.getSimpleName().toString(), new Type( - processingEnvironment.getElementUtils() - .getPackageOf( parameters.get( 0 ) ) - .getQualifiedName() - .toString(), - processingEnvironment.getTypeUtils() - .asElement( parameters.get( 0 ).asType() ) - .getSimpleName() - .toString() + elementUtils.getPackageOf( parameter ).getQualifiedName().toString(), + typeUtils.asElement( parameter.asType() ).getSimpleName().toString() ) ); } private Type retrieveReturnType(ExecutableElement method) { - Element returnTypeElement = processingEnvironment.getTypeUtils().asElement( method.getReturnType() ); + Element returnTypeElement = typeUtils.asElement( method.getReturnType() ); return new Type( - processingEnvironment.getElementUtils().getPackageOf( returnTypeElement ).getQualifiedName().toString(), + elementUtils.getPackageOf( returnTypeElement ).getQualifiedName().toString(), returnTypeElement.getSimpleName().toString() ); } + private static class TypeParameterDeterminationVisitor extends TypeKindVisitor6, Void> { + + @Override + public List visitDeclared(DeclaredType type, Void p) { + return type.getTypeArguments(); + } + } + private static class NameDeterminationVisitor extends ElementKindVisitor6 { @Override @@ -194,12 +284,37 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { } } - private static class ValueRetrievingVisitor extends SimpleAnnotationValueVisitor6 { + private static class StringValueRetrievingVisitor extends SimpleAnnotationValueVisitor6 { @Override public String visitString(String value, Void p) { return value; } + } + private static class TypeRetrievingVisitor + extends SimpleAnnotationValueVisitor6 { + + @Override + public TypeMirror visitType(TypeMirror value, Void p) { + return value; + } + } + + private static class AnnotationValueListRetrievingVisitor + extends SimpleAnnotationValueVisitor6, Void> { + + @Override + public List visitArray(List value, Void p) { + return value; + } + } + + private static class AnnotationRetrievingVisitor extends SimpleAnnotationValueVisitor6 { + + @Override + public AnnotationMirror visitAnnotation(AnnotationMirror value, Void p) { + return value; + } } } diff --git a/processor/src/main/java/de/moapa/maple/ap/model/Binding.java b/processor/src/main/java/de/moapa/maple/ap/model/Binding.java index 19b0b7252..475e9335d 100644 --- a/processor/src/main/java/de/moapa/maple/ap/model/Binding.java +++ b/processor/src/main/java/de/moapa/maple/ap/model/Binding.java @@ -17,21 +17,42 @@ package de.moapa.maple.ap.model; public class Binding { + private final Type sourceType; + private final String sourceProperty; + private final Type targetType; + private final String targetProperty; - public Binding(String sourceProperty, String targetProperty) { + private final Type converterType; + public Binding(Type sourceType, String sourceProperty, Type targetType, String targetProperty, Type converterType) { + + this.sourceType = sourceType; this.sourceProperty = sourceProperty; + this.targetType = targetType; this.targetProperty = targetProperty; + this.converterType = converterType; + } + + public Type getSourceType() { + return sourceType; } public String getSourceProperty() { return sourceProperty; } + public Type getTargetType() { + return targetType; + } + public String getTargetProperty() { return targetProperty; } + + public Type getConverterType() { + return converterType; + } } diff --git a/processor/src/main/java/de/moapa/maple/ap/model/Converter.java b/processor/src/main/java/de/moapa/maple/ap/model/Converter.java new file mode 100644 index 000000000..8cbd78b31 --- /dev/null +++ b/processor/src/main/java/de/moapa/maple/ap/model/Converter.java @@ -0,0 +1,42 @@ +/** + * Copyright 2012 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 de.moapa.maple.ap.model; + +public class Converter { + + private final Type converterType; + private final Type sourceType; + private final Type targetType; + + public Converter(Type converterType, Type sourceType, Type targetType) { + + this.converterType = converterType; + this.sourceType = sourceType; + this.targetType = targetType; + } + + public Type getConverterType() { + return converterType; + } + + public Type getSourceType() { + return sourceType; + } + + public Type getTargetType() { + return targetType; + } +} diff --git a/processor/src/main/java/de/moapa/maple/ap/model/Mapper.java b/processor/src/main/java/de/moapa/maple/ap/model/Mapper.java index 5e1e44f6b..186cbaf85 100644 --- a/processor/src/main/java/de/moapa/maple/ap/model/Mapper.java +++ b/processor/src/main/java/de/moapa/maple/ap/model/Mapper.java @@ -15,6 +15,7 @@ */ package de.moapa.maple.ap.model; +import java.util.ArrayList; import java.util.List; public class Mapper { @@ -27,11 +28,35 @@ public class Mapper { private final List mapperMethods; + private final List converters; + public Mapper(String packageName, String implementationType, String interfaceType, List mapperMethods) { this.packageName = packageName; this.implementationType = implementationType; this.interfaceType = interfaceType; this.mapperMethods = mapperMethods; + this.converters = collectConverters( mapperMethods ); + } + + private List collectConverters(List mapperMethods) { + + List converters = new ArrayList(); + + for ( MapperMethod oneMapperMethod : mapperMethods ) { + for ( Binding oneBinding : oneMapperMethod.getBindings() ) { + if ( oneBinding.getConverterType() != null ) { + converters.add( + new Converter( + oneBinding.getConverterType(), + oneBinding.getSourceType(), + oneBinding.getTargetType() + ) + ); + } + } + } + + return converters; } public String getPackageName() { @@ -49,4 +74,8 @@ public class Mapper { public List getMapperMethods() { return mapperMethods; } + + public List getConverters() { + return converters; + } } diff --git a/processor/src/main/resources/dozer-mapper-implementation.ftl b/processor/src/main/resources/dozer-mapper-implementation.ftl index 237e31b6a..f3a9ebbce 100644 --- a/processor/src/main/resources/dozer-mapper-implementation.ftl +++ b/processor/src/main/resources/dozer-mapper-implementation.ftl @@ -17,9 +17,14 @@ --> package ${packageName}; +import org.dozer.DozerConverter; import org.dozer.DozerBeanMapper; import org.dozer.loader.api.BeanMappingBuilder; +import de.moapa.maple.converter.Converter; + +import static org.dozer.loader.api.FieldsMappingOptions.*; + public class ${implementationType} implements ${interfaceType} { private final DozerBeanMapper mapper; @@ -35,7 +40,7 @@ public class ${implementationType} implements ${interfaceType} { protected void configure() { mapping( ${oneMethod.parameter.type.name}.class, ${oneMethod.returnType.name}.class ) <#list oneMethod.bindings as oneBinding> - .fields("${oneBinding.sourceProperty}", "${oneBinding.targetProperty}") + .fields( "${oneBinding.sourceProperty}", "${oneBinding.targetProperty}"<#if oneBinding.converterType??>, customConverter( ${oneBinding.converterType.name}DozerAdapter.class ) ) ; } @@ -51,4 +56,25 @@ public class ${implementationType} implements ${interfaceType} { return mapper.map(${oneMethod.parameter.name}, ${oneMethod.returnType.name}.class); } + + <#list converters as oneConverter> + public static class ${oneConverter.converterType.name}DozerAdapter extends DozerConverter<${oneConverter.sourceType.name}, ${oneConverter.targetType.name}> { + + private final Converter<${oneConverter.sourceType.name}, ${oneConverter.targetType.name}> converter = new ${oneConverter.converterType.name}(); + + public ${oneConverter.converterType.name}DozerAdapter() { + super(${oneConverter.sourceType.name}.class, ${oneConverter.targetType.name}.class); + } + + @Override + public String convertTo(${oneConverter.sourceType.name} source, ${oneConverter.targetType.name} destination) { + return converter.from(source); + } + + @Override + public ${oneConverter.sourceType.name} convertFrom(${oneConverter.targetType.name} source, ${oneConverter.sourceType.name} destination) { + return converter.to(source); + } + } + } diff --git a/processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java b/processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java index 1427a02b1..2af0f3042 100644 --- a/processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java +++ b/processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java @@ -34,6 +34,7 @@ import de.moapa.maple.ap.MappingProcessor; import de.moapa.maple.ap.test.model.Car; import de.moapa.maple.ap.test.model.CarDto; import de.moapa.maple.ap.test.model.CarMapper; +import de.moapa.maple.ap.test.model.IntToStringConverter; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -83,7 +84,7 @@ public class CarMapperTest { public void generateMapperImplementation() { diagnostics = new DiagnosticCollector(); - File[] sourceFiles = getSourceFiles( Car.class, CarDto.class, CarMapper.class ); + File[] sourceFiles = getSourceFiles( Car.class, CarDto.class, CarMapper.class, IntToStringConverter.class ); boolean compilationSuccessful = compile( diagnostics, sourceFiles ); @@ -101,7 +102,7 @@ public class CarMapperTest { public void shouldMapAttributeByName() { //given - Car car = new Car( "Morris", 2 ); + Car car = new Car( "Morris", 2, 1980 ); //when CarDto carDto = CarMapper.INSTANCE.carToCarDto( car ); @@ -115,7 +116,7 @@ public class CarMapperTest { public void shouldMapAttributeWithCustomMapping() { //given - Car car = new Car( "Morris", 2 ); + Car car = new Car( "Morris", 2, 1980 ); //when CarDto carDto = CarMapper.INSTANCE.carToCarDto( car ); @@ -129,7 +130,7 @@ public class CarMapperTest { public void shouldConsiderCustomMappingForReverseMapping() { //given - CarDto carDto = new CarDto( "Morris", 2 ); + CarDto carDto = new CarDto( "Morris", 2, "1980" ); //when Car car = CarMapper.INSTANCE.carDtoToCar( carDto ); @@ -139,6 +140,34 @@ public class CarMapperTest { assertThat( car.getNumberOfSeats() ).isEqualTo( carDto.getSeatCount() ); } + @Test + public void shouldApplyConverter() { + + //given + Car car = new Car( "Morris", 2, 1980 ); + + //when + CarDto carDto = CarMapper.INSTANCE.carToCarDto( car ); + + //then + assertThat( carDto ).isNotNull(); + assertThat( carDto.getManufacturingYear() ).isEqualTo( "1980" ); + } + + @Test + public void shouldApplyConverterForReverseMapping() { + + //given + CarDto carDto = new CarDto( "Morris", 2, "1980" ); + + //when + Car car = CarMapper.INSTANCE.carDtoToCar( carDto ); + + //then + assertThat( car ).isNotNull(); + assertThat( car.getYearOfManufacture() ).isEqualTo( 1980 ); + } + private File[] getSourceFiles(Class... clazz) { File[] sourceFiles = new File[clazz.length]; diff --git a/processor/src/test/java/de/moapa/maple/ap/test/model/Car.java b/processor/src/test/java/de/moapa/maple/ap/test/model/Car.java index bffd9e100..9a6d0bb29 100644 --- a/processor/src/test/java/de/moapa/maple/ap/test/model/Car.java +++ b/processor/src/test/java/de/moapa/maple/ap/test/model/Car.java @@ -21,12 +21,15 @@ public class Car { private int numberOfSeats; + private int yearOfManufacture; + public Car() { } - public Car(String make, int numberOfSeats) { + public Car(String make, int numberOfSeats, int yearOfManufacture) { this.make = make; this.numberOfSeats = numberOfSeats; + this.yearOfManufacture = yearOfManufacture; } public String getMake() { @@ -44,4 +47,12 @@ public class Car { public void setNumberOfSeats(int numberOfSeats) { this.numberOfSeats = numberOfSeats; } + + public int getYearOfManufacture() { + return yearOfManufacture; + } + + public void setYearOfManufacture(int yearOfManufacture) { + this.yearOfManufacture = yearOfManufacture; + } } diff --git a/processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java b/processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java index e243f71a8..da332de16 100644 --- a/processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java +++ b/processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java @@ -21,12 +21,15 @@ public class CarDto { private int seatCount; + private String manufacturingYear; + public CarDto() { } - public CarDto(String make, int seatCount) { + public CarDto(String make, int seatCount, String manufacturingYear) { this.make = make; this.seatCount = seatCount; + this.manufacturingYear = manufacturingYear; } public String getMake() { @@ -44,4 +47,12 @@ public class CarDto { public void setSeatCount(int seatCount) { this.seatCount = seatCount; } + + public String getManufacturingYear() { + return manufacturingYear; + } + + public void setManufacturingYear(String manufacturingYear) { + this.manufacturingYear = manufacturingYear; + } } diff --git a/processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java b/processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java index 6f57844fe..cccda75e3 100644 --- a/processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java +++ b/processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java @@ -18,13 +18,17 @@ package de.moapa.maple.ap.test.model; import de.moapa.maple.Mapper; import de.moapa.maple.Mappers; import de.moapa.maple.Mapping; +import de.moapa.maple.Mappings; @Mapper public interface CarMapper { CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); - @Mapping(source = "numberOfSeats", target = "seatCount") + @Mappings({ + @Mapping(source = "numberOfSeats", target = "seatCount"), + @Mapping(source = "yearOfManufacture", target = "manufacturingYear", converter = IntToStringConverter.class) + }) CarDto carToCarDto(Car car); Car carDtoToCar(CarDto carDto); diff --git a/processor/src/test/java/de/moapa/maple/ap/test/model/IntToStringConverter.java b/processor/src/test/java/de/moapa/maple/ap/test/model/IntToStringConverter.java new file mode 100644 index 000000000..7d38893ed --- /dev/null +++ b/processor/src/test/java/de/moapa/maple/ap/test/model/IntToStringConverter.java @@ -0,0 +1,31 @@ +/** + * Copyright 2012 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 de.moapa.maple.ap.test.model; + +import de.moapa.maple.converter.Converter; + +public class IntToStringConverter implements Converter { + + @Override + public String from(Integer source) { + return source != null ? source.toString() : null; + } + + @Override + public Integer to(String target) { + return target != null ? Integer.valueOf( target ) : null; + } +}