mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1 Adding support for implicit mapping of enums
This commit is contained in:
parent
192cfc8937
commit
7121f22ff0
@ -52,6 +52,7 @@ import org.mapstruct.ap.model.source.MappedProperty;
|
|||||||
import org.mapstruct.ap.model.source.Mapping;
|
import org.mapstruct.ap.model.source.Mapping;
|
||||||
import org.mapstruct.ap.model.source.Method;
|
import org.mapstruct.ap.model.source.Method;
|
||||||
import org.mapstruct.ap.model.source.Parameter;
|
import org.mapstruct.ap.model.source.Parameter;
|
||||||
|
import org.mapstruct.ap.util.TypeUtil;
|
||||||
import org.mapstruct.ap.writer.ModelWriter;
|
import org.mapstruct.ap.writer.ModelWriter;
|
||||||
|
|
||||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||||
@ -66,11 +67,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
private final ProcessingEnvironment processingEnvironment;
|
private final ProcessingEnvironment processingEnvironment;
|
||||||
private final Types typeUtils;
|
private final Types typeUtils;
|
||||||
private final Elements elementUtils;
|
private final Elements elementUtils;
|
||||||
|
private final TypeUtil typeUtil;
|
||||||
|
|
||||||
public MapperGenerationVisitor(ProcessingEnvironment processingEnvironment) {
|
public MapperGenerationVisitor(ProcessingEnvironment processingEnvironment) {
|
||||||
this.processingEnvironment = processingEnvironment;
|
this.processingEnvironment = processingEnvironment;
|
||||||
this.typeUtils = processingEnvironment.getTypeUtils();
|
this.typeUtils = processingEnvironment.getTypeUtils();
|
||||||
this.elementUtils = processingEnvironment.getElementUtils();
|
this.elementUtils = processingEnvironment.getElementUtils();
|
||||||
|
this.typeUtil = new TypeUtil( elementUtils, typeUtils );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,6 +104,8 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
Set<Method> processedMethods = new HashSet<Method>();
|
Set<Method> processedMethods = new HashSet<Method>();
|
||||||
List<BeanMapping> mappings = new ArrayList<BeanMapping>();
|
List<BeanMapping> mappings = new ArrayList<BeanMapping>();
|
||||||
|
|
||||||
|
Conversions conversions = new Conversions( elementUtils, typeUtils, typeUtil );
|
||||||
|
|
||||||
for ( Method method : methods ) {
|
for ( Method method : methods ) {
|
||||||
if ( processedMethods.contains( method ) ) {
|
if ( processedMethods.contains( method ) ) {
|
||||||
continue;
|
continue;
|
||||||
@ -116,7 +121,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
Method rawReverseMappingMethod = getReverseMappingMethod( methods, method );
|
Method rawReverseMappingMethod = getReverseMappingMethod( methods, method );
|
||||||
if ( rawReverseMappingMethod != null ) {
|
if ( rawReverseMappingMethod != null ) {
|
||||||
processedMethods.add( rawReverseMappingMethod );
|
processedMethods.add( rawReverseMappingMethod );
|
||||||
// MappingMethod reverseElementMappingMethod = rawReverseElementMappingMethod == null ? null : new MappingMethod(rawReverseElementMappingMethod.getName(), rawReverseElementMappingMethod.getParameterName() );
|
|
||||||
|
|
||||||
reverseMappingMethod = new MappingMethod(
|
reverseMappingMethod = new MappingMethod(
|
||||||
rawReverseMappingMethod.getName(),
|
rawReverseMappingMethod.getName(),
|
||||||
@ -125,14 +129,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
||||||
|
|
||||||
for ( MappedProperty property : method.getMappedProperties() ) {
|
for ( MappedProperty property : method.getMappedProperties() ) {
|
||||||
Method propertyMappingMethod = getPropertyMappingMethod( methods, property );
|
Method propertyMappingMethod = getPropertyMappingMethod( methods, property );
|
||||||
Method reversePropertyMappingMethod = getReversePropertyMappingMethod( 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(
|
propertyMappings.add(
|
||||||
new PropertyMapping(
|
new PropertyMapping(
|
||||||
@ -152,12 +155,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
conversion != null ? conversion.to(
|
conversion != null ? conversion.to(
|
||||||
mappingMethod.getParameterName() + "." + getAccessor(
|
mappingMethod.getParameterName() + "." + getAccessor(
|
||||||
property.getSourceName()
|
property.getSourceName()
|
||||||
)
|
),
|
||||||
|
property.getTargetType()
|
||||||
) : null,
|
) : null,
|
||||||
conversion != null ? conversion.from(
|
conversion != null ? conversion.from(
|
||||||
reverseMappingMethod.getParameterName() + "." + getAccessor(
|
reverseMappingMethod.getParameterName() + "." + getAccessor(
|
||||||
property.getTargetName()
|
property.getTargetName()
|
||||||
)
|
),
|
||||||
|
property.getSourceType()
|
||||||
) : null
|
) : null
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -287,20 +292,12 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
|
|
||||||
for ( ExecutableElement getterMethod : getterMethodsIn( parameterElement.getEnclosedElements() ) ) {
|
for ( ExecutableElement getterMethod : getterMethodsIn( parameterElement.getEnclosedElements() ) ) {
|
||||||
|
|
||||||
String sourcePropertyName = Introspector.decapitalize(
|
String sourcePropertyName = getPropertyName( getterMethod );
|
||||||
getterMethod.getSimpleName()
|
|
||||||
.toString()
|
|
||||||
.substring( 3 )
|
|
||||||
);
|
|
||||||
Mapping mapping = mappings.get( sourcePropertyName );
|
Mapping mapping = mappings.get( sourcePropertyName );
|
||||||
|
|
||||||
for ( ExecutableElement setterMethod : setterMethodsIn( returnTypeElement.getEnclosedElements() ) ) {
|
for ( ExecutableElement setterMethod : setterMethodsIn( returnTypeElement.getEnclosedElements() ) ) {
|
||||||
|
|
||||||
String targetPropertyName = Introspector.decapitalize(
|
String targetPropertyName = getPropertyName( setterMethod );
|
||||||
setterMethod.getSimpleName()
|
|
||||||
.toString()
|
|
||||||
.substring( 3 )
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
|
if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
|
||||||
properties.add(
|
properties.add(
|
||||||
@ -319,6 +316,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPropertyName(ExecutableElement getterOrSetterMethod) {
|
||||||
|
//TODO consider is/has
|
||||||
|
return Introspector.decapitalize(
|
||||||
|
getterOrSetterMethod.getSimpleName().toString().substring( 3 )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, Mapping> getMappings(AnnotationMirror annotationMirror) {
|
private Map<String, Mapping> getMappings(AnnotationMirror annotationMirror) {
|
||||||
Map<String, Mapping> mappings = new HashMap<String, Mapping>();
|
Map<String, Mapping> mappings = new HashMap<String, Mapping>();
|
||||||
|
|
||||||
@ -344,25 +348,12 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
Type converterType = null;
|
Type converterType = null;
|
||||||
|
|
||||||
if ( converterTypeMirror != null ) {
|
if ( converterTypeMirror != null ) {
|
||||||
converterType = getType( (DeclaredType) converterTypeMirror );
|
converterType = typeUtil.getType( (DeclaredType) converterTypeMirror );
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Mapping( sourcePropertyName, targetPropertyName, converterType );
|
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) {
|
private Parameter retrieveParameter(ExecutableElement method) {
|
||||||
List<? extends VariableElement> parameters = method.getParameters();
|
List<? extends VariableElement> parameters = method.getParameters();
|
||||||
|
|
||||||
@ -375,26 +366,15 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
|
|
||||||
return new Parameter(
|
return new Parameter(
|
||||||
parameter.getSimpleName().toString(),
|
parameter.getSimpleName().toString(),
|
||||||
retrieveType( parameter.asType() )
|
typeUtil.retrieveType( parameter.asType() )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type retrieveReturnType(ExecutableElement method) {
|
private Type retrieveReturnType(ExecutableElement method) {
|
||||||
|
return typeUtil.retrieveType( method.getReturnType() );
|
||||||
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() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getStringValue(AnnotationMirror annotationMirror, String attributeName) {
|
private String getStringValue(AnnotationMirror annotationMirror, String attributeName) {
|
||||||
|
|
||||||
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
||||||
.entrySet() ) {
|
.entrySet() ) {
|
||||||
|
|
||||||
@ -407,7 +387,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TypeMirror getTypeMirrorValue(AnnotationMirror annotationMirror, String attributeName) {
|
private TypeMirror getTypeMirrorValue(AnnotationMirror annotationMirror, String attributeName) {
|
||||||
|
|
||||||
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
||||||
.entrySet() ) {
|
.entrySet() ) {
|
||||||
|
|
||||||
@ -420,7 +399,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<? extends AnnotationValue> getAnnotationValueListValue(AnnotationMirror annotationMirror, String attributeName) {
|
private List<? extends AnnotationValue> getAnnotationValueListValue(AnnotationMirror annotationMirror, String attributeName) {
|
||||||
|
|
||||||
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
||||||
.entrySet() ) {
|
.entrySet() ) {
|
||||||
|
|
||||||
@ -464,7 +442,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
return setterMethods;
|
return setterMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class NameDeterminationVisitor extends ElementKindVisitor6<String, Void> {
|
private static class NameDeterminationVisitor extends ElementKindVisitor6<String, Void> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,9 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.conversion;
|
package org.mapstruct.ap.conversion;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.model.Type;
|
||||||
|
|
||||||
public interface Conversion {
|
public interface Conversion {
|
||||||
|
|
||||||
String to(String sourcePropertyAccessor);
|
String to(String sourcePropertyAccessor, Type type);
|
||||||
|
|
||||||
String from(String targetPropertyAccessor);
|
String from(String targetPropertyAccessor, Type type);
|
||||||
}
|
}
|
||||||
|
@ -15,28 +15,45 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.conversion;
|
package org.mapstruct.ap.conversion;
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
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.model.Type;
|
||||||
|
import org.mapstruct.ap.util.TypeUtil;
|
||||||
|
|
||||||
import static org.mapstruct.ap.conversion.ReverseConversion.reverse;
|
import static org.mapstruct.ap.conversion.ReverseConversion.reverse;
|
||||||
|
|
||||||
public class Conversions {
|
public class Conversions {
|
||||||
|
|
||||||
private static ConcurrentMap<Key, Conversion> conversions = new ConcurrentHashMap<Conversions.Key, Conversion>();
|
private TypeUtil typeUtil;
|
||||||
|
private final Map<Key, Conversion> conversions = new HashMap<Conversions.Key, Conversion>();
|
||||||
|
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, Long.class, new IntLongConversion() );
|
||||||
register( int.class, String.class, new IntStringConversion() );
|
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( sourceType, targetType ), conversion );
|
||||||
conversions.put( Key.forClasses( targetType, sourceType ), reverse( 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 ) );
|
return conversions.get( new Key( sourceType, targetType ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +70,12 @@ public class Conversions {
|
|||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Key [sourceType=" + sourceType + ", targetType="
|
||||||
|
+ targetType + "]";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
@ -15,15 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.conversion;
|
package org.mapstruct.ap.conversion;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.model.Type;
|
||||||
|
|
||||||
public class IntLongConversion implements Conversion {
|
public class IntLongConversion implements Conversion {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String to(String sourcePropertyAccessor) {
|
public String to(String sourcePropertyAccessor, Type type) {
|
||||||
return "Long.valueOf( " + sourcePropertyAccessor + " )";
|
return "Long.valueOf( " + sourcePropertyAccessor + " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String from(String targetPropertyAccessor) {
|
public String from(String targetPropertyAccessor, Type type) {
|
||||||
return targetPropertyAccessor + ".intValue()";
|
return targetPropertyAccessor + ".intValue()";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.conversion;
|
package org.mapstruct.ap.conversion;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.model.Type;
|
||||||
|
|
||||||
public class IntStringConversion implements Conversion {
|
public class IntStringConversion implements Conversion {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String to(String sourcePropertyAccessor) {
|
public String to(String sourcePropertyAccessor, Type type) {
|
||||||
return "String.valueOf( " + sourcePropertyAccessor + " )";
|
return "String.valueOf( " + sourcePropertyAccessor + " )";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String from(String targetPropertyAccessor) {
|
public String from(String targetPropertyAccessor, Type type) {
|
||||||
return "Integer.parseInt( " + targetPropertyAccessor + " )";
|
return "Integer.parseInt( " + targetPropertyAccessor + " )";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.conversion;
|
package org.mapstruct.ap.conversion;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.model.Type;
|
||||||
|
|
||||||
public class ReverseConversion implements Conversion {
|
public class ReverseConversion implements Conversion {
|
||||||
|
|
||||||
private Conversion conversion;
|
private Conversion conversion;
|
||||||
@ -28,12 +30,12 @@ public class ReverseConversion implements Conversion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String to(String sourcePropertyAccessor) {
|
public String to(String sourcePropertyAccessor, Type type) {
|
||||||
return conversion.from( sourcePropertyAccessor );
|
return conversion.from( sourcePropertyAccessor, type );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String from(String targetPropertyAccessor) {
|
public String from(String targetPropertyAccessor, Type type) {
|
||||||
return conversion.to( targetPropertyAccessor );
|
return conversion.to( targetPropertyAccessor, type );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,13 @@ public class Type {
|
|||||||
private final String packageName;
|
private final String packageName;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Type elementType;
|
private final Type elementType;
|
||||||
|
private final boolean isEnumType;
|
||||||
|
|
||||||
public static Type forClass(Class<?> clazz) {
|
public static Type forClass(Class<?> clazz) {
|
||||||
Package pakkage = clazz.getPackage();
|
Package pakkage = clazz.getPackage();
|
||||||
|
|
||||||
if ( pakkage != null ) {
|
if ( pakkage != null ) {
|
||||||
return new Type( pakkage.getName(), clazz.getSimpleName() );
|
return new Type( pakkage.getName(), clazz.getSimpleName(), null, clazz.isEnum() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new Type( clazz.getSimpleName() );
|
return new Type( clazz.getSimpleName() );
|
||||||
@ -47,21 +47,18 @@ public class Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Type(String name) {
|
public Type(String name) {
|
||||||
this.packageName = null;
|
this( null, name, null, false );
|
||||||
this.name = name;
|
|
||||||
this.elementType = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type(String packageName, String name) {
|
public Type(String packageName, String name) {
|
||||||
this.packageName = packageName;
|
this( packageName, name, null, false );
|
||||||
this.name = name;
|
|
||||||
this.elementType = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type(String packageName, String name, Type elementType) {
|
public Type(String packageName, String name, Type elementType, boolean isEnumType) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.elementType = elementType;
|
this.elementType = elementType;
|
||||||
|
this.isEnumType = isEnumType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
@ -80,6 +77,10 @@ public class Type {
|
|||||||
return packageName == null && primitiveTypeNames.contains( name );
|
return packageName == null && primitiveTypeNames.contains( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnumType() {
|
||||||
|
return isEnumType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if ( packageName == null ) {
|
if ( packageName == null ) {
|
||||||
|
61
processor/src/main/java/org/mapstruct/ap/util/TypeUtil.java
Normal file
61
processor/src/main/java/org/mapstruct/ap/util/TypeUtil.java
Normal file
@ -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() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,10 @@ public class ${implementationName} implements ${interfaceName} {
|
|||||||
<#if beanMapping.iterableMapping == true>
|
<#if beanMapping.iterableMapping == true>
|
||||||
@Override
|
@Override
|
||||||
public ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.mappingMethod.parameterName}) {
|
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}>();
|
${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} ) {
|
for ( ${beanMapping.sourceType.elementType.name} ${beanMapping.sourceType.elementType.name?uncap_first} : ${beanMapping.mappingMethod.parameterName} ) {
|
||||||
@ -37,6 +41,10 @@ public class ${implementationName} implements ${interfaceName} {
|
|||||||
<#else>
|
<#else>
|
||||||
@Override
|
@Override
|
||||||
public ${beanMapping.targetType.name} ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name} ${beanMapping.mappingMethod.parameterName}) {
|
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}();
|
${beanMapping.targetType.name} ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}();
|
||||||
|
|
||||||
<#list beanMapping.propertyMappings as propertyMapping>
|
<#list beanMapping.propertyMappings as propertyMapping>
|
||||||
@ -65,6 +73,10 @@ public class ${implementationName} implements ${interfaceName} {
|
|||||||
<#if beanMapping.iterableMapping == true>
|
<#if beanMapping.iterableMapping == true>
|
||||||
@Override
|
@Override
|
||||||
public ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.reverseMappingMethod.parameterName}) {
|
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}>();
|
${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} ) {
|
for ( ${beanMapping.targetType.elementType.name} ${beanMapping.targetType.elementType.name?uncap_first} : ${beanMapping.reverseMappingMethod.parameterName} ) {
|
||||||
@ -76,6 +88,10 @@ public class ${implementationName} implements ${interfaceName} {
|
|||||||
<#else>
|
<#else>
|
||||||
@Override
|
@Override
|
||||||
public ${beanMapping.sourceType.name} ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name} ${beanMapping.reverseMappingMethod.parameterName}) {
|
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}();
|
${beanMapping.sourceType.name} ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}();
|
||||||
|
|
||||||
<#list beanMapping.propertyMappings as propertyMapping>
|
<#list beanMapping.propertyMappings as propertyMapping>
|
||||||
|
@ -25,6 +25,7 @@ import javax.tools.JavaFileObject;
|
|||||||
import org.mapstruct.ap.test.model.Car;
|
import org.mapstruct.ap.test.model.Car;
|
||||||
import org.mapstruct.ap.test.model.CarDto;
|
import org.mapstruct.ap.test.model.CarDto;
|
||||||
import org.mapstruct.ap.test.model.CarMapper;
|
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.IntToStringConverter;
|
||||||
import org.mapstruct.ap.test.model.Person;
|
import org.mapstruct.ap.test.model.Person;
|
||||||
import org.mapstruct.ap.test.model.PersonDto;
|
import org.mapstruct.ap.test.model.PersonDto;
|
||||||
@ -50,7 +51,8 @@ public class CarMapperTest extends MapperTestBase {
|
|||||||
Person.class,
|
Person.class,
|
||||||
PersonDto.class,
|
PersonDto.class,
|
||||||
CarMapper.class,
|
CarMapper.class,
|
||||||
IntToStringConverter.class
|
IntToStringConverter.class,
|
||||||
|
Category.class
|
||||||
);
|
);
|
||||||
|
|
||||||
boolean compilationSuccessful = compile( diagnostics, sourceFiles );
|
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( 0 ).getName() ).isEqualTo( "Alice" );
|
||||||
assertThat( car.getPassengers().get( 1 ).getName() ).isEqualTo( "Bill" );
|
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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ public class Car {
|
|||||||
private Person driver;
|
private Person driver;
|
||||||
private ArrayList<Person> passengers;
|
private ArrayList<Person> passengers;
|
||||||
private int price;
|
private int price;
|
||||||
|
private Category category;
|
||||||
|
|
||||||
public Car() {
|
public Car() {
|
||||||
}
|
}
|
||||||
@ -84,4 +85,12 @@ public class Car {
|
|||||||
public void setPrice(int price) {
|
public void setPrice(int price) {
|
||||||
this.price = price;
|
this.price = price;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Category getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(Category category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ public class CarDto {
|
|||||||
private PersonDto driver;
|
private PersonDto driver;
|
||||||
private ArrayList<PersonDto> passengers;
|
private ArrayList<PersonDto> passengers;
|
||||||
private Long price;
|
private Long price;
|
||||||
|
private String category;
|
||||||
|
|
||||||
public CarDto() {
|
public CarDto() {
|
||||||
}
|
}
|
||||||
@ -84,4 +85,12 @@ public class CarDto {
|
|||||||
public void setPrice(Long price) {
|
public void setPrice(Long price) {
|
||||||
this.price = price;
|
this.price = price;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(String category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user