mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#120 Consolidating method reference look-up in MapperCreationProcessor
This commit is contained in:
parent
40669a0f8a
commit
9b8e22462f
@ -578,22 +578,17 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
targetType = typeFactory.getReturnType( targetAcessor );
|
targetType = typeFactory.getReturnType( targetAcessor );
|
||||||
}
|
}
|
||||||
|
|
||||||
// first try the source methods
|
|
||||||
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
|
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
|
||||||
MethodReference propertyMappingMethod = getMappingMethodReference(
|
MethodReference mappingMethodReference = getMappingMethodReference(
|
||||||
getBestMatch( method, mappedElement, methods, sourceType, targetType ),
|
method,
|
||||||
mapperReferences
|
mappedElement,
|
||||||
|
mapperReferences,
|
||||||
|
methods,
|
||||||
|
sourceType,
|
||||||
|
targetType,
|
||||||
|
dateFormat
|
||||||
);
|
);
|
||||||
|
|
||||||
// then try built-in methods
|
|
||||||
if ( propertyMappingMethod == null ) {
|
|
||||||
propertyMappingMethod = getMappingMethodReference(
|
|
||||||
getBestMatch( method, mappedElement, builtInMethods.getBuiltInMethods(), sourceType, targetType ),
|
|
||||||
targetType,
|
|
||||||
dateFormat
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeConversion conversion = getConversion(
|
TypeConversion conversion = getConversion(
|
||||||
sourceType,
|
sourceType,
|
||||||
targetType,
|
targetType,
|
||||||
@ -609,7 +604,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
Executables.getPropertyName( targetAcessor ),
|
Executables.getPropertyName( targetAcessor ),
|
||||||
targetAcessor.getSimpleName().toString(),
|
targetAcessor.getSimpleName().toString(),
|
||||||
targetType,
|
targetType,
|
||||||
propertyMappingMethod,
|
mappingMethodReference,
|
||||||
conversion
|
conversion
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -638,26 +633,18 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// first try the source methods
|
MethodReference mappingMethodReference = getMappingMethodReference(
|
||||||
MethodReference elementMappingMethod = getMappingMethodReference(
|
method,
|
||||||
getBestMatch( method, "collection element", methods, sourceElementType, targetElementType ),
|
"collection element",
|
||||||
mapperReferences
|
mapperReferences,
|
||||||
|
methods,
|
||||||
|
sourceElementType,
|
||||||
|
targetElementType,
|
||||||
|
dateFormat
|
||||||
);
|
);
|
||||||
|
|
||||||
// then try built-in methods
|
|
||||||
if ( elementMappingMethod == null ) {
|
|
||||||
elementMappingMethod = getMappingMethodReference(
|
|
||||||
getBestMatch(
|
|
||||||
method, "collection element", builtInMethods.getBuiltInMethods(), sourceElementType,
|
|
||||||
targetElementType
|
|
||||||
),
|
|
||||||
targetElementType,
|
|
||||||
dateFormat
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null &&
|
if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null &&
|
||||||
elementMappingMethod == null ) {
|
mappingMethodReference == null ) {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
Kind.ERROR,
|
Kind.ERROR,
|
||||||
String.format(
|
String.format(
|
||||||
@ -672,7 +659,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||||
return new IterableMappingMethod(
|
return new IterableMappingMethod(
|
||||||
method,
|
method,
|
||||||
elementMappingMethod,
|
mappingMethodReference,
|
||||||
conversion,
|
conversion,
|
||||||
factoryMethod
|
factoryMethod
|
||||||
);
|
);
|
||||||
@ -681,60 +668,25 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
private MapMappingMethod getMapMappingMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
private MapMappingMethod getMapMappingMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
||||||
SourceMethod method) {
|
SourceMethod method) {
|
||||||
List<Type> sourceTypeParams = method.getSourceParameters().iterator().next().getType().getTypeParameters();
|
List<Type> sourceTypeParams = method.getSourceParameters().iterator().next().getType().getTypeParameters();
|
||||||
Type sourceKeyType = sourceTypeParams.get( 0 );
|
|
||||||
Type sourceValueType = sourceTypeParams.get( 1 );
|
|
||||||
|
|
||||||
List<Type> resultTypeParams = method.getResultType().getTypeParameters();
|
List<Type> resultTypeParams = method.getResultType().getTypeParameters();
|
||||||
Type targetKeyType = resultTypeParams.get( 0 );
|
|
||||||
Type targetValueType = resultTypeParams.get( 1 );
|
|
||||||
|
|
||||||
|
// find mapping method or conversion for key
|
||||||
|
Type keySourceType = sourceTypeParams.get( 0 );
|
||||||
|
Type keyTargetType = resultTypeParams.get( 0 );
|
||||||
String keyDateFormat = method.getMapMapping() != null ? method.getMapMapping().getKeyFormat() : null;
|
String keyDateFormat = method.getMapMapping() != null ? method.getMapMapping().getKeyFormat() : null;
|
||||||
String valueDateFormat = method.getMapMapping() != null ? method.getMapMapping().getValueFormat() : null;
|
|
||||||
|
|
||||||
TypeConversion keyConversion = getConversion( sourceKeyType, targetKeyType, keyDateFormat, "entry.getKey()" );
|
|
||||||
TypeConversion valueConversion = getConversion(
|
|
||||||
sourceValueType,
|
|
||||||
targetValueType,
|
|
||||||
valueDateFormat,
|
|
||||||
"entry.getValue()"
|
|
||||||
);
|
|
||||||
|
|
||||||
// first try the source methods
|
|
||||||
MethodReference keyMappingMethod = getMappingMethodReference(
|
MethodReference keyMappingMethod = getMappingMethodReference(
|
||||||
getBestMatch( method, "map key", methods, sourceKeyType, targetKeyType ), mapperReferences
|
method,
|
||||||
|
"map key",
|
||||||
|
mapperReferences,
|
||||||
|
methods,
|
||||||
|
keySourceType,
|
||||||
|
keyTargetType,
|
||||||
|
keyDateFormat
|
||||||
);
|
);
|
||||||
|
TypeConversion keyConversion = getConversion( keySourceType, keyTargetType, keyDateFormat, "entry.getKey()" );
|
||||||
|
|
||||||
// then try built-in methods
|
if ( !keySourceType.isAssignableTo( keyTargetType ) && keyConversion == null && keyMappingMethod == null ) {
|
||||||
if ( keyMappingMethod == null ) {
|
|
||||||
keyMappingMethod = getMappingMethodReference(
|
|
||||||
getBestMatch( method, "map key", builtInMethods.getBuiltInMethods(), sourceKeyType, targetKeyType ),
|
|
||||||
targetKeyType,
|
|
||||||
keyDateFormat
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// first try the source methods
|
|
||||||
MethodReference valueMappingMethod = getMappingMethodReference(
|
|
||||||
getBestMatch( method, "map value", methods, sourceValueType, targetValueType ),
|
|
||||||
mapperReferences
|
|
||||||
);
|
|
||||||
|
|
||||||
// then try built-in methods
|
|
||||||
if ( valueMappingMethod == null ) {
|
|
||||||
valueMappingMethod = getMappingMethodReference(
|
|
||||||
getBestMatch(
|
|
||||||
method,
|
|
||||||
"map value",
|
|
||||||
builtInMethods.getBuiltInMethods(),
|
|
||||||
sourceValueType,
|
|
||||||
targetValueType
|
|
||||||
),
|
|
||||||
targetValueType,
|
|
||||||
valueDateFormat
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !sourceKeyType.isAssignableTo( targetKeyType ) && keyConversion == null && keyMappingMethod == null ) {
|
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
Kind.ERROR,
|
Kind.ERROR,
|
||||||
String.format(
|
String.format(
|
||||||
@ -746,7 +698,28 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !sourceValueType.isAssignableTo( targetValueType ) && valueConversion == null &&
|
// find mapping method or conversion for value
|
||||||
|
Type valueSourceType = sourceTypeParams.get( 1 );
|
||||||
|
Type valueTargetType = resultTypeParams.get( 1 );
|
||||||
|
String valueDateFormat = method.getMapMapping() != null ? method.getMapMapping().getValueFormat() : null;
|
||||||
|
|
||||||
|
MethodReference valueMappingMethod = getMappingMethodReference(
|
||||||
|
method,
|
||||||
|
"map value",
|
||||||
|
mapperReferences,
|
||||||
|
methods,
|
||||||
|
valueSourceType,
|
||||||
|
valueTargetType,
|
||||||
|
valueDateFormat
|
||||||
|
);
|
||||||
|
TypeConversion valueConversion = getConversion(
|
||||||
|
valueSourceType,
|
||||||
|
valueTargetType,
|
||||||
|
valueDateFormat,
|
||||||
|
"entry.getValue()"
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( !valueSourceType.isAssignableTo( valueTargetType ) && valueConversion == null &&
|
||||||
valueMappingMethod == null ) {
|
valueMappingMethod == null ) {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
Kind.ERROR,
|
Kind.ERROR,
|
||||||
@ -760,6 +733,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||||
|
|
||||||
return new MapMappingMethod(
|
return new MapMappingMethod(
|
||||||
method, keyMappingMethod, keyConversion, valueMappingMethod, valueConversion,
|
method, keyMappingMethod, keyConversion, valueMappingMethod, valueConversion,
|
||||||
factoryMethod
|
factoryMethod
|
||||||
@ -779,6 +753,32 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to a method mapping the given source type to the given target type, if such a method exists.
|
||||||
|
*/
|
||||||
|
private MethodReference getMappingMethodReference(SourceMethod method, String mappedElement,
|
||||||
|
List<MapperReference> mapperReferences,
|
||||||
|
List<SourceMethod> methods, Type sourceType, Type targetType,
|
||||||
|
String dateFormat) {
|
||||||
|
// first try to find a matching source method
|
||||||
|
SourceMethod matchingSourceMethod = getBestMatch( method, mappedElement, methods, sourceType, targetType );
|
||||||
|
|
||||||
|
if ( matchingSourceMethod != null ) {
|
||||||
|
return getMappingMethodReference( matchingSourceMethod, mapperReferences );
|
||||||
|
}
|
||||||
|
|
||||||
|
// then a matching built-in method
|
||||||
|
BuiltInMethod matchingBuiltInMethod = getBestMatch(
|
||||||
|
method,
|
||||||
|
mappedElement,
|
||||||
|
builtInMethods.getBuiltInMethods(),
|
||||||
|
sourceType,
|
||||||
|
targetType
|
||||||
|
);
|
||||||
|
|
||||||
|
return matchingBuiltInMethod != null ?
|
||||||
|
getMappingMethodReference( matchingBuiltInMethod, targetType, dateFormat ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
private <T extends Method> T getBestMatch(SourceMethod mappingMethod, String mappedElement,
|
private <T extends Method> T getBestMatch(SourceMethod mappingMethod, String mappedElement,
|
||||||
Iterable<T> methods, Type parameterType,
|
Iterable<T> methods, Type parameterType,
|
||||||
@ -850,26 +850,20 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MethodReference getMappingMethodReference(SourceMethod method, List<MapperReference> mapperReferences) {
|
private MethodReference getMappingMethodReference(SourceMethod method, List<MapperReference> mapperReferences) {
|
||||||
if ( method != null ) {
|
MapperReference mapperReference = null;
|
||||||
MapperReference mapperReference = null;
|
for ( MapperReference ref : mapperReferences ) {
|
||||||
for ( MapperReference ref : mapperReferences ) {
|
if ( ref.getMapperType().equals( method.getDeclaringMapper() ) ) {
|
||||||
if ( ref.getMapperType().equals( method.getDeclaringMapper() ) ) {
|
mapperReference = ref;
|
||||||
mapperReference = ref;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new MethodReference( method, mapperReference );
|
|
||||||
}
|
}
|
||||||
return null;
|
return new MethodReference( method, mapperReference );
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodReference getMappingMethodReference(BuiltInMethod method, Type returnType, String dateFormat) {
|
private MethodReference getMappingMethodReference(BuiltInMethod method, Type returnType, String dateFormat) {
|
||||||
if ( method != null ) {
|
virtualMethods.add( new VirtualMappingMethod( method ) );
|
||||||
virtualMethods.add( new VirtualMappingMethod( method ) );
|
ConversionContext ctx = new DefaultConversionContext( typeFactory, returnType, dateFormat );
|
||||||
ConversionContext ctx = new DefaultConversionContext( typeFactory, returnType, dateFormat );
|
return new MethodReference( method, ctx );
|
||||||
return new MethodReference( method, ctx );
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -878,6 +872,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>the source type is assignable to the target type</li>
|
* <li>the source type is assignable to the target type</li>
|
||||||
* <li>a mapping method exists</li>
|
* <li>a mapping method exists</li>
|
||||||
|
* <li>a built-in method exists/<li>
|
||||||
* <li>a built-in conversion exists</li>
|
* <li>a built-in conversion exists</li>
|
||||||
* <li>the property is of a collection or map type and the constructor of the target type (either itself or its
|
* <li>the property is of a collection or map type and the constructor of the target type (either itself or its
|
||||||
* implementation type) accepts the source type.</li>
|
* implementation type) accepts the source type.</li>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user