From 7121f22ff0b7342fba3c6b7e079b1fe940f3e344 Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Sun, 3 Mar 2013 13:06:06 +0100 Subject: [PATCH] #1 Adding support for implicit mapping of enums --- .../mapstruct/ap/MapperGenerationVisitor.java | 67 ++++++------------- .../mapstruct/ap/conversion/Conversion.java | 6 +- .../mapstruct/ap/conversion/Conversions.java | 35 ++++++++-- .../ap/conversion/EnumStringConversion.java | 31 +++++++++ .../ap/conversion/IntLongConversion.java | 6 +- .../ap/conversion/IntStringConversion.java | 6 +- .../ap/conversion/ReverseConversion.java | 10 +-- .../java/org/mapstruct/ap/model/Type.java | 19 +++--- .../java/org/mapstruct/ap/util/TypeUtil.java | 61 +++++++++++++++++ .../main/resources/mapper-implementation.ftl | 16 +++++ .../org/mapstruct/ap/test/CarMapperTest.java | 30 ++++++++- .../java/org/mapstruct/ap/test/model/Car.java | 9 +++ .../org/mapstruct/ap/test/model/CarDto.java | 9 +++ .../org/mapstruct/ap/test/model/Category.java | 20 ++++++ 14 files changed, 254 insertions(+), 71 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/EnumStringConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/util/TypeUtil.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/model/Category.java diff --git a/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java b/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java index d6ec70618..c7bef65ea 100644 --- a/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java +++ b/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java @@ -52,6 +52,7 @@ import org.mapstruct.ap.model.source.MappedProperty; import org.mapstruct.ap.model.source.Mapping; import org.mapstruct.ap.model.source.Method; import org.mapstruct.ap.model.source.Parameter; +import org.mapstruct.ap.util.TypeUtil; import org.mapstruct.ap.writer.ModelWriter; import static javax.lang.model.util.ElementFilter.methodsIn; @@ -66,11 +67,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { private final ProcessingEnvironment processingEnvironment; private final Types typeUtils; private final Elements elementUtils; + private final TypeUtil typeUtil; public MapperGenerationVisitor(ProcessingEnvironment processingEnvironment) { this.processingEnvironment = processingEnvironment; this.typeUtils = processingEnvironment.getTypeUtils(); this.elementUtils = processingEnvironment.getElementUtils(); + this.typeUtil = new TypeUtil( elementUtils, typeUtils ); } @Override @@ -101,6 +104,8 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { Set processedMethods = new HashSet(); List mappings = new ArrayList(); + Conversions conversions = new Conversions( elementUtils, typeUtils, typeUtil ); + for ( Method method : methods ) { if ( processedMethods.contains( method ) ) { continue; @@ -116,7 +121,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { Method rawReverseMappingMethod = getReverseMappingMethod( methods, method ); if ( rawReverseMappingMethod != null ) { processedMethods.add( rawReverseMappingMethod ); -// MappingMethod reverseElementMappingMethod = rawReverseElementMappingMethod == null ? null : new MappingMethod(rawReverseElementMappingMethod.getName(), rawReverseElementMappingMethod.getParameterName() ); reverseMappingMethod = new MappingMethod( rawReverseMappingMethod.getName(), @@ -125,14 +129,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { ); } - List propertyMappings = new ArrayList(); for ( MappedProperty property : method.getMappedProperties() ) { Method propertyMappingMethod = getPropertyMappingMethod( methods, property ); Method reversePropertyMappingMethod = getReversePropertyMappingMethod( methods, property ); - Conversion conversion = Conversions.getConversion( property.getSourceType(), property.getTargetType() ); + Conversion conversion = conversions.getConversion( property.getSourceType(), property.getTargetType() ); propertyMappings.add( new PropertyMapping( @@ -152,12 +155,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { conversion != null ? conversion.to( mappingMethod.getParameterName() + "." + getAccessor( property.getSourceName() - ) + ), + property.getTargetType() ) : null, conversion != null ? conversion.from( reverseMappingMethod.getParameterName() + "." + getAccessor( property.getTargetName() - ) + ), + property.getSourceType() ) : null ) ); @@ -287,20 +292,12 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { for ( ExecutableElement getterMethod : getterMethodsIn( parameterElement.getEnclosedElements() ) ) { - String sourcePropertyName = Introspector.decapitalize( - getterMethod.getSimpleName() - .toString() - .substring( 3 ) - ); + String sourcePropertyName = getPropertyName( getterMethod ); Mapping mapping = mappings.get( sourcePropertyName ); for ( ExecutableElement setterMethod : setterMethodsIn( returnTypeElement.getEnclosedElements() ) ) { - String targetPropertyName = Introspector.decapitalize( - setterMethod.getSimpleName() - .toString() - .substring( 3 ) - ); + String targetPropertyName = getPropertyName( setterMethod ); if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) { properties.add( @@ -319,6 +316,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { return properties; } + private String getPropertyName(ExecutableElement getterOrSetterMethod) { + //TODO consider is/has + return Introspector.decapitalize( + getterOrSetterMethod.getSimpleName().toString().substring( 3 ) + ); + } + private Map getMappings(AnnotationMirror annotationMirror) { Map mappings = new HashMap(); @@ -344,25 +348,12 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { Type converterType = null; if ( converterTypeMirror != null ) { - converterType = getType( (DeclaredType) converterTypeMirror ); + converterType = typeUtil.getType( (DeclaredType) converterTypeMirror ); } return new Mapping( sourcePropertyName, targetPropertyName, converterType ); } - private Type getType(DeclaredType type) { - Type elementType = null; - if ( !type.getTypeArguments().isEmpty() ) { - elementType = retrieveType( type.getTypeArguments().iterator().next() ); - } - - return new Type( - elementUtils.getPackageOf( type.asElement() ).toString(), - type.asElement().getSimpleName().toString(), - elementType - ); - } - private Parameter retrieveParameter(ExecutableElement method) { List parameters = method.getParameters(); @@ -375,26 +366,15 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { return new Parameter( parameter.getSimpleName().toString(), - retrieveType( parameter.asType() ) + typeUtil.retrieveType( parameter.asType() ) ); } private Type retrieveReturnType(ExecutableElement method) { - - return retrieveType( method.getReturnType() ); - } - - private Type retrieveType(TypeMirror mirror) { - if ( mirror.getKind() == TypeKind.DECLARED ) { - return getType( ( (DeclaredType) mirror ) ); - } - else { - return new Type( null, mirror.toString() ); - } + return typeUtil.retrieveType( method.getReturnType() ); } private String getStringValue(AnnotationMirror annotationMirror, String attributeName) { - for ( Entry oneAttribute : annotationMirror.getElementValues() .entrySet() ) { @@ -407,7 +387,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { } private TypeMirror getTypeMirrorValue(AnnotationMirror annotationMirror, String attributeName) { - for ( Entry oneAttribute : annotationMirror.getElementValues() .entrySet() ) { @@ -420,7 +399,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { } private List getAnnotationValueListValue(AnnotationMirror annotationMirror, String attributeName) { - for ( Entry oneAttribute : annotationMirror.getElementValues() .entrySet() ) { @@ -464,7 +442,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6 { return setterMethods; } - private static class NameDeterminationVisitor extends ElementKindVisitor6 { @Override diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/Conversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/Conversion.java index b641fa988..51cb8fea0 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/Conversion.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/Conversion.java @@ -15,9 +15,11 @@ */ package org.mapstruct.ap.conversion; +import org.mapstruct.ap.model.Type; + public interface Conversion { - String to(String sourcePropertyAccessor); + String to(String sourcePropertyAccessor, Type type); - String from(String targetPropertyAccessor); + String from(String targetPropertyAccessor, Type type); } diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java index 9e7a5ca7d..6d7470d78 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java @@ -15,28 +15,45 @@ */ package org.mapstruct.ap.conversion; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +import java.util.HashMap; +import java.util.Map; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import org.mapstruct.ap.model.Type; +import org.mapstruct.ap.util.TypeUtil; import static org.mapstruct.ap.conversion.ReverseConversion.reverse; public class Conversions { - private static ConcurrentMap conversions = new ConcurrentHashMap(); + private TypeUtil typeUtil; + private final Map conversions = new HashMap(); + private final DeclaredType enumType; + private final DeclaredType stringType; + + public Conversions(Elements elementUtils, Types typeUtils, TypeUtil typeUtil) { + this.typeUtil = typeUtil; + + this.enumType = typeUtils.getDeclaredType( elementUtils.getTypeElement( Enum.class.getCanonicalName() ) ); + this.stringType = typeUtils.getDeclaredType( elementUtils.getTypeElement( String.class.getCanonicalName() ) ); - static { register( int.class, Long.class, new IntLongConversion() ); register( int.class, String.class, new IntStringConversion() ); + register( Enum.class, String.class, new EnumStringConversion() ); } - private static void register(Class sourceType, Class targetType, Conversion conversion) { + private void register(Class sourceType, Class targetType, Conversion conversion) { conversions.put( Key.forClasses( sourceType, targetType ), conversion ); conversions.put( Key.forClasses( targetType, sourceType ), reverse( conversion ) ); } - public static Conversion getConversion(Type sourceType, Type targetType) { + public Conversion getConversion(Type sourceType, Type targetType) { + if ( sourceType.isEnumType() && targetType.equals( typeUtil.getType( stringType ) ) ) { + sourceType = typeUtil.getType( enumType ); + } + return conversions.get( new Key( sourceType, targetType ) ); } @@ -53,6 +70,12 @@ public class Conversions { this.targetType = targetType; } + @Override + public String toString() { + return "Key [sourceType=" + sourceType + ", targetType=" + + targetType + "]"; + } + @Override public int hashCode() { final int prime = 31; diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/EnumStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/EnumStringConversion.java new file mode 100644 index 000000000..8ce134bca --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/EnumStringConversion.java @@ -0,0 +1,31 @@ +/** + * 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.ap.conversion; + +import org.mapstruct.ap.model.Type; + +public class EnumStringConversion implements Conversion { + + @Override + public String to(String sourcePropertyAccessor, Type type) { + return sourcePropertyAccessor + " != null ? " + sourcePropertyAccessor + ".toString() : null"; + } + + @Override + public String from(String targetPropertyAccessor, Type type) { + return targetPropertyAccessor + " != null ? Enum.valueOf( " + type.getName() + ".class, " + targetPropertyAccessor + " ) : null"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/IntLongConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/IntLongConversion.java index 109ffb650..353ec3f7a 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/IntLongConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/IntLongConversion.java @@ -15,15 +15,17 @@ */ package org.mapstruct.ap.conversion; +import org.mapstruct.ap.model.Type; + public class IntLongConversion implements Conversion { @Override - public String to(String sourcePropertyAccessor) { + public String to(String sourcePropertyAccessor, Type type) { return "Long.valueOf( " + sourcePropertyAccessor + " )"; } @Override - public String from(String targetPropertyAccessor) { + public String from(String targetPropertyAccessor, Type type) { return targetPropertyAccessor + ".intValue()"; } } diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/IntStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/IntStringConversion.java index 3000d6bb4..4f55ce443 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/IntStringConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/IntStringConversion.java @@ -15,15 +15,17 @@ */ package org.mapstruct.ap.conversion; +import org.mapstruct.ap.model.Type; + public class IntStringConversion implements Conversion { @Override - public String to(String sourcePropertyAccessor) { + public String to(String sourcePropertyAccessor, Type type) { return "String.valueOf( " + sourcePropertyAccessor + " )"; } @Override - public String from(String targetPropertyAccessor) { + public String from(String targetPropertyAccessor, Type type) { return "Integer.parseInt( " + targetPropertyAccessor + " )"; } } diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/ReverseConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/ReverseConversion.java index a3570377d..00cb99817 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/ReverseConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/ReverseConversion.java @@ -15,6 +15,8 @@ */ package org.mapstruct.ap.conversion; +import org.mapstruct.ap.model.Type; + public class ReverseConversion implements Conversion { private Conversion conversion; @@ -28,12 +30,12 @@ public class ReverseConversion implements Conversion { } @Override - public String to(String sourcePropertyAccessor) { - return conversion.from( sourcePropertyAccessor ); + public String to(String sourcePropertyAccessor, Type type) { + return conversion.from( sourcePropertyAccessor, type ); } @Override - public String from(String targetPropertyAccessor) { - return conversion.to( targetPropertyAccessor ); + public String from(String targetPropertyAccessor, Type type) { + return conversion.to( targetPropertyAccessor, type ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/Type.java b/processor/src/main/java/org/mapstruct/ap/model/Type.java index 1a1217c2e..7e147dd13 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Type.java @@ -33,13 +33,13 @@ public class Type { private final String packageName; private final String name; private final Type elementType; - + private final boolean isEnumType; public static Type forClass(Class clazz) { Package pakkage = clazz.getPackage(); if ( pakkage != null ) { - return new Type( pakkage.getName(), clazz.getSimpleName() ); + return new Type( pakkage.getName(), clazz.getSimpleName(), null, clazz.isEnum() ); } else { return new Type( clazz.getSimpleName() ); @@ -47,21 +47,18 @@ public class Type { } public Type(String name) { - this.packageName = null; - this.name = name; - this.elementType = null; + this( null, name, null, false ); } public Type(String packageName, String name) { - this.packageName = packageName; - this.name = name; - this.elementType = null; + this( packageName, name, null, false ); } - public Type(String packageName, String name, Type elementType) { + public Type(String packageName, String name, Type elementType, boolean isEnumType) { this.packageName = packageName; this.name = name; this.elementType = elementType; + this.isEnumType = isEnumType; } public String getPackageName() { @@ -80,6 +77,10 @@ public class Type { return packageName == null && primitiveTypeNames.contains( name ); } + public boolean isEnumType() { + return isEnumType; + } + @Override public String toString() { if ( packageName == null ) { diff --git a/processor/src/main/java/org/mapstruct/ap/util/TypeUtil.java b/processor/src/main/java/org/mapstruct/ap/util/TypeUtil.java new file mode 100644 index 000000000..c91c6797a --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/util/TypeUtil.java @@ -0,0 +1,61 @@ +/** + * 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.ap.util; + +import javax.lang.model.element.ElementKind; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; + +import org.mapstruct.ap.model.Type; + +public class TypeUtil { + + private final Elements elementUtils; + private final Types typeUtils; + + public TypeUtil(Elements elementUtils, Types typeUtils) { + this.elementUtils = elementUtils; + this.typeUtils = typeUtils; + } + + public Type getType(DeclaredType type) { + Type elementType = isIterableType( type ) ? retrieveType( type.getTypeArguments().iterator().next() ) : null; + + return new Type( + elementUtils.getPackageOf( type.asElement() ).toString(), + type.asElement().getSimpleName().toString(), + elementType, + type.asElement().getKind() == ElementKind.ENUM + ); + } + + private boolean isIterableType(DeclaredType type) { + TypeMirror iterableType = typeUtils.getDeclaredType( elementUtils.getTypeElement( Iterable.class.getCanonicalName() ) ); + return typeUtils.isSubtype( type, iterableType ); + } + + public Type retrieveType(TypeMirror mirror) { + if ( mirror.getKind() == TypeKind.DECLARED ) { + return getType( ( (DeclaredType) mirror ) ); + } + else { + return new Type( mirror.toString() ); + } + } +} diff --git a/processor/src/main/resources/mapper-implementation.ftl b/processor/src/main/resources/mapper-implementation.ftl index 75b92a236..cf40388b3 100644 --- a/processor/src/main/resources/mapper-implementation.ftl +++ b/processor/src/main/resources/mapper-implementation.ftl @@ -26,6 +26,10 @@ public class ${implementationName} implements ${interfaceName} { <#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}) { + if( ${beanMapping.mappingMethod.parameterName} == null ) { + return new ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}>(); + } + ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}>(); for ( ${beanMapping.sourceType.elementType.name} ${beanMapping.sourceType.elementType.name?uncap_first} : ${beanMapping.mappingMethod.parameterName} ) { @@ -37,6 +41,10 @@ public class ${implementationName} implements ${interfaceName} { <#else> @Override public ${beanMapping.targetType.name} ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name} ${beanMapping.mappingMethod.parameterName}) { + if( ${beanMapping.mappingMethod.parameterName} == null ) { + return null; + } + ${beanMapping.targetType.name} ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}(); <#list beanMapping.propertyMappings as propertyMapping> @@ -65,6 +73,10 @@ public class ${implementationName} implements ${interfaceName} { <#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}) { + if( ${beanMapping.reverseMappingMethod.parameterName} == null ) { + return new ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}>(); + } + ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}>(); for ( ${beanMapping.targetType.elementType.name} ${beanMapping.targetType.elementType.name?uncap_first} : ${beanMapping.reverseMappingMethod.parameterName} ) { @@ -76,6 +88,10 @@ public class ${implementationName} implements ${interfaceName} { <#else> @Override public ${beanMapping.sourceType.name} ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name} ${beanMapping.reverseMappingMethod.parameterName}) { + if( ${beanMapping.reverseMappingMethod.parameterName} == null ) { + return null; + } + ${beanMapping.sourceType.name} ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}(); <#list beanMapping.propertyMappings as propertyMapping> diff --git a/processor/src/test/java/org/mapstruct/ap/test/CarMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/CarMapperTest.java index ebd85fcf0..e4d648185 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/CarMapperTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/CarMapperTest.java @@ -25,6 +25,7 @@ import javax.tools.JavaFileObject; 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.Person; import org.mapstruct.ap.test.model.PersonDto; @@ -50,7 +51,8 @@ public class CarMapperTest extends MapperTestBase { Person.class, PersonDto.class, CarMapper.class, - IntToStringConverter.class + IntToStringConverter.class, + Category.class ); boolean compilationSuccessful = compile( diagnostics, sourceFiles ); @@ -248,4 +250,30 @@ public class CarMapperTest extends MapperTestBase { assertThat( car.getPassengers().get( 0 ).getName() ).isEqualTo( "Alice" ); assertThat( car.getPassengers().get( 1 ).getName() ).isEqualTo( "Bill" ); } + + @Test + public void shouldMapEnumToString() { + //given + Car car = new Car(); + car.setCategory( Category.CONVERTIBLE ); + //when + CarDto carDto = CarMapper.INSTANCE.carToCarDto( car ); + + //then + assertThat( carDto ).isNotNull(); + assertThat( carDto.getCategory() ).isEqualTo( "CONVERTIBLE" ); + } + + @Test + public void shouldMapStringToEnum() { + //given + CarDto carDto = new CarDto(); + carDto.setCategory( "CONVERTIBLE" ); + //when + Car car = CarMapper.INSTANCE.carDtoToCar( carDto ); + + //then + assertThat( car ).isNotNull(); + assertThat( car.getCategory() ).isEqualTo( Category.CONVERTIBLE ); + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/model/Car.java b/processor/src/test/java/org/mapstruct/ap/test/model/Car.java index c24e74d97..d2abb9345 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/model/Car.java +++ b/processor/src/test/java/org/mapstruct/ap/test/model/Car.java @@ -25,6 +25,7 @@ public class Car { private Person driver; private ArrayList passengers; private int price; + private Category category; public Car() { } @@ -84,4 +85,12 @@ public class Car { public void setPrice(int price) { this.price = price; } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/model/CarDto.java b/processor/src/test/java/org/mapstruct/ap/test/model/CarDto.java index 74eb8226b..76bdf41c2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/model/CarDto.java +++ b/processor/src/test/java/org/mapstruct/ap/test/model/CarDto.java @@ -25,6 +25,7 @@ public class CarDto { private PersonDto driver; private ArrayList passengers; private Long price; + private String category; public CarDto() { } @@ -84,4 +85,12 @@ public class CarDto { public void setPrice(Long price) { this.price = price; } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/model/Category.java b/processor/src/test/java/org/mapstruct/ap/test/model/Category.java new file mode 100644 index 000000000..bf9cfc548 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/model/Category.java @@ -0,0 +1,20 @@ +/** + * 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.ap.test.model; + +public enum Category { + SEDAN, CONVERTIBLE, TRUCK; +}