#2983 Add @AnnotateWith support to non bean mapping methods

This commit is contained in:
Orange Add 2022-08-28 18:33:46 +08:00 committed by GitHub
parent 4708f4b2aa
commit ac356cab25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 264 additions and 32 deletions

View File

@ -13,6 +13,9 @@ import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.util.Strings; import org.mapstruct.ap.internal.util.Strings;
import java.util.ArrayList;
import java.util.List;
/** /**
* An abstract builder that can be reused for building {@link MappingMethod}(s). * An abstract builder that can be reused for building {@link MappingMethod}(s).
* *
@ -117,4 +120,15 @@ public abstract class AbstractMappingMethodBuilder<B extends AbstractMappingMeth
return description; return description;
} }
public List<Annotation> getMethodAnnotations() {
AdditionalAnnotationsBuilder additionalAnnotationsBuilder =
new AdditionalAnnotationsBuilder(
ctx.getElementUtils(),
ctx.getTypeFactory(),
ctx.getMessager() );
List<Annotation> annotations = new ArrayList<>();
annotations.addAll( additionalAnnotationsBuilder.getProcessedAnnotations( method.getExecutable() ) );
return annotations;
}
} }

View File

@ -85,7 +85,6 @@ import static org.mapstruct.ap.internal.util.Message.PROPERTYMAPPING_CANNOT_DETE
*/ */
public class BeanMappingMethod extends NormalTypeMappingMethod { public class BeanMappingMethod extends NormalTypeMappingMethod {
private final List<Annotation> annotations;
private final List<PropertyMapping> propertyMappings; private final List<PropertyMapping> propertyMappings;
private final Map<String, List<PropertyMapping>> mappingsByParameter; private final Map<String, List<PropertyMapping>> mappingsByParameter;
private final Map<String, List<PropertyMapping>> constructorMappingsByParameter; private final Map<String, List<PropertyMapping>> constructorMappingsByParameter;
@ -113,7 +112,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
private final Set<Parameter> unprocessedSourceParameters = new HashSet<>(); private final Set<Parameter> unprocessedSourceParameters = new HashSet<>();
private final Set<String> existingVariableNames = new HashSet<>(); private final Set<String> existingVariableNames = new HashSet<>();
private final Map<String, Set<MappingReference>> unprocessedDefinedTargets = new LinkedHashMap<>(); private final Map<String, Set<MappingReference>> unprocessedDefinedTargets = new LinkedHashMap<>();
private final List<Annotation> annotations = new ArrayList<>();
private MappingReferences mappingReferences; private MappingReferences mappingReferences;
private MethodReference factoryMethod; private MethodReference factoryMethod;
@ -216,12 +214,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
// If the return type cannot be constructed then no need to try to create mappings // If the return type cannot be constructed then no need to try to create mappings
return null; return null;
} }
AdditionalAnnotationsBuilder additionalAnnotationsBuilder =
new AdditionalAnnotationsBuilder(
ctx.getElementUtils(),
ctx.getTypeFactory(),
ctx.getMessager() );
annotations.addAll( additionalAnnotationsBuilder.getProcessedAnnotations( method.getExecutable() ) );
/* the type that needs to be used in the mapping process as target */ /* the type that needs to be used in the mapping process as target */
Type resultTypeToMap = returnTypeToConstruct == null ? method.getResultType() : returnTypeToConstruct; Type resultTypeToMap = returnTypeToConstruct == null ? method.getResultType() : returnTypeToConstruct;
@ -370,7 +362,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
return new BeanMappingMethod( return new BeanMappingMethod(
method, method,
annotations, getMethodAnnotations(),
existingVariableNames, existingVariableNames,
propertyMappings, propertyMappings,
factoryMethod, factoryMethod,
@ -1724,6 +1716,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
List<SubclassMapping> subclassMappings) { List<SubclassMapping> subclassMappings) {
super( super(
method, method,
annotations,
existingVariableNames, existingVariableNames,
factoryMethod, factoryMethod,
mapNullToDefault, mapNullToDefault,
@ -1732,7 +1725,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
); );
//CHECKSTYLE:ON //CHECKSTYLE:ON
this.annotations = annotations;
this.propertyMappings = propertyMappings; this.propertyMappings = propertyMappings;
this.returnTypeBuilder = returnTypeBuilder; this.returnTypeBuilder = returnTypeBuilder;
this.finalizerMethod = finalizerMethod; this.finalizerMethod = finalizerMethod;
@ -1771,10 +1763,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
this.subclassMappings = subclassMappings; this.subclassMappings = subclassMappings;
} }
public List<Annotation> getAnnotations() {
return annotations;
}
public List<PropertyMapping> getConstantMappings() { public List<PropertyMapping> getConstantMappings() {
return constantMappings; return constantMappings;
} }

