org.mapstruct.ap.internal.model.PresenceCheckMethodResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mapstruct-processor Show documentation
Show all versions of mapstruct-processor Show documentation
An annotation processor for generating type-safe bean mappers
/*
* 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;
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.util.Message;
/**
* @author Filip Hrisafov
*/
public final class PresenceCheckMethodResolver {
private PresenceCheckMethodResolver() {
}
public static PresenceCheck getPresenceCheck(
Method method,
SelectionParameters selectionParameters,
MappingBuilderContext ctx
) {
SelectedMethod matchingMethod = findMatchingPresenceCheckMethod(
method,
selectionParameters,
ctx
);
if ( matchingMethod == null ) {
return null;
}
MethodReference methodReference = getPresenceCheckMethodReference( method, matchingMethod, ctx );
return new MethodReferencePresenceCheck( methodReference );
}
private static SelectedMethod findMatchingPresenceCheckMethod(
Method method,
SelectionParameters selectionParameters,
MappingBuilderContext ctx
) {
MethodSelectors selectors = new MethodSelectors(
ctx.getTypeUtils(),
ctx.getElementUtils(),
ctx.getTypeFactory(),
ctx.getMessager()
);
Type booleanType = ctx.getTypeFactory().getType( Boolean.class );
List> matchingMethods = selectors.getMatchingMethods(
method,
getAllAvailableMethods( method, ctx.getSourceModel() ),
Collections.emptyList(),
booleanType,
booleanType,
SelectionCriteria.forPresenceCheckMethods( selectionParameters )
);
if ( matchingMethods.isEmpty() ) {
return null;
}
if ( matchingMethods.size() > 1 ) {
ctx.getMessager().printMessage(
method.getExecutable(),
Message.GENERAL_AMBIGUOUS_PRESENCE_CHECK_METHOD,
selectionParameters.getSourceRHS().getSourceType().describe(),
matchingMethods.stream()
.map( SelectedMethod::getMethod )
.map( Method::describe )
.collect( Collectors.joining( ", " ) )
);
return null;
}
return matchingMethods.get( 0 );
}
private static MethodReference getPresenceCheckMethodReference(
Method method,
SelectedMethod matchingMethod,
MappingBuilderContext ctx
) {
Parameter providingParameter =
method.getContextProvidedMethods().getParameterForProvidedMethod( matchingMethod.getMethod() );
if ( providingParameter != null ) {
return MethodReference.forParameterProvidedMethod(
matchingMethod.getMethod(),
providingParameter,
matchingMethod.getParameterBindings()
);
}
else {
MapperReference ref = MapperReference.findMapperReference(
ctx.getMapperReferences(),
matchingMethod.getMethod()
);
return MethodReference.forMapperReference(
matchingMethod.getMethod(),
ref,
matchingMethod.getParameterBindings()
);
}
}
private static List getAllAvailableMethods(Method method, List sourceModelMethods) {
ParameterProvidedMethods contextProvidedMethods = method.getContextProvidedMethods();
if ( contextProvidedMethods.isEmpty() ) {
return sourceModelMethods;
}
List methodsProvidedByParams = contextProvidedMethods
.getAllProvidedMethodsInParameterOrder( method.getContextParameters() );
List availableMethods =
new ArrayList<>( methodsProvidedByParams.size() + sourceModelMethods.size() );
for ( SourceMethod methodProvidedByParams : methodsProvidedByParams ) {
// add only methods from context that do have the @Condition annotation
if ( methodProvidedByParams.isPresenceCheck() ) {
availableMethods.add( methodProvidedByParams );
}
}
availableMethods.addAll( sourceModelMethods );
return availableMethods;
}
}