#433 introduce resultType in @Mapping

This commit is contained in:
sjaakd 2015-01-26 20:19:04 +01:00
parent 490d454858
commit adcc89b184
26 changed files with 304 additions and 17 deletions

View File

@ -136,4 +136,11 @@ public @interface Mapping {
* @return the qualifiers
*/
Class<? extends Annotation>[] qualifiedBy() default { };
/**
* Specifies the result type of the mapping method to be used in case multiple mapping methods qualify.
*
* @return the resultType to select
*/
Class<?> resultType() default void.class;
}

View File

@ -134,4 +134,11 @@ public @interface Mapping {
* @return the qualifiers
*/
Class<? extends Annotation>[] qualifiedBy() default { };
/**
* Specifies the result type of the mapping method to be used in case multiple mapping methods qualify.
*
* @return the resultType to select
*/
Class<?> resultType() default void.class;
}

View File

@ -170,6 +170,7 @@ public class BeanMappingMethod extends MappingMethod {
.targetPropertyName( mapping.getTargetName() )
.sourceReference( sourceRef )
.qualifiers( mapping.getQualifiers() )
.resultType( mapping.getResultType() )
.dateFormat( mapping.getDateFormat() )
.build();
handledTargets.add( mapping.getTargetName() );
@ -191,6 +192,7 @@ public class BeanMappingMethod extends MappingMethod {
.targetAccessor( targetProperty )
.dateFormat( mapping.getDateFormat() )
.qualifiers( mapping.getQualifiers() )
.resultType( mapping.getResultType() )
.build();
handledTargets.add( mapping.getTargetName() );
}
@ -277,6 +279,7 @@ public class BeanMappingMethod extends MappingMethod {
.targetPropertyName( targetProperty.getKey() )
.sourceReference( sourceRef )
.qualifiers( mapping != null ? mapping.getQualifiers() : null )
.resultType( mapping != null ? mapping.getResultType() : null )
.dateFormat( mapping != null ? mapping.getDateFormat() : null )
.build();
@ -339,6 +342,7 @@ public class BeanMappingMethod extends MappingMethod {
.targetPropertyName( targetProperty.getKey() )
.sourceReference( sourceRef )
.qualifiers( mapping != null ? mapping.getQualifiers() : null )
.resultType( mapping != null ? mapping.getResultType() : null )
.dateFormat( mapping != null ? mapping.getDateFormat() : null )
.build();

View File

@ -100,6 +100,7 @@ public class IterableMappingMethod extends MappingMethod {
null, // there is no targetPropertyName
dateFormat,
qualifiers,
null, // resulttype does not seem to make sense
loopVariableName
);

View File

@ -102,6 +102,7 @@ public class MapMappingMethod extends MappingMethod {
null, // there is no targetPropertyName
keyDateFormat,
keyQualifiers,
null, // resulttype does not seem to make sense
"entry.getKey()"
);
@ -125,6 +126,7 @@ public class MapMappingMethod extends MappingMethod {
null, // there is no targetPropertyName
valueDateFormat,
valueQualifiers,
null, // resulttype does not seem to make sense
"entry.getValue()"
);

View File

@ -80,6 +80,7 @@ public class MappingBuilderContext {
* @param targetPropertyName name of the target property
* @param dateFormat used for formatting dates in build in methods that need context information
* @param qualifiers used for further select the appropriate mapping method based on class and name
* @param resultType used for further select the appropriate mapping method based on class and name
* @param sourceReference call to source type as string
*
* @return an assignment to a method parameter, which can either be:
@ -92,7 +93,7 @@ public class MappingBuilderContext {
*/
Assignment getTargetAssignment(Method mappingMethod, String mappedElement, Type sourceType, Type targetType,
String targetPropertyName, String dateFormat, List<TypeMirror> qualifiers,
String sourceReference);
TypeMirror resultType, String sourceReference);
/**
* returns a no arg factory method

View File

@ -70,6 +70,7 @@ public class PropertyMapping extends ModelElement {
private String targetPropertyName;
private String dateFormat;
private List<TypeMirror> qualifiers;
private TypeMirror resultType;
private SourceReference sourceReference;
public PropertyMappingBuilder mappingContext(MappingBuilderContext mappingContext) {
@ -102,6 +103,11 @@ public class PropertyMapping extends ModelElement {
return this;
}
public PropertyMappingBuilder resultType(TypeMirror resultType) {
this.resultType = resultType;
return this;
}
public PropertyMappingBuilder dateFormat(String dateFormat) {
this.dateFormat = dateFormat;
return this;
@ -142,6 +148,7 @@ public class PropertyMapping extends ModelElement {
targetPropertyName,
dateFormat,
qualifiers,
resultType,
sourceRefStr
);
@ -450,6 +457,7 @@ public class PropertyMapping extends ModelElement {
private ExecutableElement targetAccessor;
private String dateFormat;
private List<TypeMirror> qualifiers;
private TypeMirror resultType;
public ConstantMappingBuilder mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext;
@ -481,6 +489,11 @@ public class PropertyMapping extends ModelElement {
return this;
}
public ConstantMappingBuilder resultType(TypeMirror resultType) {
this.resultType = resultType;
return this;
}
public PropertyMapping build() {
// source
@ -506,6 +519,7 @@ public class PropertyMapping extends ModelElement {
targetPropertyName,
dateFormat,
qualifiers,
resultType,
constantExpression
);

View File

@ -55,6 +55,7 @@ public class Mapping {
private final String targetName;
private final String dateFormat;
private final List<TypeMirror> qualifiers;
private final TypeMirror resultType;
private final boolean isIgnored;
private final AnnotationMirror mirror;
@ -135,6 +136,9 @@ public class Mapping {
String expression = getExpression( mappingPrism, element, messager );
String dateFormat = mappingPrism.dateFormat().isEmpty() ? null : mappingPrism.dateFormat();
boolean resultTypeIsDefined = !TypeKind.VOID.equals( mappingPrism.resultType().getKind() );
TypeMirror resultType = resultTypeIsDefined ? mappingPrism.resultType() : null;
return new Mapping(
source,
constant,
@ -145,14 +149,17 @@ public class Mapping {
mappingPrism.ignore(),
mappingPrism.mirror,
mappingPrism.values.source(),
mappingPrism.values.target()
mappingPrism.values.target(),
resultType
);
}
@SuppressWarnings( "checkstyle:parameternumber" )
private Mapping(String sourceName, String constant, String javaExpression, String targetName,
String dateFormat, List<TypeMirror> qualifiers,
boolean isIgnored, AnnotationMirror mirror,
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue) {
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
TypeMirror resultType ) {
this.sourceName = sourceName;
this.constant = constant;
this.javaExpression = javaExpression;
@ -163,6 +170,7 @@ public class Mapping {
this.mirror = mirror;
this.sourceAnnotationValue = sourceAnnotationValue;
this.targetAnnotationValue = targetAnnotationValue;
this.resultType = resultType;
}
private static String getExpression(MappingPrism mappingPrism, ExecutableElement element, Messager messager) {
@ -257,6 +265,10 @@ public class Mapping {
return targetReference;
}
public TypeMirror getResultType() {
return resultType;
}
private boolean hasPropertyInReverseMethod(String name, SourceMethod method) {
CollectionMappingStrategyPrism cms = method.getConfig().getCollectionMappingStrategy();
return method.getResultType().getTargetAccessors( cms ).containsKey( name );
@ -303,7 +315,8 @@ public class Mapping {
isIgnored,
mirror,
sourceAnnotationValue,
targetAnnotationValue
targetAnnotationValue,
null
);
reverse.init( method, messager, typeFactory );

View File

@ -170,7 +170,7 @@ public class SourceMethod implements Method {
}
}
//CHECKSTYLE:OFF
@SuppressWarnings( "checkstyle:parameternumber" )
private SourceMethod( Type declaringMapper, ExecutableElement executable, List<Parameter> parameters,
Type returnType, List<Type> exceptionTypes, Map<String, List<Mapping>> mappings,
IterableMapping iterableMapping, MapMapping mapMapping, Types typeUtils,
@ -192,7 +192,6 @@ public class SourceMethod implements Method {
this.messager = messager;
this.config = config;
}
//CHECKSTYLE:ON
private Parameter determineTargetParameter(Iterable<Parameter> parameters) {
for ( Parameter parameter : parameters ) {

View File

@ -124,9 +124,10 @@ public class MappingResolverImpl implements MappingResolver {
String targetPropertyName,
String dateFormat,
List<TypeMirror> qualifiers,
TypeMirror resultType,
String sourceReference) {
SelectionCriteria criteria = new SelectionCriteria(qualifiers, targetPropertyName, null );
SelectionCriteria criteria = new SelectionCriteria(qualifiers, targetPropertyName, resultType );
ResolvingAttempt attempt = new ResolvingAttempt(
sourceModel,

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
/**
*

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
/**
*

View File

@ -0,0 +1,34 @@
/**
* 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.selection.resulttype;
/**
*
* @author Sjaak Derksen
*/
public class AppleFactory {
public Apple createApple() {
return new Apple( "apple" );
}
public GoldenDelicious createGoldenDelicious() {
return new GoldenDelicious( "GoldenDelicious" );
}
}

View File

@ -0,0 +1,37 @@
/**
* 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.selection.resulttype;
/**
*
* @author Sjaak Derksen
*/
public class AppleFamily {
private Apple apple;
public Apple getApple() {
return apple;
}
public void setApple(Apple apple) {
this.apple = apple;
}
}

View File

@ -0,0 +1,37 @@
/**
* 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.selection.resulttype;
/**
*
* @author Sjaak Derksen
*/
public class AppleFamilyDto {
private AppleDto apple;
public AppleDto getApple() {
return apple;
}
public void setApple(AppleDto apple) {
this.apple = apple;
}
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
/**
*

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
/**
*

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
/**
*
@ -31,4 +31,5 @@ public class ConflictingFruitFactory {
public Banana createBanana() {
return new Banana( "banana" );
}
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
/**
*

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
/**
*

View File

@ -0,0 +1,43 @@
/**
* 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.selection.resulttype;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
*
* @author Sjaak Derksen
*/
@Mapper(uses = AppleFactory.class)
public interface FruitFamilyMapper {
FruitFamilyMapper INSTANCE = Mappers.getMapper( FruitFamilyMapper.class );
@Mapping(target = "apple", resultType = GoldenDelicious.class)
AppleFamily map(AppleFamilyDto source);
GoldenDelicious mapToGoldenDelicious(AppleDto source);
@BeanMapping(resultType = Apple.class)
Apple mapToApple(AppleDto source);
}

View File

@ -0,0 +1,31 @@
/**
* 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.selection.resulttype;
/**
*
* @author Sjaak Derksen
*/
public class GoldenDelicious extends Apple {
public GoldenDelicious(String type) {
super( type );
}
}

View File

@ -0,0 +1,31 @@
/**
* 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.selection.resulttype;
/**
*
* @author Sjaak Derksen
*/
public class GoldenDeliciousDto extends AppleDto {
public GoldenDeliciousDto(String type) {
super( type );
}
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
import javax.tools.Diagnostic.Kind;
import static org.fest.assertions.Assertions.assertThat;
@ -71,4 +71,28 @@ public class InheritanceSelectionTest {
}
@Test
@IssueKey("433")
@WithClasses( {
FruitFamilyMapper.class,
GoldenDeliciousDto.class,
GoldenDelicious.class,
AppleFamily.class,
AppleFamilyDto.class,
AppleFactory.class,
Banana.class
} )
public void testShouldSelectResultTypeInCaseOfAmbiguity() {
AppleFamilyDto appleFamilyDto = new AppleFamilyDto();
appleFamilyDto.setApple( new AppleDto("AppleDto") );
AppleFamily result = FruitFamilyMapper.INSTANCE.map( appleFamilyDto );
assertThat( result ).isNotNull();
assertThat( result.getApple() ).isNotNull();
assertThat( result.getApple() ).isInstanceOf( GoldenDelicious.class );
assertThat( result.getApple().getType() ).isEqualTo( "AppleDto" );
}
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.selection.inheritance;
package org.mapstruct.ap.test.selection.resulttype;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;