View File

@ -32,12 +32,13 @@ public abstract class ContainerMappingMethod extends NormalTypeMappingMethod {
private final String index2Name; private final String index2Name;
private IterableCreation iterableCreation; private IterableCreation iterableCreation;
ContainerMappingMethod(Method method, Collection<String> existingVariables, Assignment parameterAssignment, ContainerMappingMethod(Method method, List<Annotation> annotations,
Collection<String> existingVariables, Assignment parameterAssignment,
MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName, MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences, List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences, List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters) { SelectionParameters selectionParameters) {
super( method, existingVariables, factoryMethod, mapNullToDefault, beforeMappingReferences, super( method, annotations, existingVariables, factoryMethod, mapNullToDefault, beforeMappingReferences,
afterMappingReferences ); afterMappingReferences );
this.elementAssignment = parameterAssignment; this.elementAssignment = parameterAssignment;
this.loopVariableName = loopVariableName; this.loopVariableName = loopVariableName;

View File

@ -57,6 +57,7 @@ public class IterableMappingMethod extends ContainerMappingMethod {
List<LifecycleCallbackMethodReference> afterMappingMethods, SelectionParameters selectionParameters) { List<LifecycleCallbackMethodReference> afterMappingMethods, SelectionParameters selectionParameters) {
return new IterableMappingMethod( return new IterableMappingMethod(
method, method,
getMethodAnnotations(),
existingVariables, existingVariables,
assignment, assignment,
factoryMethod, factoryMethod,
@ -69,13 +70,15 @@ public class IterableMappingMethod extends ContainerMappingMethod {
} }
} }
private IterableMappingMethod(Method method, Collection<String> existingVariables, Assignment parameterAssignment, private IterableMappingMethod(Method method, List<Annotation> annotations,
Collection<String> existingVariables, Assignment parameterAssignment,
MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName, MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences, List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences, List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters) { SelectionParameters selectionParameters) {
super( super(
method, method,
annotations,
existingVariables, existingVariables,
parameterAssignment, parameterAssignment,
factoryMethod, factoryMethod,

View File

@ -199,6 +199,7 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
return new MapMappingMethod( return new MapMappingMethod(
method, method,
getMethodAnnotations(),
existingVariables, existingVariables,
keyAssignment, keyAssignment,
valueAssignment, valueAssignment,
@ -224,11 +225,12 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
} }
private MapMappingMethod(Method method, Collection<String> existingVariableNames, Assignment keyAssignment, private MapMappingMethod(Method method, List<Annotation> annotations,
Collection<String> existingVariableNames, Assignment keyAssignment,
Assignment valueAssignment, MethodReference factoryMethod, boolean mapNullToDefault, Assignment valueAssignment, MethodReference factoryMethod, boolean mapNullToDefault,
List<LifecycleCallbackMethodReference> beforeMappingReferences, List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences) { List<LifecycleCallbackMethodReference> afterMappingReferences) {
super( method, existingVariableNames, factoryMethod, mapNullToDefault, beforeMappingReferences, super( method, annotations, existingVariableNames, factoryMethod, mapNullToDefault, beforeMappingReferences,
afterMappingReferences ); afterMappingReferences );
this.keyAssignment = keyAssignment; this.keyAssignment = keyAssignment;

View File

@ -24,7 +24,10 @@ public abstract class NormalTypeMappingMethod extends MappingMethod {
private final boolean overridden; private final boolean overridden;
private final boolean mapNullToDefault; private final boolean mapNullToDefault;
NormalTypeMappingMethod(Method method, Collection<String> existingVariableNames, MethodReference factoryMethod, private final List<Annotation> annotations;
NormalTypeMappingMethod(Method method, List<Annotation> annotations,
Collection<String> existingVariableNames, MethodReference factoryMethod,
boolean mapNullToDefault, boolean mapNullToDefault,
List<LifecycleCallbackMethodReference> beforeMappingReferences, List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences) { List<LifecycleCallbackMethodReference> afterMappingReferences) {
@ -32,6 +35,7 @@ public abstract class NormalTypeMappingMethod extends MappingMethod {
this.factoryMethod = factoryMethod; this.factoryMethod = factoryMethod;
this.overridden = method.overridesMethod(); this.overridden = method.overridesMethod();
this.mapNullToDefault = mapNullToDefault; this.mapNullToDefault = mapNullToDefault;
this.annotations = annotations;
} }
@Override @Override
@ -45,6 +49,9 @@ public abstract class NormalTypeMappingMethod extends MappingMethod {
else if ( factoryMethod != null ) { else if ( factoryMethod != null ) {
types.addAll( factoryMethod.getImportTypes() ); types.addAll( factoryMethod.getImportTypes() );
} }
for ( Annotation annotation : annotations ) {
types.addAll( annotation.getImportTypes() );
}
return types; return types;
} }
@ -60,6 +67,10 @@ public abstract class NormalTypeMappingMethod extends MappingMethod {
return this.factoryMethod; return this.factoryMethod;
} }
public List<Annotation> getAnnotations() {
return annotations;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;

View File

@ -5,6 +5,12 @@
*/ */
package org.mapstruct.ap.internal.model; package org.mapstruct.ap.internal.model;
import org.mapstruct.ap.internal.model.assignment.Java8FunctionWrapper;
import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -13,12 +19,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import org.mapstruct.ap.internal.model.assignment.Java8FunctionWrapper;
import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
import static org.mapstruct.ap.internal.util.Collections.first; import static org.mapstruct.ap.internal.util.Collections.first;
/** /**
@ -63,9 +63,9 @@ public class StreamMappingMethod extends ContainerMappingMethod {
sourceParameterType.isIterableType() ) { sourceParameterType.isIterableType() ) {
helperImports.add( ctx.getTypeFactory().getType( StreamSupport.class ) ); helperImports.add( ctx.getTypeFactory().getType( StreamSupport.class ) );
} }
return new StreamMappingMethod( return new StreamMappingMethod(
method, method,
getMethodAnnotations(),
existingVariables, existingVariables,
assignment, assignment,
factoryMethod, factoryMethod,
@ -78,14 +78,16 @@ public class StreamMappingMethod extends ContainerMappingMethod {
); );
} }
} }
//CHECKSTYLE:OFF
private StreamMappingMethod(Method method, Collection<String> existingVariables, Assignment parameterAssignment, private StreamMappingMethod(Method method, List<Annotation> annotations,
Collection<String> existingVariables, Assignment parameterAssignment,
MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName, MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences, List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences, List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters, Set<Type> helperImports) { SelectionParameters selectionParameters, Set<Type> helperImports) {
super( super(
method, method,
annotations,
existingVariables, existingVariables,
parameterAssignment, parameterAssignment,
factoryMethod, factoryMethod,
@ -95,6 +97,7 @@ public class StreamMappingMethod extends ContainerMappingMethod {
afterMappingReferences, afterMappingReferences,
selectionParameters selectionParameters
); );
//CHECKSTYLE:ON
this.helperImports = helperImports; this.helperImports = helperImports;
} }

View File

@ -41,6 +41,7 @@ import static org.mapstruct.ap.internal.util.Collections.first;
*/ */
public class ValueMappingMethod extends MappingMethod { public class ValueMappingMethod extends MappingMethod {
private final List<Annotation> annotations;
private final List<MappingEntry> valueMappings; private final List<MappingEntry> valueMappings;
private final MappingEntry defaultTarget; private final MappingEntry defaultTarget;
private final MappingEntry nullTarget; private final MappingEntry nullTarget;
@ -116,9 +117,16 @@ public class ValueMappingMethod extends MappingMethod {
LifecycleMethodResolver.beforeMappingMethods( method, selectionParameters, ctx, existingVariables ); LifecycleMethodResolver.beforeMappingMethods( method, selectionParameters, ctx, existingVariables );
List<LifecycleCallbackMethodReference> afterMappingMethods = List<LifecycleCallbackMethodReference> afterMappingMethods =
LifecycleMethodResolver.afterMappingMethods( method, selectionParameters, ctx, existingVariables ); LifecycleMethodResolver.afterMappingMethods( method, selectionParameters, ctx, existingVariables );
AdditionalAnnotationsBuilder additionalAnnotationsBuilder =
new AdditionalAnnotationsBuilder(
ctx.getElementUtils(),
ctx.getTypeFactory(),
ctx.getMessager() );
List<Annotation> annotations = new ArrayList<>();
annotations.addAll( additionalAnnotationsBuilder.getProcessedAnnotations( method.getExecutable() ) );
// finally return a mapping // finally return a mapping
return new ValueMappingMethod( method, return new ValueMappingMethod( method,
annotations,
mappingEntries, mappingEntries,
valueMappings.nullValueTarget, valueMappings.nullValueTarget,
valueMappings.defaultTargetValue, valueMappings.defaultTargetValue,
@ -532,6 +540,7 @@ public class ValueMappingMethod extends MappingMethod {
} }
private ValueMappingMethod(Method method, private ValueMappingMethod(Method method,
List<Annotation> annotations,
List<MappingEntry> enumMappings, List<MappingEntry> enumMappings,
String nullTarget, String nullTarget,
String defaultTarget, String defaultTarget,
@ -544,6 +553,7 @@ public class ValueMappingMethod extends MappingMethod {
this.defaultTarget = new MappingEntry( null, defaultTarget != null ? defaultTarget : THROW_EXCEPTION); this.defaultTarget = new MappingEntry( null, defaultTarget != null ? defaultTarget : THROW_EXCEPTION);
this.unexpectedValueMappingException = unexpectedValueMappingException; this.unexpectedValueMappingException = unexpectedValueMappingException;
this.overridden = method.overridesMethod(); this.overridden = method.overridesMethod();
this.annotations = annotations;
} }
@Override @Override
@ -556,7 +566,9 @@ public class ValueMappingMethod extends MappingMethod {
importTypes.addAll( unexpectedValueMappingException.getImportTypes() ); importTypes.addAll( unexpectedValueMappingException.getImportTypes() );
} }
} }
for ( Annotation annotation : annotations ) {
importTypes.addAll( annotation.getImportTypes() );
}
return importTypes; return importTypes;
} }
@ -590,6 +602,10 @@ public class ValueMappingMethod extends MappingMethod {
return overridden; return overridden;
} }
public List<Annotation> getAnnotations() {
return annotations;
}
public static class MappingEntry { public static class MappingEntry {
private final String source; private final String source;
private final String target; private final String target;

View File

@ -6,6 +6,9 @@
--> -->
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.IterableMappingMethod" --> <#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.IterableMappingMethod" -->
<#list annotations as annotation>
<#nt><@includeModel object=annotation/>
</#list>
<#if overridden>@Override</#if> <#if overridden>@Override</#if>
<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> { <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> {
<#list beforeMappingReferencesWithoutMappingTarget as callback> <#list beforeMappingReferencesWithoutMappingTarget as callback>

View File

@ -6,6 +6,9 @@
--> -->
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.MapMappingMethod" --> <#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.MapMappingMethod" -->
<#list annotations as annotation>
<#nt><@includeModel object=annotation/>
</#list>
<#if overridden>@Override</#if> <#if overridden>@Override</#if>
<#lt>${accessibility.keyword} <@includeModel object=returnType /> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> { <#lt>${accessibility.keyword} <@includeModel object=returnType /> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> {
<#list beforeMappingReferencesWithoutMappingTarget as callback> <#list beforeMappingReferencesWithoutMappingTarget as callback>

View File

@ -6,6 +6,9 @@
--> -->
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.StreamMappingMethod" --> <#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.StreamMappingMethod" -->
<#list annotations as annotation>
<#nt><@includeModel object=annotation/>
</#list>
<#if overridden>@Override</#if> <#if overridden>@Override</#if>
<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> { <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> {
<#--TODO does it even make sense to do a callback if the result is a Stream, as they are immutable--> <#--TODO does it even make sense to do a callback if the result is a Stream, as they are immutable-->

View File

@ -6,6 +6,9 @@
--> -->
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.ValueMappingMethod" --> <#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.ValueMappingMethod" -->
<#list annotations as annotation>
<#nt><@includeModel object=annotation/>
</#list>
<#if overridden>@Override</#if> <#if overridden>@Override</#if>
<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) { <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) {
<#list beforeMappingReferencesWithoutMappingTarget as callback> <#list beforeMappingReferencesWithoutMappingTarget as callback>

View File

@ -0,0 +1,46 @@
/*
* 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.test.annotatewith;
import org.mapstruct.AnnotateWith;
import org.mapstruct.Mapper;
/**
* @author orange add
*/
@Mapper
public interface AnnotateBeanMappingMethodMapper {
@AnnotateWith(CustomMethodOnlyAnnotation.class)
Target map(Source source);
class Source {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
class Target {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.test.annotatewith;
import org.mapstruct.AnnotateWith;
import org.mapstruct.Mapper;
import java.util.List;
/**
* @author orange add
*/
@Mapper
public interface AnnotateIterableMappingMethodMapper {
@AnnotateWith(CustomMethodOnlyAnnotation.class)
List<String> toStringList(List<Integer> integers);
}

View File

@ -0,0 +1,24 @@
/*
* 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.test.annotatewith;
import org.mapstruct.AnnotateWith;
import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;
import java.util.Date;
import java.util.Map;
/**
* @author orange add
*/
@Mapper
public interface AnnotateMapMappingMethodMapper {
@MapMapping(valueDateFormat = "dd.MM.yyyy")
@AnnotateWith(CustomMethodOnlyAnnotation.class)
Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source);
}

View File

@ -0,0 +1,21 @@
/*
* 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.test.annotatewith;
import org.mapstruct.AnnotateWith;
import org.mapstruct.Mapper;
import java.util.stream.Stream;
/**
* @author orange add
*/
@Mapper
public interface AnnotateStreamMappingMethodMapper {
@AnnotateWith(CustomMethodOnlyAnnotation.class)
Stream<String> toStringStream(Stream<Integer> integerStream);
}

View File

@ -0,0 +1,26 @@
/*
* 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.test.annotatewith;
import org.mapstruct.AnnotateWith;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;
/**
* @author orange add
*/
@Mapper
public interface AnnotateValueMappingMethodMapper {
@ValueMappings({
@ValueMapping(target = "EXISTING", source = "EXISTING"),
@ValueMapping( source = MappingConstants.ANY_REMAINING, target = "OTHER_EXISTING" )
})
@AnnotateWith(CustomMethodOnlyAnnotation.class)
AnnotateWithEnum map(String str);
}

View File

@ -6,7 +6,6 @@
package org.mapstruct.ap.test.annotatewith; package org.mapstruct.ap.test.annotatewith;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.ProcessorTest;
@ -17,6 +16,11 @@ import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutco
import org.mapstruct.ap.testutil.runner.GeneratedSource; import org.mapstruct.ap.testutil.runner.GeneratedSource;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
@ -545,4 +549,44 @@ public class AnnotateWithTest {
public void mapperWithIdenticalAnnotationRepeated() { public void mapperWithIdenticalAnnotationRepeated() {
} }
@ProcessorTest
@WithClasses( {AnnotateBeanMappingMethodMapper.class, CustomMethodOnlyAnnotation.class} )
public void beanMappingMethodWithCorrectCustomAnnotation() throws NoSuchMethodException {
AnnotateBeanMappingMethodMapper mapper = Mappers.getMapper( AnnotateBeanMappingMethodMapper.class );
Method method = mapper.getClass().getMethod( "map", AnnotateBeanMappingMethodMapper.Source.class );
assertThat( method.getAnnotation( CustomMethodOnlyAnnotation.class ) ).isNotNull();
}
@ProcessorTest
@WithClasses( {AnnotateIterableMappingMethodMapper.class, CustomMethodOnlyAnnotation.class} )
public void iterableMappingMethodWithCorrectCustomAnnotation() throws NoSuchMethodException {
AnnotateIterableMappingMethodMapper mapper = Mappers.getMapper( AnnotateIterableMappingMethodMapper.class );
Method method = mapper.getClass().getMethod( "toStringList", List.class );
assertThat( method.getAnnotation( CustomMethodOnlyAnnotation.class ) ).isNotNull();
}
@ProcessorTest
@WithClasses( {AnnotateMapMappingMethodMapper.class, CustomMethodOnlyAnnotation.class} )
public void mapMappingMethodWithCorrectCustomAnnotation() throws NoSuchMethodException {
AnnotateMapMappingMethodMapper mapper = Mappers.getMapper( AnnotateMapMappingMethodMapper.class );
Method method = mapper.getClass().getMethod( "longDateMapToStringStringMap", Map.class );
assertThat( method.getAnnotation( CustomMethodOnlyAnnotation.class ) ).isNotNull();
}
@ProcessorTest
@WithClasses( {AnnotateStreamMappingMethodMapper.class, CustomMethodOnlyAnnotation.class} )
public void streamMappingMethodWithCorrectCustomAnnotation() throws NoSuchMethodException {
AnnotateStreamMappingMethodMapper mapper = Mappers.getMapper( AnnotateStreamMappingMethodMapper.class );
Method method = mapper.getClass().getMethod( "toStringStream", Stream.class );
assertThat( method.getAnnotation( CustomMethodOnlyAnnotation.class ) ).isNotNull();
}
@ProcessorTest
@WithClasses( {AnnotateValueMappingMethodMapper.class, AnnotateWithEnum.class, CustomMethodOnlyAnnotation.class} )
public void valueMappingMethodWithCorrectCustomAnnotation() throws NoSuchMethodException {
AnnotateValueMappingMethodMapper mapper = Mappers.getMapper( AnnotateValueMappingMethodMapper.class );
Method method = mapper.getClass().getMethod( "map", String.class );
assertThat( method.getAnnotation( CustomMethodOnlyAnnotation.class ) ).isNotNull();
}
} }