#14 Consider qualifiers when selecting @BeforeMapping/@AfterMapping methods

This commit is contained in:
Andreas Gudian 2015-04-04 17:42:45 +02:00
parent ac8320b0a3
commit 68fc3af645
11 changed files with 257 additions and 50 deletions

View File

@ -163,9 +163,9 @@ public class BeanMappingMethod extends MappingMethod {
sortPropertyMappingsByDependencies(); sortPropertyMappingsByDependencies();
List<LifecycleCallbackMethodReference> beforeMappingMethods = List<LifecycleCallbackMethodReference> beforeMappingMethods =
LifecycleCallbackFactory.beforeMappingMethods( method, ctx ); LifecycleCallbackFactory.beforeMappingMethods( method, qualifiers, ctx );
List<LifecycleCallbackMethodReference> afterMappingMethods = List<LifecycleCallbackMethodReference> afterMappingMethods =
LifecycleCallbackFactory.afterMappingMethods( method, ctx ); LifecycleCallbackFactory.afterMappingMethods( method, qualifiers, ctx );
return new BeanMappingMethod( return new BeanMappingMethod(
method, method,

View File

@ -150,9 +150,9 @@ public class IterableMappingMethod extends MappingMethod {
= ctx.getMappingResolver().getFactoryMethod( method, method.getResultType(), null, null ); = ctx.getMappingResolver().getFactoryMethod( method, method.getResultType(), null, null );
List<LifecycleCallbackMethodReference> beforeMappingMethods = List<LifecycleCallbackMethodReference> beforeMappingMethods =
LifecycleCallbackFactory.beforeMappingMethods( method, ctx ); LifecycleCallbackFactory.beforeMappingMethods( method, qualifiers, ctx );
List<LifecycleCallbackMethodReference> afterMappingMethods = List<LifecycleCallbackMethodReference> afterMappingMethods =
LifecycleCallbackFactory.afterMappingMethods( method, ctx ); LifecycleCallbackFactory.afterMappingMethods( method, qualifiers, ctx );
return new IterableMappingMethod( return new IterableMappingMethod(
method, method,

View File

@ -19,14 +19,19 @@
package org.mapstruct.ap.model; package org.mapstruct.ap.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.mapstruct.ap.model.common.Parameter; import org.mapstruct.ap.model.common.Parameter;
import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.Type;
import org.mapstruct.ap.model.source.Method; import org.mapstruct.ap.model.source.Method;
import org.mapstruct.ap.model.source.SourceMethod; import org.mapstruct.ap.model.source.SourceMethod;
import org.mapstruct.ap.model.source.selector.QualifierSelector;
import org.mapstruct.ap.model.source.selector.SelectionCriteria;
/** /**
* Factory for creating lists of appropriate {@link LifecycleCallbackMethodReference}s * Factory for creating lists of appropriate {@link LifecycleCallbackMethodReference}s
@ -40,27 +45,95 @@ public final class LifecycleCallbackFactory {
/** /**
* @param method the method to obtain the beforeMapping methods for * @param method the method to obtain the beforeMapping methods for
* @param qualifiers method qualifiers
* @param ctx the builder context * @param ctx the builder context
* @return all applicable {@code @BeforeMapping} methods for the given method * @return all applicable {@code @BeforeMapping} methods for the given method
*/ */
public static List<LifecycleCallbackMethodReference> beforeMappingMethods( public static List<LifecycleCallbackMethodReference> beforeMappingMethods(
Method method, MappingBuilderContext ctx) { Method method, List<TypeMirror> qualifiers, MappingBuilderContext ctx) {
return collectLifecycleCallbackMethods( method, filterBeforeMappingMethods( ctx.getSourceModel() ), ctx ); return collectLifecycleCallbackMethods(
method,
qualifiers,
filterBeforeMappingMethods( ctx.getSourceModel() ),
ctx );
} }
/** /**
* @param method the method to obtain the afterMapping methods for * @param method the method to obtain the afterMapping methods for
* @param qualifiers method qualifiers
* @param ctx the builder context * @param ctx the builder context
* @return all applicable {@code @AfterMapping} methods for the given method * @return all applicable {@code @AfterMapping} methods for the given method
*/ */
public static List<LifecycleCallbackMethodReference> afterMappingMethods( public static List<LifecycleCallbackMethodReference> afterMappingMethods(
Method method, MappingBuilderContext ctx) { Method method, List<TypeMirror> qualifiers, MappingBuilderContext ctx) {
return collectLifecycleCallbackMethods( method, filterAfterMappingMethods( ctx.getSourceModel() ), ctx ); return collectLifecycleCallbackMethods(
method,
qualifiers,
filterAfterMappingMethods( ctx.getSourceModel() ),
ctx );
} }
private static List<LifecycleCallbackMethodReference> collectLifecycleCallbackMethods( private static List<LifecycleCallbackMethodReference> collectLifecycleCallbackMethods(
Method method, List<SourceMethod> callbackMethods, MappingBuilderContext ctx) { Method method, List<TypeMirror> qualifiers, List<SourceMethod> callbackMethods, MappingBuilderContext ctx) {
Map<SourceMethod, List<Parameter>> parameterAssignmentsForSourceMethod =
new HashMap<SourceMethod, List<Parameter>>();
List<SourceMethod> candidates =
filterCandidatesByType( method, callbackMethods, parameterAssignmentsForSourceMethod, ctx );
candidates = filterCandidatesByQualifiers( method, qualifiers, candidates, ctx );
return toLifecycleCallbackMethodRefs( candidates, parameterAssignmentsForSourceMethod, ctx );
}
private static List<SourceMethod> filterCandidatesByQualifiers(Method method, List<TypeMirror> qualifiers,
List<SourceMethod> candidates,
MappingBuilderContext ctx) {
QualifierSelector selector = new QualifierSelector( ctx.getTypeUtils(), ctx.getElementUtils() );
return selector.getMatchingMethods( method, candidates, null, null, new SelectionCriteria(
qualifiers,
null,
null,
false ) );
}
private static List<LifecycleCallbackMethodReference> toLifecycleCallbackMethodRefs(
List<SourceMethod> candidates, Map<SourceMethod, List<Parameter>> parameterAssignmentsForSourceMethod,
MappingBuilderContext ctx) {
List<LifecycleCallbackMethodReference> result = new ArrayList<LifecycleCallbackMethodReference>();
for ( SourceMethod candidate : candidates ) {
markMapperReferenceAsUsed( ctx.getMapperReferences(), candidate );
result.add( new LifecycleCallbackMethodReference(
candidate,
parameterAssignmentsForSourceMethod.get( candidate ) ) );
}
return result;
}
private static List<SourceMethod> filterCandidatesByType(Method method,
List<SourceMethod> callbackMethods, Map<SourceMethod, List<Parameter>> parameterAssignmentsForSourceMethod,
MappingBuilderContext ctx) {
List<SourceMethod> candidates = new ArrayList<SourceMethod>();
List<Parameter> availableParams = getAvailableParameters( method, ctx );
for ( SourceMethod callback : callbackMethods ) {
List<Parameter> parameterAssignments = getParameterAssignments( availableParams, callback.getParameters() );
if ( parameterAssignments != null
&& callback.matches( extractSourceTypes( parameterAssignments ), method.getResultType() ) ) {
parameterAssignmentsForSourceMethod.put( callback, parameterAssignments );
candidates.add( callback );
}
}
return candidates;
}
private static List<Parameter> getAvailableParameters(Method method, MappingBuilderContext ctx) {
List<Parameter> availableParams = new ArrayList<Parameter>( method.getParameters() ); List<Parameter> availableParams = new ArrayList<Parameter>( method.getParameters() );
if ( method.getMappingTargetParameter() == null ) { if ( method.getMappingTargetParameter() == null ) {
availableParams.add( new Parameter( null, method.getResultType(), true, false ) ); availableParams.add( new Parameter( null, method.getResultType(), true, false ) );
@ -73,23 +146,10 @@ public final class LifecycleCallbackFactory {
true ); true );
availableParams.add( targetTypeParameter ); availableParams.add( targetTypeParameter );
return availableParams;
List<LifecycleCallbackMethodReference> result = new ArrayList<LifecycleCallbackMethodReference>();
for ( SourceMethod callback : callbackMethods ) {
List<Parameter> parameterAssignments = getParameterAssignments( availableParams, callback.getParameters() );
if ( parameterAssignments != null
&& callback.matches( extractSourceTypes( parameterAssignments ), method.getResultType() ) ) {
markMapperReferenceAsUsed( ctx.getMapperReferences(), callback );
result.add( new LifecycleCallbackMethodReference( callback, parameterAssignments ) );
}
}
return result;
} }
private static void markMapperReferenceAsUsed(List<MapperReference> references, SourceMethod method) { private static void markMapperReferenceAsUsed(List<MapperReference> references, Method method) {
for ( MapperReference ref : references ) { for ( MapperReference ref : references ) {
if ( ref.getType().equals( method.getDeclaringMapper() ) ) { if ( ref.getType().equals( method.getDeclaringMapper() ) ) {
ref.setUsed( !method.isStatic() ); ref.setUsed( !method.isStatic() );

View File

@ -192,9 +192,9 @@ public class MapMappingMethod extends MappingMethod {
valueAssignment = new LocalVarWrapper( valueAssignment, method.getThrownTypes() ); valueAssignment = new LocalVarWrapper( valueAssignment, method.getThrownTypes() );
List<LifecycleCallbackMethodReference> beforeMappingMethods = List<LifecycleCallbackMethodReference> beforeMappingMethods =
LifecycleCallbackFactory.beforeMappingMethods( method, ctx ); LifecycleCallbackFactory.beforeMappingMethods( method, null, ctx );
List<LifecycleCallbackMethodReference> afterMappingMethods = List<LifecycleCallbackMethodReference> afterMappingMethods =
LifecycleCallbackFactory.afterMappingMethods( method, ctx ); LifecycleCallbackFactory.afterMappingMethods( method, null, ctx );
return new MapMappingMethod( return new MapMappingMethod(
method, method,

View File

@ -34,16 +34,18 @@ import org.mapstruct.ap.model.source.SourceMethod;
import org.mapstruct.ap.prism.QualifierPrism; import org.mapstruct.ap.prism.QualifierPrism;
/** /**
* This selector selects a best match based on qualifiers name. * This selector selects a best match based on qualifier annotations.
* <p> * <p>
* A method is said to be marked with a qualifier annotation if the class in which it resides is annotated with a * A method is said to be marked with a qualifier annotation if the class in which it resides is annotated with a
* qualifier annotation or if the method itself is annotated with a qualifier annotation or both. * qualifier annotation or if the method itself is annotated with a qualifier annotation or both.
* <p> * <p>
* Rules: * Rules:
* <ol> * <ol>
* <li>If a method is marked with a qualifier annotation, it does not contribute to a match otherwise and is hence * <li>If no qualifiers are requested in the selection criteria, then only candidate methods without any qualifier
* removed from the list of potential mapping methods</li> * annotations remain in the list of potential candidates</li>
* <li>If multiple qualifiers (qualifedBy) are specified, all should match to make a match.</li> * <li>If multiple qualifiers (qualifedBy) are specified, then all of them need to be present at a candidate for it to
* match.</li>
* <li>If no candidate matches the required qualifiers, then all candidates are returned.</li>
* </ol> * </ol>
* *
* @author Sjaak Derksen * @author Sjaak Derksen

View File

@ -46,16 +46,34 @@ public abstract class BaseMapper {
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
} }
@BeforeMapping
@Qualified
public void withSourceBeforeMappingQualified(Source source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
}
@BeforeMapping @BeforeMapping
public void withSourceBeforeMapping(List<Source> source) { public void withSourceBeforeMapping(List<Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
} }
@BeforeMapping
@Qualified
public void withSourceBeforeMappingQualified(List<Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
}
@BeforeMapping @BeforeMapping
public void withSourceBeforeMapping(Map<String, Source> source) { public void withSourceBeforeMapping(Map<String, Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
} }
@BeforeMapping
@Qualified
public void withSourceBeforeMappingQualified(Map<String, Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
}
@BeforeMapping @BeforeMapping
public void withSourceAsObjectBeforeMapping(Object source) { public void withSourceAsObjectBeforeMapping(Object source) {
INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) );
@ -157,16 +175,34 @@ public abstract class BaseMapper {
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
} }
@AfterMapping
@Qualified
public void withTargetAfterMappingQualified(@MappingTarget Target target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
}
@AfterMapping @AfterMapping
public void withTargetAfterMapping(@MappingTarget List<Target> target) { public void withTargetAfterMapping(@MappingTarget List<Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
} }
@AfterMapping
@Qualified
public void withTargetAfterMappingQualified(@MappingTarget List<Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
}
@AfterMapping @AfterMapping
public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) { public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
} }
@AfterMapping
@Qualified
public void withTargetAfterMappingQualified(@MappingTarget Map<String, Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
}
@AfterMapping @AfterMapping
public void withTargetAsObjectAfterMapping(@MappingTarget Object target) { public void withTargetAsObjectAfterMapping(@MappingTarget Object target) {
INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) );
@ -184,5 +220,4 @@ public abstract class BaseMapper {
public static void reset() { public static void reset() {
INVOCATIONS.clear(); INVOCATIONS.clear();
} }
} }

View File

@ -25,7 +25,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.fest.assertions.Assertions;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -35,6 +34,8 @@ import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.fest.assertions.Assertions.assertThat;
/** /**
* Test for callback methods that are defined using {@link BeforeMapping} / {@link AfterMapping} * Test for callback methods that are defined using {@link BeforeMapping} / {@link AfterMapping}
* *
@ -42,7 +43,7 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
*/ */
@RunWith( AnnotationProcessorTestRunner.class ) @RunWith( AnnotationProcessorTestRunner.class )
@WithClasses( { ClassContainingCallbacks.class, Invocation.class, Source.class, Target.class, SourceTargetMapper.class, @WithClasses( { ClassContainingCallbacks.class, Invocation.class, Source.class, Target.class, SourceTargetMapper.class,
SourceTargetCollectionMapper.class, BaseMapper.class } ) SourceTargetCollectionMapper.class, BaseMapper.class, Qualified.class })
@IssueKey("14") @IssueKey("14")
public class CallbackMethodTest { public class CallbackMethodTest {
@ -103,12 +104,29 @@ public class CallbackMethodTest {
assertMapMappingInvocations( BaseMapper.getInvocations() ); assertMapMappingInvocations( BaseMapper.getInvocations() );
} }
@Test
public void qualifiersAreEvaluatedCorrectly() {
Source source = createSource();
Target target = SourceTargetMapper.INSTANCE.qualifiedSourceToTarget( source );
assertQualifiedInvocations( ClassContainingCallbacks.getInvocations(), source, target );
assertQualifiedInvocations( BaseMapper.getInvocations(), source, target );
reset();
List<Source> sourceList = Arrays.asList( createSource() );
List<Target> targetList = SourceTargetCollectionMapper.INSTANCE.qualifiedSourceToTarget( sourceList );
assertQualifiedInvocations( ClassContainingCallbacks.getInvocations(), sourceList, targetList );
assertQualifiedInvocations( BaseMapper.getInvocations(), sourceList, targetList );
}
private void assertBeanMappingInvocations(List<Invocation> invocations) { private void assertBeanMappingInvocations(List<Invocation> invocations) {
Source source = createSource(); Source source = createSource();
Target target = createResultTarget(); Target target = createResultTarget();
Target emptyTarget = createEmptyTarget(); Target emptyTarget = createEmptyTarget();
Assertions.assertThat( invocations ).isEqualTo( beanMappingInvocationList( source, target, emptyTarget ) ); assertThat( invocations ).isEqualTo( beanMappingInvocationList( source, target, emptyTarget ) );
} }
private void assertIterableMappingInvocations(List<Invocation> invocations) { private void assertIterableMappingInvocations(List<Invocation> invocations) {
@ -168,7 +186,7 @@ public class CallbackMethodTest {
expected.addAll( beanMappingInvocationList( source, target, emptyTarget ) ); expected.addAll( beanMappingInvocationList( source, target, emptyTarget ) );
expected.addAll( allAfterMappingMethods( sourceCollection, targetCollection, targetCollectionClass ) ); expected.addAll( allAfterMappingMethods( sourceCollection, targetCollection, targetCollectionClass ) );
Assertions.assertThat( invocations ).isEqualTo( expected ); assertThat( invocations ).isEqualTo( expected );
} }
private List<Invocation> beanMappingInvocationList(Object source, Object target, Object emptyTarget) { private List<Invocation> beanMappingInvocationList(Object source, Object target, Object emptyTarget) {
@ -202,6 +220,24 @@ public class CallbackMethodTest {
new Invocation( "withTargetAsObjectBeforeMapping", emptyTarget ) ) ); new Invocation( "withTargetAsObjectBeforeMapping", emptyTarget ) ) );
} }
private void assertQualifiedInvocations(List<Invocation> actual, Object source, Object target) {
assertThat( actual ).isEqualTo( allQualifiedCallbackMethods( source, target ) );
}
private List<Invocation> allQualifiedCallbackMethods(Object source, Object target) {
List<Invocation> invocations = new ArrayList<Invocation>();
invocations.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
if ( source instanceof List || source instanceof Map ) {
invocations.addAll(
beanMappingInvocationList( createSource(), createResultTarget(), createEmptyTarget() ) );
}
invocations.add( new Invocation( "withTargetAfterMappingQualified", target ) );
return invocations;
}
private Source createSource() { private Source createSource() {
Source source = new Source(); Source source = new Source();
source.setFoo( "foo" ); source.setFoo( "foo" );

View File

@ -43,21 +43,54 @@ public class ClassContainingCallbacks {
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
} }
@BeforeMapping
@Qualified
public void withSourceBeforeMappingQualified(Source source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
}
@BeforeMapping @BeforeMapping
public void withSourceBeforeMapping(List<Source> source) { public void withSourceBeforeMapping(List<Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
} }
@BeforeMapping
@Qualified
public void withSourceBeforeMappingQualified(List<Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
}
@BeforeMapping @BeforeMapping
public void withSourceBeforeMapping(Map<String, Source> source) { public void withSourceBeforeMapping(Map<String, Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
} }
@BeforeMapping
@Qualified
public void withSourceBeforeMappingQualified(Map<String, Source> source) {
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
}
@BeforeMapping @BeforeMapping
public void withSourceAsObjectBeforeMapping(Object source) { public void withSourceAsObjectBeforeMapping(Object source) {
INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) ); INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) );
} }
@BeforeMapping
public <T> void withSourceAndTargetTypeBeforeMapping(Source source, @TargetType Class<T> targetClass) {
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
}
@BeforeMapping
public <T> void withSourceAndTargetTypeBeforeMapping(List<Source> source, @TargetType Class<T> targetClass) {
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
}
@BeforeMapping
public <T> void withSourceAndTargetTypeBeforeMapping(Map<String, Source> source, @TargetType Class<T> targetClass) {
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
}
@BeforeMapping @BeforeMapping
public void withSourceAndTargetBeforeMapping(Source source, @MappingTarget Target target) { public void withSourceAndTargetBeforeMapping(Source source, @MappingTarget Target target) {
INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) );
@ -94,21 +127,6 @@ public class ClassContainingCallbacks {
INVOCATIONS.add( new Invocation( "withTargetAsObjectBeforeMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAsObjectBeforeMapping", target ) );
} }
@BeforeMapping
public <T> void withSourceAndTargetTypeBeforeMapping(Source source, @TargetType Class<T> targetClass) {
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
}
@BeforeMapping
public <T> void withSourceAndTargetTypeBeforeMapping(List<Source> source, @TargetType Class<T> targetClass) {
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
}
@BeforeMapping
public <T> void withSourceAndTargetTypeBeforeMapping(Map<String, Source> source, @TargetType Class<T> targetClass) {
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
}
@AfterMapping @AfterMapping
public void noArgsAfterMapping() { public void noArgsAfterMapping() {
INVOCATIONS.add( new Invocation( "noArgsAfterMapping" ) ); INVOCATIONS.add( new Invocation( "noArgsAfterMapping" ) );
@ -154,16 +172,34 @@ public class ClassContainingCallbacks {
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
} }
@AfterMapping
@Qualified
public void withTargetAfterMappingQualified(@MappingTarget Target target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
}
@AfterMapping @AfterMapping
public void withTargetAfterMapping(@MappingTarget List<Target> target) { public void withTargetAfterMapping(@MappingTarget List<Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
} }
@AfterMapping
@Qualified
public void withTargetAfterMappingQualified(@MappingTarget List<Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
}
@AfterMapping @AfterMapping
public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) { public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
} }
@AfterMapping
@Qualified
public void withTargetAfterMappingQualified(@MappingTarget Map<String, Target> target) {
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
}
@AfterMapping @AfterMapping
public void withTargetAsObjectAfterMapping(@MappingTarget Object target) { public void withTargetAsObjectAfterMapping(@MappingTarget Object target) {
INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) ); INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) );

View File

@ -0,0 +1,30 @@
/**
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.callbacks;
import org.mapstruct.Qualifier;
/**
* @author Andreas Gudian
*
*/
@Qualifier
public @interface Qualified {
}

View File

@ -21,6 +21,7 @@ package org.mapstruct.ap.test.callbacks;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.mapstruct.IterableMapping;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget; import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -36,6 +37,9 @@ public abstract class SourceTargetCollectionMapper extends BaseMapper {
public abstract void sourceToTarget(List<Source> source, @MappingTarget List<Target> target); public abstract void sourceToTarget(List<Source> source, @MappingTarget List<Target> target);
@IterableMapping(qualifiedBy = Qualified.class)
public abstract List<Target> qualifiedSourceToTarget(List<Source> source);
public abstract Map<String, Target> sourceToTarget(Map<String, Source> source); public abstract Map<String, Target> sourceToTarget(Map<String, Source> source);
public abstract void sourceToTarget(Map<String, Source> source, @MappingTarget Map<String, Target> target); public abstract void sourceToTarget(Map<String, Source> source, @MappingTarget Map<String, Target> target);

View File

@ -18,6 +18,7 @@
*/ */
package org.mapstruct.ap.test.callbacks; package org.mapstruct.ap.test.callbacks;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget; import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -30,4 +31,7 @@ public abstract class SourceTargetMapper extends BaseMapper {
public static final SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); public static final SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
public abstract void sourceToTarget(Source source, @MappingTarget Target target); public abstract void sourceToTarget(Source source, @MappingTarget Target target);
@BeanMapping(qualifiedBy = Qualified.class)
public abstract Target qualifiedSourceToTarget(Source source);
} }