mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#3280 Refactor method selection and use a context to be able to more easily access information
This commit is contained in:
parent
c2eed45df1
commit
62d1bd3490
@ -6,7 +6,6 @@
|
||||
package org.mapstruct.ap.internal.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@ -19,7 +18,7 @@ import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.MethodSelectors;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionCriteria;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionContext;
|
||||
|
||||
/**
|
||||
* Factory for creating lists of appropriate {@link LifecycleCallbackMethodReference}s
|
||||
@ -134,15 +133,12 @@ public final class LifecycleMethodResolver {
|
||||
MappingBuilderContext ctx, Set<String> existingVariableNames) {
|
||||
|
||||
MethodSelectors selectors =
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getTypeFactory(), ctx.getMessager() );
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getMessager() );
|
||||
|
||||
List<SelectedMethod<SourceMethod>> matchingMethods = selectors.getMatchingMethods(
|
||||
method,
|
||||
callbackMethods,
|
||||
Collections.emptyList(),
|
||||
targetType,
|
||||
method.getResultType(),
|
||||
SelectionCriteria.forLifecycleMethods( selectionParameters ) );
|
||||
SelectionContext.forLifecycleMethods( method, targetType, selectionParameters, ctx.getTypeFactory() )
|
||||
);
|
||||
|
||||
return toLifecycleCallbackMethodRefs(
|
||||
method,
|
||||
|
@ -23,7 +23,7 @@ import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.MethodSelectors;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionCriteria;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionContext;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
|
||||
/**
|
||||
@ -126,15 +126,11 @@ public class ObjectFactoryMethodResolver {
|
||||
MappingBuilderContext ctx) {
|
||||
|
||||
MethodSelectors selectors =
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getTypeFactory(), ctx.getMessager() );
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getMessager() );
|
||||
|
||||
return selectors.getMatchingMethods(
|
||||
method,
|
||||
getAllAvailableMethods( method, ctx.getSourceModel() ),
|
||||
java.util.Collections.emptyList(),
|
||||
alternativeTarget,
|
||||
alternativeTarget,
|
||||
SelectionCriteria.forFactoryMethods( selectionParameters )
|
||||
SelectionContext.forFactoryMethods( method, alternativeTarget, selectionParameters, ctx.getTypeFactory() )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -6,20 +6,18 @@
|
||||
package org.mapstruct.ap.internal.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.PresenceCheck;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.ParameterProvidedMethods;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.MethodSelectors;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionCriteria;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionContext;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
|
||||
/**
|
||||
@ -60,18 +58,12 @@ public final class PresenceCheckMethodResolver {
|
||||
MethodSelectors selectors = new MethodSelectors(
|
||||
ctx.getTypeUtils(),
|
||||
ctx.getElementUtils(),
|
||||
ctx.getTypeFactory(),
|
||||
ctx.getMessager()
|
||||
);
|
||||
|
||||
Type booleanType = ctx.getTypeFactory().getType( Boolean.class );
|
||||
List<SelectedMethod<SourceMethod>> matchingMethods = selectors.getMatchingMethods(
|
||||
method,
|
||||
getAllAvailableMethods( method, ctx.getSourceModel() ),
|
||||
Collections.emptyList(),
|
||||
booleanType,
|
||||
booleanType,
|
||||
SelectionCriteria.forPresenceCheckMethods( selectionParameters )
|
||||
SelectionContext.forPresenceCheckMethods( method, selectionParameters, ctx.getTypeFactory() )
|
||||
);
|
||||
|
||||
if ( matchingMethods.isEmpty() ) {
|
||||
|
@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.model.source.selector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
|
||||
/**
|
||||
@ -29,13 +28,9 @@ import org.mapstruct.ap.internal.model.source.Method;
|
||||
public class CreateOrUpdateSelector implements MethodSelector {
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
SelectionCriteria criteria = context.getSelectionCriteria();
|
||||
if ( criteria.isLifecycleCallbackRequired() || criteria.isObjectFactoryRequired()
|
||||
|| criteria.isPresenceCheckRequired() ) {
|
||||
return methods;
|
||||
|
@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.model.source.selector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
|
||||
/**
|
||||
@ -21,11 +20,9 @@ import org.mapstruct.ap.internal.model.source.Method;
|
||||
public class FactoryParameterSelector implements MethodSelector {
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType, Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
SelectionCriteria criteria = context.getSelectionCriteria();
|
||||
if ( !criteria.isObjectFactoryRequired() || methods.size() <= 1 ) {
|
||||
return methods;
|
||||
}
|
||||
|
@ -22,18 +22,14 @@ import org.mapstruct.ap.internal.model.source.Method;
|
||||
public class InheritanceSelector implements MethodSelector {
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType, Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
|
||||
if ( sourceTypes.size() != 1 ) {
|
||||
Type sourceType = context.getSourceType();
|
||||
if ( sourceType == null ) {
|
||||
return methods;
|
||||
}
|
||||
|
||||
Type singleSourceType = first( sourceTypes );
|
||||
|
||||
List<SelectedMethod<T>> candidatesWithBestMatchingSourceType = new ArrayList<>();
|
||||
int bestMatchingSourceTypeDistance = Integer.MAX_VALUE;
|
||||
|
||||
@ -41,7 +37,7 @@ public class InheritanceSelector implements MethodSelector {
|
||||
for ( SelectedMethod<T> method : methods ) {
|
||||
Parameter singleSourceParam = first( method.getMethod().getSourceParameters() );
|
||||
|
||||
int sourceTypeDistance = singleSourceType.distanceTo( singleSourceParam.getType() );
|
||||
int sourceTypeDistance = sourceType.distanceTo( singleSourceParam.getType() );
|
||||
bestMatchingSourceTypeDistance =
|
||||
addToCandidateListIfMinimal(
|
||||
candidatesWithBestMatchingSourceType,
|
||||
|
@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.model.source.selector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
|
||||
/**
|
||||
@ -20,12 +19,9 @@ import org.mapstruct.ap.internal.model.source.Method;
|
||||
public class MethodFamilySelector implements MethodSelector {
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
SelectionCriteria criteria = context.getSelectionCriteria();
|
||||
|
||||
List<SelectedMethod<T>> result = new ArrayList<>( methods.size() );
|
||||
for ( SelectedMethod<T> method : methods ) {
|
||||
|
@ -7,7 +7,6 @@ package org.mapstruct.ap.internal.model.source.selector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
|
||||
/**
|
||||
@ -23,18 +22,10 @@ interface MethodSelector {
|
||||
* Selects those methods which match the given types and other criteria
|
||||
*
|
||||
* @param <T> either SourceMethod or BuiltInMethod
|
||||
* @param mappingMethod mapping method, defined in Mapper for which this selection is carried out
|
||||
* @param candidates list of available methods
|
||||
* @param sourceTypes parameter type(s) that should be matched
|
||||
* @param mappingTargetType mappingTargetType that should be matched
|
||||
* @param returnType return type that should be matched
|
||||
* @param criteria criteria used in the selection process
|
||||
* @param context the context for the matching
|
||||
* @return list of methods that passes the matching process
|
||||
*/
|
||||
<T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> candidates,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria);
|
||||
<T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> candidates,
|
||||
SelectionContext context);
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
@ -25,11 +23,11 @@ public class MethodSelectors {
|
||||
|
||||
private final List<MethodSelector> selectors;
|
||||
|
||||
public MethodSelectors(TypeUtils typeUtils, ElementUtils elementUtils, TypeFactory typeFactory,
|
||||
public MethodSelectors(TypeUtils typeUtils, ElementUtils elementUtils,
|
||||
FormattingMessager messager) {
|
||||
selectors = Arrays.asList(
|
||||
new MethodFamilySelector(),
|
||||
new TypeSelector( typeFactory, messager ),
|
||||
new TypeSelector( messager ),
|
||||
new QualifierSelector( typeUtils, elementUtils ),
|
||||
new TargetTypeSelector( typeUtils ),
|
||||
new JavaxXmlElementDeclSelector( typeUtils ),
|
||||
@ -46,20 +44,12 @@ public class MethodSelectors {
|
||||
* Selects those methods which match the given types and other criteria
|
||||
*
|
||||
* @param <T> either SourceMethod or BuiltInMethod
|
||||
* @param mappingMethod mapping method, defined in Mapper for which this selection is carried out
|
||||
* @param methods list of available methods
|
||||
* @param sourceTypes parameter type(s) that should be matched
|
||||
* @param mappingTargetType the mapping target type that should be matched
|
||||
* @param returnType return type that should be matched
|
||||
* @param criteria criteria used in the selection process
|
||||
* @param context the selection context that should be used in the matching process
|
||||
* @return list of methods that passes the matching process
|
||||
*/
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<T> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<T> methods,
|
||||
SelectionContext context) {
|
||||
|
||||
List<SelectedMethod<T>> candidates = new ArrayList<>( methods.size() );
|
||||
for ( T method : methods ) {
|
||||
@ -67,13 +57,7 @@ public class MethodSelectors {
|
||||
}
|
||||
|
||||
for ( MethodSelector selector : selectors ) {
|
||||
candidates = selector.getMatchingMethods(
|
||||
mappingMethod,
|
||||
candidates,
|
||||
sourceTypes,
|
||||
mappingTargetType,
|
||||
returnType,
|
||||
criteria );
|
||||
candidates = selector.getMatchingMethods( candidates, context );
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ import org.mapstruct.ap.internal.model.source.Method;
|
||||
public class MostSpecificResultTypeSelector implements MethodSelector {
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> candidates,
|
||||
List<Type> sourceTypes, Type mappingTargetType,
|
||||
Type returnType, SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> candidates,
|
||||
SelectionContext context) {
|
||||
SelectionCriteria criteria = context.getSelectionCriteria();
|
||||
Type mappingTargetType = context.getMappingTargetType();
|
||||
if ( candidates.size() < 2 || !criteria.isForMapping() || criteria.getQualifyingResultType() != null) {
|
||||
return candidates;
|
||||
}
|
||||
|
@ -49,12 +49,9 @@ public class QualifierSelector implements MethodSelector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
SelectionCriteria criteria = context.getSelectionCriteria();
|
||||
|
||||
int numberOfQualifiersToMatch = 0;
|
||||
|
||||
|
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model.source.selector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.ParameterBinding;
|
||||
import org.mapstruct.ap.internal.model.common.SourceRHS;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
|
||||
/**
|
||||
* Context passed to the selectors to get the information they need.
|
||||
*
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class SelectionContext {
|
||||
|
||||
private final Type sourceType;
|
||||
private final SelectionCriteria selectionCriteria;
|
||||
private final Method mappingMethod;
|
||||
private final Type mappingTargetType;
|
||||
private final Type returnType;
|
||||
private final Supplier<List<ParameterBinding>> parameterBindingsProvider;
|
||||
private List<ParameterBinding> parameterBindings;
|
||||
|
||||
private SelectionContext(Type sourceType, SelectionCriteria selectionCriteria, Method mappingMethod,
|
||||
Type mappingTargetType, Type returnType,
|
||||
Supplier<List<ParameterBinding>> parameterBindingsProvider) {
|
||||
this.sourceType = sourceType;
|
||||
this.selectionCriteria = selectionCriteria;
|
||||
this.mappingMethod = mappingMethod;
|
||||
this.mappingTargetType = mappingTargetType;
|
||||
this.returnType = returnType;
|
||||
this.parameterBindingsProvider = parameterBindingsProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the source type that should be matched
|
||||
*/
|
||||
public Type getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the criteria used in the selection process
|
||||
*/
|
||||
public SelectionCriteria getSelectionCriteria() {
|
||||
return selectionCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mapping target type that should be matched
|
||||
*/
|
||||
public Type getMappingTargetType() {
|
||||
return mappingTargetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the return type that should be matched
|
||||
*/
|
||||
public Type getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the available parameter bindings for the matching
|
||||
*/
|
||||
public List<ParameterBinding> getAvailableParameterBindings() {
|
||||
if ( this.parameterBindings == null ) {
|
||||
this.parameterBindings = this.parameterBindingsProvider.get();
|
||||
}
|
||||
return parameterBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mapping method, defined in Mapper for which this selection is carried out
|
||||
*/
|
||||
public Method getMappingMethod() {
|
||||
return mappingMethod;
|
||||
}
|
||||
|
||||
public static SelectionContext forMappingMethods(Method mappingMethod, Type source, Type target,
|
||||
SelectionCriteria criteria, TypeFactory typeFactory) {
|
||||
return new SelectionContext(
|
||||
source,
|
||||
criteria,
|
||||
mappingMethod,
|
||||
target,
|
||||
target,
|
||||
() -> getAvailableParameterBindingsFromSourceType(
|
||||
source,
|
||||
target,
|
||||
mappingMethod,
|
||||
typeFactory
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static SelectionContext forLifecycleMethods(Method mappingMethod, Type targetType,
|
||||
SelectionParameters selectionParameters,
|
||||
TypeFactory typeFactory) {
|
||||
SelectionCriteria criteria = SelectionCriteria.forLifecycleMethods( selectionParameters );
|
||||
return new SelectionContext(
|
||||
null,
|
||||
criteria,
|
||||
mappingMethod,
|
||||
targetType,
|
||||
mappingMethod.getResultType(),
|
||||
() -> getAvailableParameterBindingsFromMethod(
|
||||
mappingMethod,
|
||||
targetType,
|
||||
criteria.getSourceRHS(),
|
||||
typeFactory
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static SelectionContext forFactoryMethods(Method mappingMethod, Type alternativeTarget,
|
||||
SelectionParameters selectionParameters,
|
||||
TypeFactory typeFactory) {
|
||||
SelectionCriteria criteria = SelectionCriteria.forFactoryMethods( selectionParameters );
|
||||
return new SelectionContext(
|
||||
null,
|
||||
criteria,
|
||||
mappingMethod,
|
||||
alternativeTarget,
|
||||
alternativeTarget,
|
||||
() -> getAvailableParameterBindingsFromMethod(
|
||||
mappingMethod,
|
||||
alternativeTarget,
|
||||
criteria.getSourceRHS(),
|
||||
typeFactory
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static SelectionContext forPresenceCheckMethods(Method mappingMethod,
|
||||
SelectionParameters selectionParameters,
|
||||
TypeFactory typeFactory) {
|
||||
SelectionCriteria criteria = SelectionCriteria.forPresenceCheckMethods( selectionParameters );
|
||||
Type booleanType = typeFactory.getType( Boolean.class );
|
||||
return new SelectionContext(
|
||||
null,
|
||||
criteria,
|
||||
mappingMethod,
|
||||
booleanType,
|
||||
booleanType,
|
||||
() -> getAvailableParameterBindingsFromMethod(
|
||||
mappingMethod,
|
||||
booleanType,
|
||||
criteria.getSourceRHS(),
|
||||
typeFactory
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static List<ParameterBinding> getAvailableParameterBindingsFromMethod(Method method, Type targetType,
|
||||
SourceRHS sourceRHS,
|
||||
TypeFactory typeFactory) {
|
||||
List<ParameterBinding> availableParams = new ArrayList<>( method.getParameters().size() + 3 );
|
||||
|
||||
if ( sourceRHS != null ) {
|
||||
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
||||
availableParams.add( ParameterBinding.fromSourceRHS( sourceRHS ) );
|
||||
}
|
||||
else {
|
||||
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
||||
}
|
||||
|
||||
addTargetRelevantBindings( availableParams, targetType, typeFactory );
|
||||
|
||||
return availableParams;
|
||||
}
|
||||
|
||||
private static List<ParameterBinding> getAvailableParameterBindingsFromSourceType(Type sourceType,
|
||||
Type targetType,
|
||||
Method mappingMethod,
|
||||
TypeFactory typeFactory) {
|
||||
|
||||
List<ParameterBinding> availableParams = new ArrayList<>();
|
||||
|
||||
availableParams.add( ParameterBinding.forSourceTypeBinding( sourceType ) );
|
||||
|
||||
for ( Parameter param : mappingMethod.getParameters() ) {
|
||||
if ( param.isMappingContext() ) {
|
||||
availableParams.add( ParameterBinding.fromParameter( param ) );
|
||||
}
|
||||
}
|
||||
|
||||
addTargetRelevantBindings( availableParams, targetType, typeFactory );
|
||||
|
||||
return availableParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default parameter bindings for the mapping-target and target-type if not already available.
|
||||
*
|
||||
* @param availableParams Already available params, new entries will be added to this list
|
||||
* @param targetType Target type
|
||||
*/
|
||||
private static void addTargetRelevantBindings(List<ParameterBinding> availableParams, Type targetType,
|
||||
TypeFactory typeFactory) {
|
||||
boolean mappingTargetAvailable = false;
|
||||
boolean targetTypeAvailable = false;
|
||||
boolean targetPropertyNameAvailable = false;
|
||||
|
||||
// search available parameter bindings if mapping-target and/or target-type is available
|
||||
for ( ParameterBinding pb : availableParams ) {
|
||||
if ( pb.isMappingTarget() ) {
|
||||
mappingTargetAvailable = true;
|
||||
}
|
||||
else if ( pb.isTargetType() ) {
|
||||
targetTypeAvailable = true;
|
||||
}
|
||||
else if ( pb.isTargetPropertyName() ) {
|
||||
targetPropertyNameAvailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mappingTargetAvailable ) {
|
||||
availableParams.add( ParameterBinding.forMappingTargetBinding( targetType ) );
|
||||
}
|
||||
if ( !targetTypeAvailable ) {
|
||||
availableParams.add( ParameterBinding.forTargetTypeBinding( typeFactory.classTypeOf( targetType ) ) );
|
||||
}
|
||||
if ( !targetPropertyNameAvailable ) {
|
||||
availableParams.add( ParameterBinding.forTargetPropertyNameBinding( typeFactory.getType( String.class ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ParameterBinding;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
|
||||
/**
|
||||
@ -20,10 +19,9 @@ import org.mapstruct.ap.internal.model.source.Method;
|
||||
public class SourceRhsSelector implements MethodSelector {
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> candidates,
|
||||
List<Type> sourceTypes, Type mappingTargetType,
|
||||
Type returnType, SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> candidates,
|
||||
SelectionContext context) {
|
||||
SelectionCriteria criteria = context.getSelectionCriteria();
|
||||
if ( candidates.size() < 2 || criteria.getSourceRHS() == null ) {
|
||||
return candidates;
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import java.util.List;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
|
||||
/**
|
||||
@ -31,12 +30,9 @@ public class TargetTypeSelector implements MethodSelector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
SelectionCriteria criteria = context.getSelectionCriteria();
|
||||
|
||||
TypeMirror qualifyingTypeMirror = criteria.getQualifyingResultType();
|
||||
if ( qualifyingTypeMirror != null && !criteria.isLifecycleCallbackRequired() ) {
|
||||
|
@ -11,9 +11,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.ParameterBinding;
|
||||
import org.mapstruct.ap.internal.model.common.SourceRHS;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.MethodMatcher;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
@ -29,44 +27,24 @@ import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
*/
|
||||
public class TypeSelector implements MethodSelector {
|
||||
|
||||
private TypeFactory typeFactory;
|
||||
private FormattingMessager messager;
|
||||
|
||||
public TypeSelector(TypeFactory typeFactory, FormattingMessager messager) {
|
||||
this.typeFactory = typeFactory;
|
||||
public TypeSelector(FormattingMessager messager) {
|
||||
this.messager = messager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
if ( methods.isEmpty() ) {
|
||||
return methods;
|
||||
}
|
||||
|
||||
Type returnType = context.getReturnType();
|
||||
|
||||
List<SelectedMethod<T>> result = new ArrayList<>();
|
||||
|
||||
List<ParameterBinding> availableBindings;
|
||||
if ( sourceTypes.isEmpty() ) {
|
||||
// if no source types are given, we have a factory or lifecycle method
|
||||
availableBindings = getAvailableParameterBindingsFromMethod(
|
||||
mappingMethod,
|
||||
mappingTargetType,
|
||||
criteria.getSourceRHS()
|
||||
);
|
||||
}
|
||||
else {
|
||||
availableBindings = getAvailableParameterBindingsFromSourceTypes(
|
||||
sourceTypes,
|
||||
mappingTargetType,
|
||||
mappingMethod
|
||||
);
|
||||
}
|
||||
List<ParameterBinding> availableBindings = context.getAvailableParameterBindings();
|
||||
|
||||
for ( SelectedMethod<T> method : methods ) {
|
||||
List<List<ParameterBinding>> parameterBindingPermutations =
|
||||
@ -74,7 +52,7 @@ public class TypeSelector implements MethodSelector {
|
||||
|
||||
if ( parameterBindingPermutations != null ) {
|
||||
SelectedMethod<T> matchingMethod =
|
||||
getMatchingParameterBinding( returnType, mappingMethod, method, parameterBindingPermutations );
|
||||
getMatchingParameterBinding( returnType, context, method, parameterBindingPermutations );
|
||||
|
||||
if ( matchingMethod != null ) {
|
||||
result.add( matchingMethod );
|
||||
@ -84,80 +62,8 @@ public class TypeSelector implements MethodSelector {
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<ParameterBinding> getAvailableParameterBindingsFromMethod(Method method, Type targetType,
|
||||
SourceRHS sourceRHS) {
|
||||
List<ParameterBinding> availableParams = new ArrayList<>( method.getParameters().size() + 3 );
|
||||
|
||||
if ( sourceRHS != null ) {
|
||||
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
||||
availableParams.add( ParameterBinding.fromSourceRHS( sourceRHS ) );
|
||||
}
|
||||
else {
|
||||
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
||||
}
|
||||
|
||||
addTargetRelevantBindings( availableParams, targetType );
|
||||
|
||||
return availableParams;
|
||||
}
|
||||
|
||||
private List<ParameterBinding> getAvailableParameterBindingsFromSourceTypes(List<Type> sourceTypes,
|
||||
Type targetType, Method mappingMethod) {
|
||||
|
||||
List<ParameterBinding> availableParams = new ArrayList<>( sourceTypes.size() + 2 );
|
||||
|
||||
for ( Type sourceType : sourceTypes ) {
|
||||
availableParams.add( ParameterBinding.forSourceTypeBinding( sourceType ) );
|
||||
}
|
||||
|
||||
for ( Parameter param : mappingMethod.getParameters() ) {
|
||||
if ( param.isMappingContext() ) {
|
||||
availableParams.add( ParameterBinding.fromParameter( param ) );
|
||||
}
|
||||
}
|
||||
|
||||
addTargetRelevantBindings( availableParams, targetType );
|
||||
|
||||
return availableParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default parameter bindings for the mapping-target and target-type if not already available.
|
||||
*
|
||||
* @param availableParams Already available params, new entries will be added to this list
|
||||
* @param targetType Target type
|
||||
*/
|
||||
private void addTargetRelevantBindings(List<ParameterBinding> availableParams, Type targetType) {
|
||||
boolean mappingTargetAvailable = false;
|
||||
boolean targetTypeAvailable = false;
|
||||
boolean targetPropertyNameAvailable = false;
|
||||
|
||||
// search available parameter bindings if mapping-target and/or target-type is available
|
||||
for ( ParameterBinding pb : availableParams ) {
|
||||
if ( pb.isMappingTarget() ) {
|
||||
mappingTargetAvailable = true;
|
||||
}
|
||||
else if ( pb.isTargetType() ) {
|
||||
targetTypeAvailable = true;
|
||||
}
|
||||
else if ( pb.isTargetPropertyName() ) {
|
||||
targetPropertyNameAvailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mappingTargetAvailable ) {
|
||||
availableParams.add( ParameterBinding.forMappingTargetBinding( targetType ) );
|
||||
}
|
||||
if ( !targetTypeAvailable ) {
|
||||
availableParams.add( ParameterBinding.forTargetTypeBinding( typeFactory.classTypeOf( targetType ) ) );
|
||||
}
|
||||
if ( !targetPropertyNameAvailable ) {
|
||||
availableParams.add( ParameterBinding.forTargetPropertyNameBinding( typeFactory.getType( String.class ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends Method> SelectedMethod<T> getMatchingParameterBinding(Type returnType,
|
||||
Method mappingMethod, SelectedMethod<T> selectedMethodInfo,
|
||||
SelectionContext context, SelectedMethod<T> selectedMethodInfo,
|
||||
List<List<ParameterBinding>> parameterAssignmentVariants) {
|
||||
|
||||
List<List<ParameterBinding>> matchingParameterAssignmentVariants = new ArrayList<>(
|
||||
@ -200,7 +106,7 @@ public class TypeSelector implements MethodSelector {
|
||||
messager.printMessage(
|
||||
selectedMethod.getExecutable(),
|
||||
Message.LIFECYCLEMETHOD_AMBIGUOUS_PARAMETERS,
|
||||
mappingMethod
|
||||
context.getMappingMethod()
|
||||
);
|
||||
|
||||
return null;
|
||||
|
@ -45,18 +45,16 @@ abstract class XmlElementDeclSelector implements MethodSelector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(Method mappingMethod,
|
||||
List<SelectedMethod<T>> methods,
|
||||
List<Type> sourceTypes,
|
||||
Type mappingTargetType,
|
||||
Type returnType,
|
||||
SelectionCriteria criteria) {
|
||||
public <T extends Method> List<SelectedMethod<T>> getMatchingMethods(List<SelectedMethod<T>> methods,
|
||||
SelectionContext context) {
|
||||
Type resultType = context.getMappingMethod().getResultType();
|
||||
String targetPropertyName = context.getSelectionCriteria().getTargetPropertyName();
|
||||
|
||||
List<SelectedMethod<T>> nameMatches = new ArrayList<>();
|
||||
List<SelectedMethod<T>> scopeMatches = new ArrayList<>();
|
||||
List<SelectedMethod<T>> nameAndScopeMatches = new ArrayList<>();
|
||||
XmlElementRefInfo xmlElementRefInfo =
|
||||
findXmlElementRef( mappingMethod.getResultType(), criteria.getTargetPropertyName() );
|
||||
findXmlElementRef( resultType, targetPropertyName );
|
||||
|
||||
for ( SelectedMethod<T> candidate : methods ) {
|
||||
if ( !( candidate.getMethod() instanceof SourceMethod ) ) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.processor.creation;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
import static org.mapstruct.ap.internal.util.Collections.firstKey;
|
||||
import static org.mapstruct.ap.internal.util.Collections.firstValue;
|
||||
@ -57,6 +56,7 @@ 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.selector.MethodSelectors;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionContext;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionCriteria;
|
||||
import org.mapstruct.ap.internal.util.Collections;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
@ -116,7 +116,7 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
|
||||
this.conversions = new Conversions( typeFactory );
|
||||
this.builtInMethods = new BuiltInMappingMethods( typeFactory );
|
||||
this.methodSelectors = new MethodSelectors( typeUtils, elementUtils, typeFactory, messager );
|
||||
this.methodSelectors = new MethodSelectors( typeUtils, elementUtils, messager );
|
||||
|
||||
this.verboseLogging = verboseLogging;
|
||||
}
|
||||
@ -491,12 +491,8 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
|
||||
private <T extends Method> List<SelectedMethod<T>> getBestMatch(List<T> methods, Type source, Type target) {
|
||||
return methodSelectors.getMatchingMethods(
|
||||
mappingMethod,
|
||||
methods,
|
||||
singletonList( source ),
|
||||
target,
|
||||
target,
|
||||
selectionCriteria
|
||||
SelectionContext.forMappingMethods( mappingMethod, source, target, selectionCriteria, typeFactory )
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user