#2136 performance improvement 2 step mappings (#2138)

This commit is contained in:
Sjaak Derksen 2020-07-04 22:06:30 +02:00 committed by GitHub
parent 1ce282362c
commit 12ac348609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -39,6 +39,7 @@ import org.mapstruct.ap.internal.model.common.SourceRHS;
import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SourceMethod;
import org.mapstruct.ap.internal.model.source.builtin.BuiltInMappingMethods; import org.mapstruct.ap.internal.model.source.builtin.BuiltInMappingMethods;
import org.mapstruct.ap.internal.model.source.builtin.BuiltInMethod; import org.mapstruct.ap.internal.model.source.builtin.BuiltInMethod;
import org.mapstruct.ap.internal.model.source.selector.MethodSelectors; import org.mapstruct.ap.internal.model.source.selector.MethodSelectors;
@ -376,32 +377,56 @@ public class MappingResolverImpl implements MappingResolver {
return null; return null;
} }
/**
* Applies matching to given method only
*
* @param sourceType the source type
* @param targetType the target type
* @param method the method to match
* @return an assignment if a match, given the criteria could be found. When the method is a
* buildIn method, all the bookkeeping is applied.
*/
private Assignment applyMatching(Type sourceType, Type targetType, Method method) {
if ( method instanceof SourceMethod ) {
SelectedMethod<Method> selectedMethod =
getBestMatch( java.util.Collections.singletonList( method ), sourceType, targetType );
return selectedMethod != null ? getMappingMethodReference( selectedMethod ) : null;
}
else if ( method instanceof BuiltInMethod ) {
return resolveViaBuiltInMethod( sourceType, targetType );
}
return null;
}
private Assignment resolveViaBuiltInMethod(Type sourceType, Type targetType) { private Assignment resolveViaBuiltInMethod(Type sourceType, Type targetType) {
SelectedMethod<BuiltInMethod> matchingBuiltInMethod = SelectedMethod<BuiltInMethod> matchingBuiltInMethod =
getBestMatch( builtInMethods.getBuiltInMethods(), sourceType, targetType ); getBestMatch( builtInMethods.getBuiltInMethods(), sourceType, targetType );
if ( matchingBuiltInMethod != null ) { if ( matchingBuiltInMethod != null ) {
return createFromBuiltInMethod( matchingBuiltInMethod.getMethod() );
}
return null;
}
private Assignment createFromBuiltInMethod(BuiltInMethod method) {
Set<Field> allUsedFields = new HashSet<>( mapperReferences ); Set<Field> allUsedFields = new HashSet<>( mapperReferences );
SupportingField.addAllFieldsIn( supportingMethodCandidates, allUsedFields ); SupportingField.addAllFieldsIn( supportingMethodCandidates, allUsedFields );
SupportingMappingMethod supportingMappingMethod = SupportingMappingMethod supportingMappingMethod = new SupportingMappingMethod( method, allUsedFields );
new SupportingMappingMethod( matchingBuiltInMethod.getMethod(), allUsedFields );
supportingMethodCandidates.add( supportingMappingMethod ); supportingMethodCandidates.add( supportingMappingMethod );
ConversionContext ctx = new DefaultConversionContext( ConversionContext ctx = new DefaultConversionContext(
typeFactory, typeFactory,
messager, messager,
sourceType, method.getSourceParameters().get( 0 ).getType(),
targetType, method.getResultType(),
formattingParameters formattingParameters
); );
Assignment methodReference = MethodReference.forBuiltInMethod( matchingBuiltInMethod.getMethod(), ctx ); Assignment methodReference = MethodReference.forBuiltInMethod( method, ctx );
methodReference.setAssignment( sourceRHS ); methodReference.setAssignment( sourceRHS );
return methodReference; return methodReference;
} }
return null;
}
/** /**
* Suppose mapping required from A to C and: * Suppose mapping required from A to C and:
* <ul> * <ul>
@ -435,7 +460,7 @@ public class MappingResolverImpl implements MappingResolver {
ySourceType = ySourceType.resolveTypeVarToType( targetType, methodYCandidate.getResultType() ); ySourceType = ySourceType.resolveTypeVarToType( targetType, methodYCandidate.getResultType() );
if ( ySourceType != null ) { if ( ySourceType != null ) {
methodRefY = resolveViaMethod( ySourceType, targetType, true ); methodRefY = applyMatching( ySourceType, targetType, methodYCandidate );
if ( methodRefY != null ) { if ( methodRefY != null ) {
selectionCriteria.setPreferUpdateMapping( false ); selectionCriteria.setPreferUpdateMapping( false );
@ -486,10 +511,9 @@ public class MappingResolverImpl implements MappingResolver {
ySourceType = ySourceType.resolveTypeVarToType( targetType, methodYCandidate.getResultType() ); ySourceType = ySourceType.resolveTypeVarToType( targetType, methodYCandidate.getResultType() );
if ( ySourceType != null ) { if ( ySourceType != null ) {
methodRefY = resolveViaMethod( ySourceType, targetType, true ); methodRefY = applyMatching( ySourceType, targetType, methodYCandidate );
if ( methodRefY != null ) { if ( methodRefY != null ) {
Type targetTypeX = methodYCandidate.getSourceParameters().get( 0 ).getType(); ConversionAssignment conversionXRef = resolveViaConversion( sourceType, ySourceType );
ConversionAssignment conversionXRef = resolveViaConversion( sourceType, targetTypeX );
if ( conversionXRef != null ) { if ( conversionXRef != null ) {
methodRefY.setAssignment( conversionXRef.getAssignment() ); methodRefY.setAssignment( conversionXRef.getAssignment() );
conversionXRef.getAssignment().setAssignment( sourceRHS ); conversionXRef.getAssignment().setAssignment( sourceRHS );
@ -539,9 +563,9 @@ public class MappingResolverImpl implements MappingResolver {
xTargetType.resolveTypeVarToType( sourceType, methodXCandidate.getParameters().get( 0 ).getType() ); xTargetType.resolveTypeVarToType( sourceType, methodXCandidate.getParameters().get( 0 ).getType() );
if ( xTargetType != null ) { if ( xTargetType != null ) {
Assignment methodRefX = resolveViaMethod( sourceType, xTargetType, true ); Assignment methodRefX = applyMatching( sourceType, xTargetType, methodXCandidate );
if ( methodRefX != null ) { if ( methodRefX != null ) {
conversionYRef = resolveViaConversion( methodXCandidate.getReturnType(), targetType ); conversionYRef = resolveViaConversion( xTargetType, targetType );
if ( conversionYRef != null ) { if ( conversionYRef != null ) {
conversionYRef.getAssignment().setAssignment( methodRefX ); conversionYRef.getAssignment().setAssignment( methodRefX );
methodRefX.setAssignment( sourceRHS ); methodRefX.setAssignment( sourceRHS );