This commit is contained in:
Gunnar Morling 2014-02-28 19:54:47 +01:00
parent 53ff1b7e13
commit 8ddb2a9fb3
7 changed files with 102 additions and 98 deletions

View File

@ -72,7 +72,7 @@ public class MethodReference extends MappingMethod {
return contextParam; return contextParam;
} }
public void setMethodRefChild( MethodReference methodRefChild ) { public void setMethodRefChild(MethodReference methodRefChild) {
this.methodRefChild = methodRefChild; this.methodRefChild = methodRefChild;
} }
@ -83,7 +83,7 @@ public class MethodReference extends MappingMethod {
@Override @Override
public Set<Type> getImportTypes() { public Set<Type> getImportTypes() {
Set<Type> imported = super.getImportTypes(); Set<Type> imported = super.getImportTypes();
if (methodRefChild != null) { if ( methodRefChild != null ) {
imported.addAll( methodRefChild.getImportTypes() ); imported.addAll( methodRefChild.getImportTypes() );
} }
return imported; return imported;

View File

@ -26,7 +26,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.annotation.processing.Messager; import javax.annotation.processing.Messager;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
@ -628,43 +627,44 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
conversion conversion
); );
if (!isPropertyMappable( property ) ) { if ( !isPropertyMappable( property ) ) {
// when not mappable, try again with another property mapping method based on parameter only. // when not mappable, try again with another property mapping method based on parameter only.
mappingMethodReference = getMappingMethodReferenceBasedOnParameter( mappingMethodReference = getMappingMethodReferenceBasedOnParameter(
method, method,
"property '" + Executables.getPropertyName( sourceAccessor ) + "'", "property '" + Executables.getPropertyName( sourceAccessor ) + "'",
mapperReferences, mapperReferences,
methods, methods,
sourceType, sourceType,
targetType, targetType,
targetPropertyName, targetPropertyName,
dateFormat ); dateFormat
);
property = new PropertyMapping( property = new PropertyMapping(
parameter.getName(), parameter.getName(),
Executables.getPropertyName( sourceAccessor ), Executables.getPropertyName( sourceAccessor ),
sourceAccessor.getSimpleName().toString(), sourceAccessor.getSimpleName().toString(),
sourceType, sourceType,
Executables.getPropertyName( targetAcessor ), Executables.getPropertyName( targetAcessor ),
targetAcessor.getSimpleName().toString(), targetAcessor.getSimpleName().toString(),
targetType, targetType,
mappingMethodReference, mappingMethodReference,
conversion conversion
); );
} }
if ( !isPropertyMappable( property ) ) { if ( !isPropertyMappable( property ) ) {
messager.printMessage( messager.printMessage(
Kind.ERROR, Kind.ERROR,
String.format( String.format(
"Can't map property \"%s %s\" to \"%s %s\".", "Can't map property \"%s %s\" to \"%s %s\".",
property.getSourceType(), property.getSourceType(),
property.getSourceName(), property.getSourceName(),
property.getTargetType(), property.getTargetType(),
property.getTargetName() property.getTargetName()
), ),
method.getExecutable() method.getExecutable()
); );
} }
return property; return property;
@ -699,17 +699,18 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
); );
if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null && if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null &&
mappingMethodReference == null ) { mappingMethodReference == null ) {
// when no conversion is found and no mapping method try match based on parameter only // when no conversion is found and no mapping method try match based on parameter only
mappingMethodReference = getMappingMethodReferenceBasedOnParameter( mappingMethodReference = getMappingMethodReferenceBasedOnParameter(
method, method,
"collection element", "collection element",
mapperReferences, mapperReferences,
methods, methods,
sourceElementType, sourceElementType,
targetElementType, targetElementType,
null, // there is no targetPropertyName null, // there is no targetPropertyName
dateFormat ); dateFormat
);
} }
if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null && if ( !sourceElementType.isAssignableTo( targetElementType ) && conversion == null &&
@ -759,14 +760,15 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
if ( !keySourceType.isAssignableTo( keyTargetType ) && keyConversion == null && keyMappingMethod == null ) { if ( !keySourceType.isAssignableTo( keyTargetType ) && keyConversion == null && keyMappingMethod == null ) {
// when no conversion is found and no mapping method try match based on parameter only // when no conversion is found and no mapping method try match based on parameter only
keyMappingMethod = getMappingMethodReferenceBasedOnParameter( keyMappingMethod = getMappingMethodReferenceBasedOnParameter(
method, method,
"map key", "map key",
mapperReferences, mapperReferences,
methods, methods,
keySourceType, keySourceType,
keyTargetType, keyTargetType,
null, // there is no targetPropertyName null, // there is no targetPropertyName
keyDateFormat ); keyDateFormat
);
} }
if ( !keySourceType.isAssignableTo( keyTargetType ) && keyConversion == null && keyMappingMethod == null ) { if ( !keySourceType.isAssignableTo( keyTargetType ) && keyConversion == null && keyMappingMethod == null ) {
@ -807,14 +809,15 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
valueMappingMethod == null ) { valueMappingMethod == null ) {
// when no conversion is found and no mapping method try match based on parameter only // when no conversion is found and no mapping method try match based on parameter only
keyMappingMethod = getMappingMethodReferenceBasedOnParameter( keyMappingMethod = getMappingMethodReferenceBasedOnParameter(
method, method,
"map value", "map value",
mapperReferences, mapperReferences,
methods, methods,
valueSourceType, valueSourceType,
valueTargetType, valueTargetType,
null, // there is no targetPropertyName null, // there is no targetPropertyName
valueDateFormat ); valueDateFormat
);
} }
if ( !valueSourceType.isAssignableTo( valueTargetType ) && valueConversion == null && if ( !valueSourceType.isAssignableTo( valueTargetType ) && valueConversion == null &&
@ -991,13 +994,13 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
* Returns a reference to a method mapping the given source type to the given target type, if such a method exists. * Returns a reference to a method mapping the given source type to the given target type, if such a method exists.
*/ */
private MethodReference getMappingMethodReferenceBasedOnMethod(SourceMethod method, private MethodReference getMappingMethodReferenceBasedOnMethod(SourceMethod method,
String mappedElement, String mappedElement,
List<MapperReference> mapperReferences, List<MapperReference> mapperReferences,
List<SourceMethod> methods, List<SourceMethod> methods,
Type sourceType, Type sourceType,
Type targetType, Type targetType,
String targetPropertyName, String targetPropertyName,
String dateFormat) { String dateFormat) {
// first try to find a matching source method // first try to find a matching source method
SourceMethod matchingSourceMethod = getBestMatch( SourceMethod matchingSourceMethod = getBestMatch(
method, method,
@ -1043,17 +1046,18 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
* @param parameterType parameter to match * @param parameterType parameter to match
* @param returnType return type to match * @param returnType return type to match
* @param dateFormat used for formatting dates in build in methods that need context information * @param dateFormat used for formatting dates in build in methods that need context information
*
* @return a method reference. * @return a method reference.
*/ */
private MethodReference getMappingMethodReferenceBasedOnParameter(SourceMethod mappingMethod, private MethodReference getMappingMethodReferenceBasedOnParameter(SourceMethod mappingMethod,
String mappedElement, String mappedElement,
List<MapperReference> List<MapperReference>
mapperReferences, mapperReferences,
List<SourceMethod> methods, List<SourceMethod> methods,
Type parameterType, Type parameterType,
Type returnType, Type returnType,
String targetPropertyName, String targetPropertyName,
String dateFormat) { String dateFormat) {
List<Method> methodYCandidates = new ArrayList<Method>( methods ); List<Method> methodYCandidates = new ArrayList<Method>( methods );
methodYCandidates.addAll( builtInMethods.getBuiltInMethods() ); methodYCandidates.addAll( builtInMethods.getBuiltInMethods() );
@ -1067,25 +1071,29 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
// For each of the candidates, we need to look if there's a methodY, either // For each of the candidates, we need to look if there's a methodY, either
// sourceMethod or builtIn that fits the signature B to C. Only then there is a match. If we have a match // sourceMethod or builtIn that fits the signature B to C. Only then there is a match. If we have a match
// a nested method call can be called. so C = methodY( methodX (A) ) // a nested method call can be called. so C = methodY( methodX (A) )
for (Method methodYCandidate : methodYCandidates ) { for ( Method methodYCandidate : methodYCandidates ) {
if ( methodYCandidate.getSourceParameters().size() == 1 ) { if ( methodYCandidate.getSourceParameters().size() == 1 ) {
methodRefY = getMappingMethodReferenceBasedOnMethod( mappingMethod, methodRefY = getMappingMethodReferenceBasedOnMethod(
mappingMethod,
mappedElement,
mapperReferences,
methods,
methodYCandidate.getParameters().get( 0 ).getType(),
returnType,
targetPropertyName,
dateFormat
);
if ( methodRefY != null ) {
MethodReference methodRefX = getMappingMethodReferenceBasedOnMethod(
mappingMethod,
mappedElement, mappedElement,
mapperReferences, mapperReferences,
methods, methods,
methodYCandidate.getParameters().get( 0 ).getType(), parameterType,
returnType, methodYCandidate.getSourceParameters().get( 0 ).getType(),
targetPropertyName, targetPropertyName,
dateFormat ); dateFormat
if ( methodRefY != null ) { );
MethodReference methodRefX = getMappingMethodReferenceBasedOnMethod( mappingMethod,
mappedElement,
mapperReferences,
methods,
parameterType,
methodYCandidate.getSourceParameters().get( 0 ).getType(),
targetPropertyName,
dateFormat );
if ( methodRefX != null ) { if ( methodRefX != null ) {
methodRefY.setMethodRefChild( methodRefX ); methodRefY.setMethodRefChild( methodRefX );
break; break;

View File

@ -21,7 +21,6 @@ package org.mapstruct.ap.test.nestedmethodcall;
import java.util.List; import java.util.List;
/** /**
*
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
public class OrderDetailsDto { public class OrderDetailsDto {
@ -33,7 +32,7 @@ public class OrderDetailsDto {
return name; return name;
} }
public void setName( String name ) { public void setName(String name) {
this.name = name; this.name = name;
} }
@ -41,7 +40,7 @@ public class OrderDetailsDto {
return description; return description;
} }
public void setDescription( List<String> description ) { public void setDescription(List<String> description) {
this.description = description; this.description = description;
} }

View File

@ -23,7 +23,6 @@ import java.util.List;
import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBElement;
/** /**
*
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
public class OrderDetailsType { public class OrderDetailsType {
@ -39,7 +38,7 @@ public class OrderDetailsType {
this.name = value; this.name = value;
} }
public void setDescription( List<JAXBElement<String>> description ) { public void setDescription(List<JAXBElement<String>> description) {
this.description = description; this.description = description;
} }

View File

@ -22,7 +22,6 @@ package org.mapstruct.ap.test.nestedmethodcall;
import java.util.List; import java.util.List;
/** /**
*
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
public class OrderDto { public class OrderDto {
@ -35,7 +34,7 @@ public class OrderDto {
return orderNumber; return orderNumber;
} }
public void setOrderNumber( Long orderNumber ) { public void setOrderNumber(Long orderNumber) {
this.orderNumber = orderNumber; this.orderNumber = orderNumber;
} }
@ -43,7 +42,7 @@ public class OrderDto {
return orderDetails; return orderDetails;
} }
public void setOrderDetails( OrderDetailsDto orderDetails ) { public void setOrderDetails(OrderDetailsDto orderDetails) {
this.orderDetails = orderDetails; this.orderDetails = orderDetails;
} }
@ -51,7 +50,7 @@ public class OrderDto {
return dates; return dates;
} }
public void setDates( List<String> dates ) { public void setDates(List<String> dates) {
this.dates = dates; this.dates = dates;
} }

View File

@ -24,7 +24,6 @@ import javax.xml.bind.JAXBElement;
import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.XMLGregorianCalendar;
/** /**
*
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
public class OrderType { public class OrderType {
@ -54,7 +53,7 @@ public class OrderType {
return dates; return dates;
} }
public void setDates( List<JAXBElement<XMLGregorianCalendar>> dates ) { public void setDates(List<JAXBElement<XMLGregorianCalendar>> dates) {
this.dates = dates; this.dates = dates;
} }

View File

@ -22,22 +22,22 @@ package org.mapstruct.ap.test.nestedmethodcall;
import java.util.List; import java.util.List;
import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBElement;
import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.XMLGregorianCalendar;
import org.mapstruct.IterableMapping; import org.mapstruct.IterableMapping;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
*
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
@Mapper @Mapper
public interface SourceTargetMapper { public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
OrderDto sourceToTarget(OrderType source); OrderDto sourceToTarget(OrderType source);
OrderDetailsDto detailsToDto(OrderDetailsType source);
OrderDetailsDto detailsToDto(OrderDetailsType source);
@IterableMapping(dateFormat = "dd.MM.yyyy") @IterableMapping(dateFormat = "dd.MM.yyyy")
List<String> stringListToDateList(List<JAXBElement<XMLGregorianCalendar>> dates); List<String> stringListToDateList(List<JAXBElement<XMLGregorianCalendar>> dates);