mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
parent
9c33199a66
commit
d50e41cdbb
@ -89,25 +89,15 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
|
||||
false
|
||||
);
|
||||
|
||||
Assignment assignment = ctx.getMappingResolver().getTargetAssignment(
|
||||
method,
|
||||
Assignment assignment = ctx.getMappingResolver().getTargetAssignment( method,
|
||||
targetElementType,
|
||||
formattingParameters,
|
||||
criteria,
|
||||
sourceRHS,
|
||||
null
|
||||
null,
|
||||
() -> forge( sourceRHS, sourceElementType, targetElementType )
|
||||
);
|
||||
|
||||
if ( assignment == null && !criteria.hasQualfiers() ) {
|
||||
assignment = forgeMapping( sourceRHS, sourceElementType, targetElementType );
|
||||
if ( assignment != null ) {
|
||||
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_CREATE_ELEMENT_NOTE, assignment );
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_SELECT_ELEMENT_NOTE, assignment );
|
||||
}
|
||||
|
||||
if ( assignment == null ) {
|
||||
if ( method instanceof ForgedMethod ) {
|
||||
// leave messaging to calling property mapping
|
||||
@ -124,6 +114,7 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_SELECT_ELEMENT_NOTE, assignment );
|
||||
if ( method instanceof ForgedMethod ) {
|
||||
ForgedMethod forgedMethod = (ForgedMethod) method;
|
||||
forgedMethod.addThrownTypes( assignment.getThrownTypes() );
|
||||
@ -171,6 +162,14 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
|
||||
);
|
||||
}
|
||||
|
||||
private Assignment forge(SourceRHS sourceRHS, Type sourceType, Type targetType) {
|
||||
Assignment assignment = super.forgeMapping( sourceRHS, sourceType, targetType );
|
||||
if ( assignment != null ) {
|
||||
ctx.getMessager().note( 2, Message.ITERABLEMAPPING_CREATE_ELEMENT_NOTE, assignment );
|
||||
}
|
||||
return assignment;
|
||||
}
|
||||
|
||||
protected abstract M instantiateMappingMethod(Method method, Collection<String> existingVariables,
|
||||
Assignment assignment, MethodReference factoryMethod,
|
||||
boolean mapNullToDefault, String loopVariableName,
|
||||
|
@ -97,19 +97,10 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
keyFormattingParameters,
|
||||
keyCriteria,
|
||||
keySourceRHS,
|
||||
null
|
||||
null,
|
||||
() -> forge( keySourceRHS, keySourceType, keyTargetType, Message.MAPMAPPING_CREATE_KEY_NOTE )
|
||||
);
|
||||
|
||||
if ( keyAssignment == null && !keyCriteria.hasQualfiers( ) ) {
|
||||
keyAssignment = forgeMapping( keySourceRHS, keySourceType, keyTargetType );
|
||||
if ( keyAssignment != null ) {
|
||||
ctx.getMessager().note( 2, Message.MAPMAPPING_CREATE_KEY_NOTE, keyAssignment );
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_KEY_NOTE, keyAssignment );
|
||||
}
|
||||
|
||||
if ( keyAssignment == null ) {
|
||||
if ( method instanceof ForgedMethod ) {
|
||||
// leave messaging to calling property mapping
|
||||
@ -129,6 +120,9 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_KEY_NOTE, keyAssignment );
|
||||
}
|
||||
|
||||
// find mapping method or conversion for value
|
||||
Type valueSourceType = sourceTypeParams.get( 1 ).getTypeBound();
|
||||
@ -146,7 +140,8 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
valueFormattingParameters,
|
||||
valueCriteria,
|
||||
valueSourceRHS,
|
||||
null
|
||||
null,
|
||||
() -> forge( valueSourceRHS, valueSourceType, valueTargetType, Message.MAPMAPPING_CREATE_VALUE_NOTE )
|
||||
);
|
||||
|
||||
if ( method instanceof ForgedMethod ) {
|
||||
@ -159,16 +154,6 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
}
|
||||
}
|
||||
|
||||
if ( valueAssignment == null && !valueCriteria.hasQualfiers( ) ) {
|
||||
valueAssignment = forgeMapping( valueSourceRHS, valueSourceType, valueTargetType );
|
||||
if ( valueAssignment != null ) {
|
||||
ctx.getMessager().note( 2, Message.MAPMAPPING_CREATE_VALUE_NOTE, valueAssignment );
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_VALUE_NOTE, valueAssignment );
|
||||
}
|
||||
|
||||
if ( valueAssignment == null ) {
|
||||
if ( method instanceof ForgedMethod ) {
|
||||
// leave messaging to calling property mapping
|
||||
@ -188,6 +173,9 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().note( 2, Message.MAPMAPPING_SELECT_VALUE_NOTE, valueAssignment );
|
||||
}
|
||||
|
||||
// mapNullToDefault
|
||||
boolean mapNullToDefault = false;
|
||||
@ -222,6 +210,14 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
);
|
||||
}
|
||||
|
||||
Assignment forge(SourceRHS sourceRHS, Type sourceType, Type targetType, Message message ) {
|
||||
Assignment assignment = forgeMapping( sourceRHS, sourceType, targetType );
|
||||
if ( assignment != null ) {
|
||||
ctx.getMessager().note( 2, message, assignment );
|
||||
}
|
||||
return assignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUsePropertyNamesInHistory() {
|
||||
return true;
|
||||
|
@ -11,6 +11,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
@ -93,7 +94,8 @@ public class MappingBuilderContext {
|
||||
Assignment getTargetAssignment(Method mappingMethod, Type targetType,
|
||||
FormattingParameters formattingParameters,
|
||||
SelectionCriteria criteria, SourceRHS sourceRHS,
|
||||
AnnotationMirror positionHint);
|
||||
AnnotationMirror positionHint,
|
||||
Supplier<Assignment> forger);
|
||||
|
||||
Set<SupportingMappingMethod> getUsedSupportedMappings();
|
||||
}
|
||||
|
@ -280,36 +280,17 @@ public class PropertyMapping extends ModelElement {
|
||||
formattingParameters,
|
||||
criteria,
|
||||
rightHandSide,
|
||||
positionHint
|
||||
positionHint,
|
||||
() -> forge( )
|
||||
);
|
||||
}
|
||||
else {
|
||||
assignment = forge();
|
||||
}
|
||||
|
||||
Type sourceType = rightHandSide.getSourceType();
|
||||
// No mapping found. Try to forge a mapping
|
||||
if ( assignment == null && !criteria.hasQualfiers() ) {
|
||||
if ( (sourceType.isCollectionType() || sourceType.isArrayType()) && targetType.isIterableType() ) {
|
||||
assignment = forgeIterableMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
|
||||
}
|
||||
else if ( sourceType.isMapType() && targetType.isMapType() ) {
|
||||
assignment = forgeMapMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
|
||||
}
|
||||
else if ( ( sourceType.isIterableType() && targetType.isStreamType() ) ||
|
||||
( sourceType.isStreamType() && targetType.isStreamType() ) ||
|
||||
( sourceType.isStreamType() && targetType.isIterableType() ) ) {
|
||||
assignment = forgeStreamMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
|
||||
}
|
||||
else {
|
||||
assignment = forgeMapping( rightHandSide );
|
||||
}
|
||||
if ( assignment != null ) {
|
||||
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_CREATE_NOTE, assignment );
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_SELECT_NOTE, assignment );
|
||||
}
|
||||
|
||||
if ( assignment != null ) {
|
||||
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_SELECT_NOTE, assignment );
|
||||
if ( targetType.isCollectionOrMapType() ) {
|
||||
assignment = assignToCollection( targetType, targetWriteAccessorType, assignment );
|
||||
}
|
||||
@ -336,6 +317,29 @@ public class PropertyMapping extends ModelElement {
|
||||
);
|
||||
}
|
||||
|
||||
private Assignment forge( ) {
|
||||
Assignment assignment;
|
||||
Type sourceType = rightHandSide.getSourceType();
|
||||
if ( (sourceType.isCollectionType() || sourceType.isArrayType()) && targetType.isIterableType() ) {
|
||||
assignment = forgeIterableMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
|
||||
}
|
||||
else if ( sourceType.isMapType() && targetType.isMapType() ) {
|
||||
assignment = forgeMapMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
|
||||
}
|
||||
else if ( ( sourceType.isIterableType() && targetType.isStreamType() )
|
||||
|| ( sourceType.isStreamType() && targetType.isStreamType() )
|
||||
|| ( sourceType.isStreamType() && targetType.isIterableType() ) ) {
|
||||
assignment = forgeStreamMapping( sourceType, targetType, rightHandSide, method.getExecutable() );
|
||||
}
|
||||
else {
|
||||
assignment = forgeMapping( rightHandSide );
|
||||
}
|
||||
if ( assignment != null ) {
|
||||
ctx.getMessager().note( 2, Message.PROPERTYMAPPING_CREATE_NOTE, assignment );
|
||||
}
|
||||
return assignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that a mapping could not be created.
|
||||
*/
|
||||
@ -844,7 +848,8 @@ public class PropertyMapping extends ModelElement {
|
||||
formattingParameters,
|
||||
criteria,
|
||||
new SourceRHS( constantExpression, sourceType, existingVariableNames, sourceErrorMessagePart ),
|
||||
positionHint
|
||||
positionHint,
|
||||
() -> null
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -9,6 +9,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
@ -97,7 +98,8 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
public Assignment getTargetAssignment(Method mappingMethod, Type targetType,
|
||||
FormattingParameters formattingParameters,
|
||||
SelectionCriteria criteria, SourceRHS sourceRHS,
|
||||
AnnotationMirror positionHint) {
|
||||
AnnotationMirror positionHint,
|
||||
Supplier<Assignment> forger) {
|
||||
|
||||
ResolvingAttempt attempt = new ResolvingAttempt(
|
||||
sourceModel,
|
||||
@ -105,7 +107,8 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
formattingParameters,
|
||||
sourceRHS,
|
||||
criteria,
|
||||
positionHint
|
||||
positionHint,
|
||||
forger
|
||||
);
|
||||
|
||||
return attempt.getTargetAssignment( sourceRHS.getSourceTypeForMatching(), targetType );
|
||||
@ -136,6 +139,7 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
private final boolean savedPreferUpdateMapping;
|
||||
private final FormattingParameters formattingParameters;
|
||||
private final AnnotationMirror positionHint;
|
||||
private final Supplier<Assignment> forger;
|
||||
|
||||
// resolving via 2 steps creates the possibility of wrong matches, first builtin method matches,
|
||||
// second doesn't. In that case, the first builtin method should not lead to a supported method
|
||||
@ -145,7 +149,8 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
private ResolvingAttempt(List<Method> sourceModel, Method mappingMethod,
|
||||
FormattingParameters formattingParameters, SourceRHS sourceRHS,
|
||||
SelectionCriteria criteria,
|
||||
AnnotationMirror positionHint) {
|
||||
AnnotationMirror positionHint,
|
||||
Supplier<Assignment> forger) {
|
||||
|
||||
this.mappingMethod = mappingMethod;
|
||||
this.methods = filterPossibleCandidateMethods( sourceModel );
|
||||
@ -156,6 +161,7 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
this.selectionCriteria = criteria;
|
||||
this.savedPreferUpdateMapping = criteria.isPreferUpdateMapping();
|
||||
this.positionHint = positionHint;
|
||||
this.forger = forger;
|
||||
}
|
||||
|
||||
private <T extends Method> List<T> filterPossibleCandidateMethods(List<T> candidateMethods) {
|
||||
@ -243,6 +249,19 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
return conversion.getAssignment();
|
||||
}
|
||||
|
||||
if ( hasQualfiers() ) {
|
||||
messager.printMessage(
|
||||
mappingMethod.getExecutable(),
|
||||
positionHint,
|
||||
Message.GENERAL_NO_QUALIFYING_METHOD,
|
||||
Strings.join( selectionCriteria.getQualifiers(), ", " ),
|
||||
Strings.join( selectionCriteria.getQualifiedByNames(), ", " )
|
||||
);
|
||||
}
|
||||
else {
|
||||
return forger.get();
|
||||
}
|
||||
|
||||
// if nothing works, alas, the result is null
|
||||
return null;
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ public enum Message {
|
||||
GENERAL_JODA_NOT_ON_CLASSPATH( "Cannot validate Joda dateformat, no Joda on classpath. Consider adding Joda to the annotation processorpath.", Diagnostic.Kind.WARNING ),
|
||||
GENERAL_NOT_ALL_FORGED_CREATED( "Internal Error in creation of Forged Methods, it was expected all Forged Methods to finished with creation, but %s did not" ),
|
||||
GENERAL_NO_SUITABLE_CONSTRUCTOR( "%s does not have an accessible parameterless constructor." ),
|
||||
GENERAL_NO_QUALIFYING_METHOD( "No qualifying method found for qualifiers: %s and / or qualifying names: %s" ),
|
||||
|
||||
BUILDER_MORE_THAN_ONE_BUILDER_CREATION_METHOD( "More than one builder creation method for \"%s\". Found methods: \"%s\". Builder will not be used. Consider implementing a custom BuilderProvider SPI.", Diagnostic.Kind.WARNING ),
|
||||
BUILDER_NO_BUILD_METHOD_FOUND("No build method \"%s\" found in \"%s\" for \"%s\". Found methods: \"%s\".", Diagnostic.Kind.ERROR ),
|
||||
|
@ -98,7 +98,16 @@ public class QualifierTest {
|
||||
@ExpectedCompilationOutcome(
|
||||
value = CompilationResult.FAILED,
|
||||
diagnostics = {
|
||||
@Diagnostic(type = ErroneousMapper.class,
|
||||
@Diagnostic(
|
||||
type = ErroneousMapper.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 28,
|
||||
messageRegExp =
|
||||
"No qualifying method found for qualifiers: "
|
||||
+ "org.mapstruct.ap.test.selection.qualifier.annotation.NonQualifierAnnotated and "
|
||||
+ "/ or qualifying names: .*"),
|
||||
@Diagnostic(
|
||||
type = ErroneousMapper.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 28,
|
||||
messageRegExp =
|
||||
|
Loading…
x
Reference in New Issue
Block a user