#157 moving duplicated code from MapperCreationProcessor (PropertyMapping, IterableMapping and MapMapping) to MappingResolver

This commit is contained in:
sjaakd 2014-03-15 11:32:55 +01:00
parent 59719dc6cb
commit 6f68512406
3 changed files with 168 additions and 121 deletions

View File

@ -0,0 +1,58 @@
/**
* Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.model;
/**
* This class carries the possible ways to do an assignment to a parameter on a mapping target
*
* The following options exist:
* <ol>
* <li>MethodReference</li>
* <li>TypeConversion</li>
* <li>Simple Assignment (empty ParameterAssignment)</li>
* </ol>
*
* @author Sjaak Derksen
*/
public class ParameterAssignment {
private MethodReference methodReference;
private TypeConversion typeConversion;
public ParameterAssignment() {
}
public ParameterAssignment( MethodReference methodReference ) {
this.methodReference = methodReference;
}
public ParameterAssignment( TypeConversion typeConversion ) {
this.typeConversion = typeConversion;
}
public MethodReference getMethodReference() {
return methodReference;
}
public TypeConversion getTypeConversion() {
return typeConversion;
}
}

View File

@ -18,6 +18,7 @@
*/
package org.mapstruct.ap.processor;
import org.mapstruct.ap.model.ParameterAssignment;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
@ -48,7 +49,6 @@ import org.mapstruct.ap.model.MapperReference;
import org.mapstruct.ap.model.MappingMethod;
import org.mapstruct.ap.model.MethodReference;
import org.mapstruct.ap.model.PropertyMapping;
import org.mapstruct.ap.model.TypeConversion;
import org.mapstruct.ap.model.common.Parameter;
import org.mapstruct.ap.model.common.Type;
import org.mapstruct.ap.model.common.TypeFactory;
@ -79,7 +79,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
private TypeFactory typeFactory;
private MappingMethodResolver mappingMethodResolver;
private MappingResolver mappingResolver;
@ -92,7 +92,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
this.typeFactory = context.getTypeFactory();
this.mappingMethodResolver = new MappingMethodResolver(messager, typeFactory, elementUtils, typeUtils );
this.mappingResolver = new MappingResolver(messager, typeFactory, elementUtils, typeUtils );
return getMapper( mapperTypeElement, sourceModel );
@ -107,7 +107,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element );
List<MapperReference> mapperReferences = getReferencedMappers( element );
List<MappingMethod> mappingMethods = getMappingMethods( mapperReferences, methods, unmappedTargetPolicy );
mappingMethods.addAll( mappingMethodResolver.getVirtualMethodsToCreate() );
mappingMethods.addAll( mappingResolver.getVirtualMethodsToGenerate() );
Mapper mapper = new Mapper.Builder()
.element( element )
@ -641,7 +641,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
String targetPropertyName = Executables.getPropertyName( targetAcessor );
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
MethodReference mappingMethodReference = mappingMethodResolver.getMappingMethodReferenceBasedOnMethod(
ParameterAssignment parameterAssignment = mappingResolver.getParameterAssignment(
method,
mappedElement,
mapperReferences,
@ -649,12 +650,6 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
sourceType,
targetType,
targetPropertyName,
dateFormat
);
TypeConversion conversion = mappingMethodResolver.getConversion(
sourceType,
targetType,
dateFormat,
conversionString
);
@ -667,37 +662,10 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
Executables.getPropertyName( targetAcessor ),
targetAcessor.getSimpleName().toString(),
targetType,
mappingMethodReference,
conversion
parameterAssignment != null ? parameterAssignment.getMethodReference() : null,
parameterAssignment != null ? parameterAssignment.getTypeConversion() : null
);
if ( !isPropertyMappable( property ) ) {
// when not mappable, try again with another property mapping method based on parameter only.
mappingMethodReference = mappingMethodResolver.getMappingMethodReferenceBasedOnParameter(
method,
"property '" + Executables.getPropertyName( sourceAccessor ) + "'",
mapperReferences,
methods,
sourceType,
targetType,
targetPropertyName,
dateFormat
);
property = new PropertyMapping(
parameter.getName(),
Executables.getPropertyName( sourceAccessor ),
sourceAccessor.getSimpleName().toString(),
sourceType,
Executables.getPropertyName( targetAcessor ),
targetAcessor.getSimpleName().toString(),
targetType,
mappingMethodReference,
conversion
);
}
if ( !isPropertyMappable( property ) ) {
messager.printMessage(
Kind.ERROR,
@ -720,18 +688,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
Type sourceElementType = method.getSourceParameters().iterator().next().getType().getTypeParameters().get( 0 );
Type targetElementType = method.getResultType().getTypeParameters().get( 0 );
String dateFormat = method.getIterableMapping() != null ? method.getIterableMapping().getDateFormat() : null;
String conversionStr = Strings.getSaveVariableName( sourceElementType.getName(), method.getParameterNames() );
TypeConversion conversion = mappingMethodResolver.getConversion(
sourceElementType,
targetElementType,
dateFormat,
Strings.getSaveVariableName(
sourceElementType.getName(),
method.getParameterNames()
)
);
MethodReference mappingMethodReference = mappingMethodResolver.getMappingMethodReferenceBasedOnMethod(
ParameterAssignment parameterAssignment = mappingResolver.getParameterAssignment(
method,
"collection element",
mapperReferences,
@ -739,26 +698,11 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
sourceElementType,
targetElementType,
null, // there is no targetPropertyName
dateFormat
dateFormat,
conversionStr
);
if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null &&
mappingMethodReference == null ) {
// when no conversion is found and no mapping method try match based on parameter only
mappingMethodReference = mappingMethodResolver.getMappingMethodReferenceBasedOnParameter(
method,
"collection element",
mapperReferences,
methods,
sourceElementType,
targetElementType,
null, // there is no targetPropertyName
dateFormat
);
}
if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null &&
mappingMethodReference == null ) {
if ( parameterAssignment == null ) {
messager.printMessage(
Kind.ERROR,
String.format(
@ -773,8 +717,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
return new IterableMappingMethod(
method,
mappingMethodReference,
conversion,
parameterAssignment != null ? parameterAssignment.getMethodReference() : null,
parameterAssignment != null ? parameterAssignment.getTypeConversion() : null,
factoryMethod
);
}
@ -789,7 +733,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
Type keyTargetType = resultTypeParams.get( 0 );
String keyDateFormat = method.getMapMapping() != null ? method.getMapMapping().getKeyFormat() : null;
MethodReference keyMappingMethod = mappingMethodResolver.getMappingMethodReferenceBasedOnMethod(
ParameterAssignment parameterAssignmentKey = mappingResolver.getParameterAssignment(
method,
"map key",
mapperReferences,
@ -797,26 +741,11 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
keySourceType,
keyTargetType,
null, // there is no targetPropertyName
keyDateFormat
keyDateFormat,
"entry.getKey()"
);
TypeConversion keyConversion = mappingMethodResolver.getConversion( keySourceType, keyTargetType,
keyDateFormat, "entry.getKey()" );
if ( !keySourceType.isAssignableTo( keyTargetType ) && keyConversion == null && keyMappingMethod == null ) {
// when no conversion is found and no mapping method try match based on parameter only
keyMappingMethod = mappingMethodResolver.getMappingMethodReferenceBasedOnParameter(
method,
"map key",
mapperReferences,
methods,
keySourceType,
keyTargetType,
null, // there is no targetPropertyName
keyDateFormat
);
}
if ( !keySourceType.isAssignableTo( keyTargetType ) && keyConversion == null && keyMappingMethod == null ) {
if ( parameterAssignmentKey == null ) {
messager.printMessage(
Kind.ERROR,
String.format(
@ -833,7 +762,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
Type valueTargetType = resultTypeParams.get( 1 );
String valueDateFormat = method.getMapMapping() != null ? method.getMapMapping().getValueFormat() : null;
MethodReference valueMappingMethod = mappingMethodResolver.getMappingMethodReferenceBasedOnMethod(
ParameterAssignment parameterAssignmentValue = mappingResolver.getParameterAssignment(
method,
"map value",
mapperReferences,
@ -841,32 +770,11 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
valueSourceType,
valueTargetType,
null, // there is no targetPropertyName
valueDateFormat
);
TypeConversion valueConversion = mappingMethodResolver.getConversion(
valueSourceType,
valueTargetType,
valueDateFormat,
"entry.getValue()"
);
if ( !valueSourceType.isAssignableTo( valueTargetType ) && valueConversion == null &&
valueMappingMethod == null ) {
// when no conversion is found and no mapping method try match based on parameter only
keyMappingMethod = mappingMethodResolver.getMappingMethodReferenceBasedOnParameter(
method,
"map value",
mapperReferences,
methods,
valueSourceType,
valueTargetType,
null, // there is no targetPropertyName
valueDateFormat
);
}
if ( !valueSourceType.isAssignableTo( valueTargetType ) && valueConversion == null &&
valueMappingMethod == null ) {
if ( parameterAssignmentValue == null ) {
messager.printMessage(
Kind.ERROR,
String.format(
@ -881,8 +789,12 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
return new MapMappingMethod(
method, keyMappingMethod, keyConversion, valueMappingMethod, valueConversion,
factoryMethod
method,
parameterAssignmentKey != null ? parameterAssignmentKey.getMethodReference() : null,
parameterAssignmentKey != null ? parameterAssignmentKey.getTypeConversion() : null,
parameterAssignmentValue != null ? parameterAssignmentValue.getMethodReference() : null,
parameterAssignmentValue != null ? parameterAssignmentValue.getTypeConversion() : null,
factoryMethod
);
}

View File

@ -18,6 +18,7 @@
*/
package org.mapstruct.ap.processor;
import org.mapstruct.ap.model.ParameterAssignment;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -64,7 +65,7 @@ import org.mapstruct.ap.util.Strings;
*
* @author Sjaak Derksen
*/
public class MappingMethodResolver {
public class MappingResolver {
private final Messager messager;
private final TypeFactory typeFactory;
@ -78,7 +79,8 @@ public class MappingMethodResolver {
*/
private final Set<VirtualMappingMethod> virtualMethods;
public MappingMethodResolver(Messager messager, TypeFactory typeFactory, Elements elementUtils, Types typeUtils) {
public MappingResolver(Messager messager, TypeFactory typeFactory, Elements elementUtils, Types typeUtils) {
this.messager = messager;
this.typeFactory = typeFactory;
this.conversions = new Conversions( elementUtils, typeFactory );
@ -88,7 +90,82 @@ public class MappingMethodResolver {
}
public TypeConversion getConversion(Type sourceType, Type targetType, String dateFormat, String sourceReference) {
/**
* returns a parameter assignment
*
* @param mappingMethod target mapping method
* @param mappedElement used for error messages
* @param mapperReferences list of references to mapper
* @param methods list of candidate methods
* @param sourceType parameter to match
* @param targetType return type to match
* @param targetPropertyName name of the target property
* @param dateFormat used for formatting dates in build in methods that need context information
* @param sourceReference call to source type as string
*
* @return an assignment to a method parameter, which can either be:
* <ol>
* <li>MethodReference</li>
* <li>TypeConversion</li>
* <li>Simple Assignment (empty ParameterAssignment)</li>
* <li>null, no assignment found</li>
* </ol>
*/
public ParameterAssignment getParameterAssignment( SourceMethod mappingMethod,
String mappedElement,
List<MapperReference> mapperReferences,
List<SourceMethod> methods,
Type sourceType,
Type targetType,
String targetPropertyName,
String dateFormat,
String sourceReference ) {
MethodReference mappingMethodReference = getMappingMethodReferenceBasedOnMethod(
mappingMethod,
mappedElement,
mapperReferences,
methods,
sourceType,
targetType,
targetPropertyName,
dateFormat
);
ParameterAssignment parameterAssignment = null;
if (mappingMethodReference != null ) {
parameterAssignment = new ParameterAssignment(mappingMethodReference );
}
else if (sourceType.isAssignableTo( targetType ) ) {
parameterAssignment = new ParameterAssignment();
}
else {
TypeConversion conversion = getConversion( sourceType, targetType, dateFormat, sourceReference );
if ( conversion != null ) {
parameterAssignment = new ParameterAssignment(conversion );
}
else {
mappingMethodReference = getMappingMethodReferenceBasedOnParameter(
mappingMethod,
mappedElement,
mapperReferences,
methods,
sourceType,
targetType,
targetPropertyName,
dateFormat
);
if ( mappingMethodReference != null ) {
parameterAssignment = new ParameterAssignment( mappingMethodReference );
}
}
}
return parameterAssignment;
}
private TypeConversion getConversion(Type sourceType, Type targetType, String dateFormat, String sourceReference) {
ConversionProvider conversionProvider = conversions.getConversion( sourceType, targetType );
if ( conversionProvider == null ) {
@ -115,7 +192,7 @@ public class MappingMethodResolver {
*
* @return a method reference.
*/
public MethodReference getMappingMethodReferenceBasedOnMethod(SourceMethod mappingMethod,
private MethodReference getMappingMethodReferenceBasedOnMethod(SourceMethod mappingMethod,
String mappedElement,
List<MapperReference> mapperReferences,
List<SourceMethod> methods,
@ -172,7 +249,7 @@ public class MappingMethodResolver {
*
* @return a method reference.
*/
public MethodReference getMappingMethodReferenceBasedOnParameter(SourceMethod mappingMethod,
private MethodReference getMappingMethodReferenceBasedOnParameter(SourceMethod mappingMethod,
String mappedElement,
List<MapperReference> mapperReferences,
List<SourceMethod> methods,
@ -267,7 +344,7 @@ public class MappingMethodResolver {
return null;
}
public Set<VirtualMappingMethod> getVirtualMethodsToCreate() {
public Set<VirtualMappingMethod> getVirtualMethodsToGenerate() {
return virtualMethods;
}