mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#32 Replacing BeanMapping with plain list of mapping methods
This commit is contained in:
parent
335b9d77ac
commit
cd0306683f
@ -45,7 +45,6 @@ import javax.tools.JavaFileObject;
|
|||||||
|
|
||||||
import org.mapstruct.ap.conversion.Conversion;
|
import org.mapstruct.ap.conversion.Conversion;
|
||||||
import org.mapstruct.ap.conversion.Conversions;
|
import org.mapstruct.ap.conversion.Conversions;
|
||||||
import org.mapstruct.ap.model.BeanMapping;
|
|
||||||
import org.mapstruct.ap.model.IterableMappingMethod;
|
import org.mapstruct.ap.model.IterableMappingMethod;
|
||||||
import org.mapstruct.ap.model.Mapper;
|
import org.mapstruct.ap.model.Mapper;
|
||||||
import org.mapstruct.ap.model.MappingMethod;
|
import org.mapstruct.ap.model.MappingMethod;
|
||||||
@ -143,7 +142,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
List<Method> methods = retrieveMethods( element, true );
|
List<Method> methods = retrieveMethods( element, true );
|
||||||
|
|
||||||
//2.) build up aggregated "target" model
|
//2.) build up aggregated "target" model
|
||||||
List<BeanMapping> mappings = getMappings(
|
List<MappingMethod> mappings = getMappingMethods(
|
||||||
methods,
|
methods,
|
||||||
getEffectiveUnmappedTargetPolicy( element )
|
getEffectiveUnmappedTargetPolicy( element )
|
||||||
);
|
);
|
||||||
@ -186,48 +185,55 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BeanMapping> getMappings(List<Method> methods,
|
private List<MappingMethod> getMappingMethods(List<Method> methods, ReportingPolicy unmappedTargetPolicy) {
|
||||||
ReportingPolicy unmappedTargetPolicy) {
|
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();
|
||||||
List<BeanMapping> mappings = new ArrayList<BeanMapping>();
|
|
||||||
Set<Method> processedMethods = new HashSet<Method>();
|
|
||||||
|
|
||||||
for ( Method method : methods ) {
|
for ( Method method : methods ) {
|
||||||
if ( processedMethods.contains( method ) || method.getDeclaringMapper() != null ) {
|
if ( method.getDeclaringMapper() != null ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( method.getMappings().isEmpty() ) {
|
||||||
Method reverseMappingMethod = getReverseMappingMethod( methods, method );
|
Method reverseMappingMethod = getReverseMappingMethod( methods, method );
|
||||||
|
if ( reverseMappingMethod != null && !reverseMappingMethod.getMappings().isEmpty() ) {
|
||||||
if ( reverseMappingMethod != null ) {
|
method.setMappings( reverse( reverseMappingMethod.getMappings() ) );
|
||||||
processedMethods.add( reverseMappingMethod );
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isIterableMapping = method.getSourceType().isIterableType() && method.getTargetType()
|
if ( method.isIterableMapping() ) {
|
||||||
.isIterableType();
|
mappingMethods.add( getIterableMappingMethod( methods, method ) );
|
||||||
|
|
||||||
if ( isIterableMapping ) {
|
|
||||||
mappings.add( getIterableBeanMapping( methods, method, reverseMappingMethod ) );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mappings.add( getSimpleBeanMapping( methods, unmappedTargetPolicy, method, reverseMappingMethod ) );
|
mappingMethods.add( getSimpleMappingMethod( methods, method, unmappedTargetPolicy ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mappings;
|
return mappingMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BeanMapping getSimpleBeanMapping(List<Method> methods, ReportingPolicy unmappedTargetPolicy, Method method,
|
private Map<String, Mapping> reverse(Map<String, Mapping> mappings) {
|
||||||
Method rawReverseMappingMethod) {
|
Map<String, Mapping> reversed = new HashMap<String, Mapping>();
|
||||||
|
|
||||||
|
for ( Mapping mapping : mappings.values() ) {
|
||||||
|
reversed.put( mapping.getTargetName(), mapping.reverse() );
|
||||||
|
}
|
||||||
|
return reversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MappingMethod getSimpleMappingMethod(List<Method> methods, Method method,
|
||||||
|
ReportingPolicy unmappedTargetPolicy) {
|
||||||
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
||||||
List<PropertyMapping> reversePropertyMappings = new ArrayList<PropertyMapping>();
|
|
||||||
Set<String> mappedSourceProperties = new HashSet<String>();
|
|
||||||
Set<String> mappedTargetProperties = new HashSet<String>();
|
Set<String> mappedTargetProperties = new HashSet<String>();
|
||||||
|
|
||||||
for ( MappedProperty property : method.getMappedProperties() ) {
|
List<MappedProperty> mappedProperties = retrieveMappedProperties( method );
|
||||||
mappedSourceProperties.add( property.getSourceName() );
|
|
||||||
|
for ( MappedProperty property : mappedProperties ) {
|
||||||
mappedTargetProperties.add( property.getTargetName() );
|
mappedTargetProperties.add( property.getTargetName() );
|
||||||
|
|
||||||
Method propertyMappingMethod = getPropertyMappingMethod( methods, property );
|
MappingMethodReference propertyMappingMethod = getMappingMethodReference(
|
||||||
Method reversePropertyMappingMethod = getReversePropertyMappingMethod( methods, property );
|
methods,
|
||||||
|
property.getSourceType(),
|
||||||
|
property.getTargetType()
|
||||||
|
);
|
||||||
Conversion conversion = conversions.getConversion(
|
Conversion conversion = conversions.getConversion(
|
||||||
property.getSourceType(),
|
property.getSourceType(),
|
||||||
property.getTargetType()
|
property.getTargetType()
|
||||||
@ -235,10 +241,8 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
|
|
||||||
reportErrorIfPropertyCanNotBeMapped(
|
reportErrorIfPropertyCanNotBeMapped(
|
||||||
method,
|
method,
|
||||||
rawReverseMappingMethod,
|
|
||||||
property,
|
property,
|
||||||
propertyMappingMethod,
|
propertyMappingMethod,
|
||||||
reversePropertyMappingMethod,
|
|
||||||
conversion
|
conversion
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -250,84 +254,31 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
property.getSourceType(),
|
property.getSourceType(),
|
||||||
property.getTargetWriteAccessorName(),
|
property.getTargetWriteAccessorName(),
|
||||||
property.getTargetType(),
|
property.getTargetType(),
|
||||||
propertyMappingMethod != null ? new MappingMethodReference(
|
propertyMappingMethod,
|
||||||
propertyMappingMethod.getDeclaringMapper(),
|
|
||||||
propertyMappingMethod.getName(),
|
|
||||||
propertyMappingMethod.getParameterName(),
|
|
||||||
property.getSourceType(),
|
|
||||||
property.getTargetType()
|
|
||||||
) : null,
|
|
||||||
conversion != null ? conversion.to(
|
conversion != null ? conversion.to(
|
||||||
method.getParameterName() + "." + property.getSourceReadAccessorName() + "()",
|
method.getParameterName() + "." + property.getSourceReadAccessorName() + "()",
|
||||||
property.getTargetType()
|
property.getTargetType()
|
||||||
) : null
|
) : null
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if ( rawReverseMappingMethod != null ) {
|
reportErrorForUnmappedTargetPropertiesIfRequired(
|
||||||
reversePropertyMappings.add(
|
method,
|
||||||
new PropertyMapping(
|
unmappedTargetPolicy,
|
||||||
rawReverseMappingMethod.getParameterName(),
|
mappedTargetProperties
|
||||||
Introspector.decapitalize( rawReverseMappingMethod.getTargetType().getName() ),
|
|
||||||
property.getTargetReadAccessorName(),
|
|
||||||
property.getTargetType(),
|
|
||||||
property.getSourceWriteAccessorName(),
|
|
||||||
property.getSourceType(),
|
|
||||||
reversePropertyMappingMethod != null ? new MappingMethodReference(
|
|
||||||
reversePropertyMappingMethod.getDeclaringMapper(),
|
|
||||||
reversePropertyMappingMethod.getName(),
|
|
||||||
reversePropertyMappingMethod.getParameterName(),
|
|
||||||
property.getTargetType(),
|
|
||||||
property.getSourceType()
|
|
||||||
) : null,
|
|
||||||
conversion != null && rawReverseMappingMethod != null ? conversion.from(
|
|
||||||
rawReverseMappingMethod.getParameterName() + "." +
|
|
||||||
property.getTargetReadAccessorName() +
|
|
||||||
"()",
|
|
||||||
property.getSourceType()
|
|
||||||
) : null
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MappingMethod mappingMethod = new SimpleMappingMethod(
|
return new SimpleMappingMethod(
|
||||||
method.getName(),
|
method.getName(),
|
||||||
method.getParameterName(),
|
method.getParameterName(),
|
||||||
method.getSourceType(),
|
method.getSourceType(),
|
||||||
method.getTargetType(),
|
method.getTargetType(),
|
||||||
propertyMappings
|
propertyMappings
|
||||||
);
|
);
|
||||||
|
|
||||||
reportErrorForUnmappedTargetPropertiesIfRequired(
|
|
||||||
method.getExecutable(),
|
|
||||||
unmappedTargetPolicy,
|
|
||||||
method.getTargetProeprties(),
|
|
||||||
mappedTargetProperties
|
|
||||||
);
|
|
||||||
|
|
||||||
MappingMethod reverseMappingMethod = null;
|
|
||||||
if ( rawReverseMappingMethod != null ) {
|
|
||||||
reverseMappingMethod = new SimpleMappingMethod(
|
|
||||||
rawReverseMappingMethod.getName(),
|
|
||||||
rawReverseMappingMethod.getParameterName(),
|
|
||||||
method.getTargetType(),
|
|
||||||
method.getSourceType(),
|
|
||||||
reversePropertyMappings
|
|
||||||
);
|
|
||||||
|
|
||||||
reportErrorForUnmappedTargetPropertiesIfRequired(
|
|
||||||
rawReverseMappingMethod.getExecutable(),
|
|
||||||
unmappedTargetPolicy,
|
|
||||||
method.getSourceProperties(),
|
|
||||||
mappedSourceProperties
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BeanMapping( mappingMethod, reverseMappingMethod );
|
private MappingMethod getIterableMappingMethod(List<Method> methods, Method method) {
|
||||||
}
|
|
||||||
|
|
||||||
private BeanMapping getIterableBeanMapping(List<Method> methods, Method method, Method rawReverseMappingMethod) {
|
|
||||||
String toConversionString = getIterableConversionString(
|
String toConversionString = getIterableConversionString(
|
||||||
conversions,
|
conversions,
|
||||||
method.getSourceType().getElementType(),
|
method.getSourceType().getElementType(),
|
||||||
@ -335,59 +286,41 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
String fromConversionString = getIterableConversionString(
|
return new IterableMappingMethod(
|
||||||
conversions,
|
|
||||||
method.getTargetType().getElementType(),
|
|
||||||
method.getSourceType().getElementType(),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
MappingMethod mappingMethod = new IterableMappingMethod(
|
|
||||||
method.getName(),
|
method.getName(),
|
||||||
method.getParameterName(),
|
method.getParameterName(),
|
||||||
method.getSourceType(),
|
method.getSourceType(),
|
||||||
method.getTargetType(),
|
method.getTargetType(),
|
||||||
getElementMappingMethod( methods, method ),
|
getMappingMethodReference(
|
||||||
|
methods,
|
||||||
|
method.getSourceType().getElementType(),
|
||||||
|
method.getTargetType().getElementType()
|
||||||
|
),
|
||||||
toConversionString
|
toConversionString
|
||||||
);
|
);
|
||||||
|
|
||||||
MappingMethod reverseMappingMethod = null;
|
|
||||||
|
|
||||||
if ( rawReverseMappingMethod != null ) {
|
|
||||||
reverseMappingMethod = new IterableMappingMethod(
|
|
||||||
rawReverseMappingMethod.getName(),
|
|
||||||
rawReverseMappingMethod.getParameterName(),
|
|
||||||
method.getTargetType(),
|
|
||||||
method.getSourceType(),
|
|
||||||
getElementMappingMethod( methods, rawReverseMappingMethod ),
|
|
||||||
fromConversionString
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BeanMapping( mappingMethod, reverseMappingMethod );
|
private void reportErrorForUnmappedTargetPropertiesIfRequired(Method method,
|
||||||
}
|
|
||||||
|
|
||||||
private void reportErrorForUnmappedTargetPropertiesIfRequired(ExecutableElement method,
|
|
||||||
ReportingPolicy unmappedTargetPolicy,
|
ReportingPolicy unmappedTargetPolicy,
|
||||||
Set<String> targetProperties,
|
|
||||||
Set<String> mappedTargetProperties) {
|
Set<String> mappedTargetProperties) {
|
||||||
|
|
||||||
if ( targetProperties.size() > mappedTargetProperties.size() && unmappedTargetPolicy.requiresReport() ) {
|
if ( method.getTargetProeprties().size() > mappedTargetProperties.size() &&
|
||||||
targetProperties.removeAll( mappedTargetProperties );
|
unmappedTargetPolicy.requiresReport() ) {
|
||||||
|
method.getTargetProeprties().removeAll( mappedTargetProperties );
|
||||||
printMessage(
|
printMessage(
|
||||||
unmappedTargetPolicy,
|
unmappedTargetPolicy,
|
||||||
MessageFormat.format(
|
MessageFormat.format(
|
||||||
"Unmapped target {0,choice,1#property|1<properties}: \"{1}\"",
|
"Unmapped target {0,choice,1#property|1<properties}: \"{1}\"",
|
||||||
targetProperties.size(),
|
method.getTargetProeprties().size(),
|
||||||
Strings.join( targetProperties, ", " )
|
Strings.join( method.getTargetProeprties(), ", " )
|
||||||
),
|
),
|
||||||
method
|
method.getExecutable()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportErrorIfPropertyCanNotBeMapped(Method method, Method reverseMethod, MappedProperty property,
|
private void reportErrorIfPropertyCanNotBeMapped(Method method, MappedProperty property,
|
||||||
Method propertyMappingMethod, Method reversePropertyMappingMethod,
|
MappingMethodReference propertyMappingMethod,
|
||||||
Conversion conversion) {
|
Conversion conversion) {
|
||||||
if ( property.getSourceType().equals( property.getTargetType() ) ) {
|
if ( property.getSourceType().equals( property.getTargetType() ) ) {
|
||||||
return;
|
return;
|
||||||
@ -412,29 +345,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
method.getExecutable()
|
method.getExecutable()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( reverseMethod == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !(
|
|
||||||
reversePropertyMappingMethod != null ||
|
|
||||||
conversion != null ||
|
|
||||||
( property.getSourceType().isCollectionType() && property.getSourceType()
|
|
||||||
.getCollectionImplementationType() != null ) ) ) {
|
|
||||||
|
|
||||||
printMessage(
|
|
||||||
ReportingPolicy.ERROR,
|
|
||||||
String.format(
|
|
||||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
|
||||||
property.getTargetType(),
|
|
||||||
property.getTargetName(),
|
|
||||||
property.getSourceType(),
|
|
||||||
property.getSourceName()
|
|
||||||
),
|
|
||||||
reverseMethod.getExecutable()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getIterableConversionString(Conversions conversions, Type sourceElementType, Type targetElementType,
|
private String getIterableConversionString(Conversions conversions, Type sourceElementType, Type targetElementType,
|
||||||
@ -460,45 +370,24 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
return usedMapperTypes;
|
return usedMapperTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MappingMethodReference getElementMappingMethod(Iterable<Method> methods, Method method) {
|
private MappingMethodReference getMappingMethodReference(Iterable<Method> methods, Type parameterType,
|
||||||
Method elementMappingMethod = null;
|
Type returnType) {
|
||||||
for ( Method oneMethod : methods ) {
|
for ( Method oneMethod : methods ) {
|
||||||
if ( oneMethod.getSourceType().equals( method.getSourceType().getElementType() ) ) {
|
if ( oneMethod.getSourceType().equals( parameterType ) && oneMethod.getTargetType().equals( returnType ) ) {
|
||||||
elementMappingMethod = oneMethod;
|
return new MappingMethodReference(
|
||||||
break;
|
oneMethod.getDeclaringMapper(),
|
||||||
}
|
oneMethod.getName(),
|
||||||
}
|
oneMethod.getParameterName(),
|
||||||
return elementMappingMethod == null ? null : new MappingMethodReference(
|
oneMethod.getSourceType(),
|
||||||
elementMappingMethod.getDeclaringMapper(),
|
oneMethod.getTargetType()
|
||||||
elementMappingMethod.getName(),
|
|
||||||
elementMappingMethod.getParameterName(),
|
|
||||||
elementMappingMethod.getSourceType(),
|
|
||||||
elementMappingMethod.getTargetType()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Method getPropertyMappingMethod(Iterable<Method> rawMethods, MappedProperty property) {
|
|
||||||
for ( Method oneMethod : rawMethods ) {
|
|
||||||
if ( oneMethod.getSourceType().equals( property.getSourceType() ) && oneMethod.getTargetType()
|
|
||||||
.equals( property.getTargetType() ) ) {
|
|
||||||
return oneMethod;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Method getReversePropertyMappingMethod(Iterable<Method> methods, MappedProperty property) {
|
private Method getReverseMappingMethod(List<Method> rawMethods, Method method) {
|
||||||
for ( Method method : methods ) {
|
|
||||||
if ( method.getSourceType().equals( property.getTargetType() ) && method.getTargetType()
|
|
||||||
.equals( property.getSourceType() ) ) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Method getReverseMappingMethod(List<Method> rawMethods,
|
|
||||||
Method method) {
|
|
||||||
for ( Method oneMethod : rawMethods ) {
|
for ( Method oneMethod : rawMethods ) {
|
||||||
if ( oneMethod.reverses( method ) ) {
|
if ( oneMethod.reverses( method ) ) {
|
||||||
return oneMethod;
|
return oneMethod;
|
||||||
@ -588,7 +477,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
returnType,
|
returnType,
|
||||||
sourceProperties,
|
sourceProperties,
|
||||||
targetProperties,
|
targetProperties,
|
||||||
retrieveMappedProperties( method, sourceProperties, targetProperties )
|
getMappings( method )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -627,18 +516,19 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
* method.
|
* method.
|
||||||
*
|
*
|
||||||
* @param method The method of interest
|
* @param method The method of interest
|
||||||
* @param targetProperties
|
|
||||||
* @param sourceProperties
|
|
||||||
*
|
*
|
||||||
* @return All mapped properties for the given method
|
* @return All mapped properties for the given method
|
||||||
*/
|
*/
|
||||||
private List<MappedProperty> retrieveMappedProperties(ExecutableElement method, Set<String> sourceProperties,
|
private List<MappedProperty> retrieveMappedProperties(Method method) {
|
||||||
Set<String> targetProperties) {
|
Map<String, Mapping> mappings = method.getMappings();
|
||||||
|
|
||||||
Map<String, Mapping> mappings = getMappings( method );
|
TypeElement returnTypeElement = (TypeElement) typeUtils.asElement( method.getExecutable().getReturnType() );
|
||||||
|
TypeElement parameterElement = (TypeElement) typeUtils.asElement(
|
||||||
TypeElement returnTypeElement = (TypeElement) typeUtils.asElement( method.getReturnType() );
|
method.getExecutable()
|
||||||
TypeElement parameterElement = (TypeElement) typeUtils.asElement( method.getParameters().get( 0 ).asType() );
|
.getParameters()
|
||||||
|
.get( 0 )
|
||||||
|
.asType()
|
||||||
|
);
|
||||||
|
|
||||||
List<MappedProperty> properties = new ArrayList<MappedProperty>();
|
List<MappedProperty> properties = new ArrayList<MappedProperty>();
|
||||||
|
|
||||||
@ -648,14 +538,8 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
List<ExecutableElement> targetSetters = Filters.setterMethodsIn(
|
List<ExecutableElement> targetSetters = Filters.setterMethodsIn(
|
||||||
elementUtils.getAllMembers( returnTypeElement )
|
elementUtils.getAllMembers( returnTypeElement )
|
||||||
);
|
);
|
||||||
List<ExecutableElement> sourceSetters = Filters.setterMethodsIn(
|
|
||||||
elementUtils.getAllMembers( parameterElement )
|
|
||||||
);
|
|
||||||
List<ExecutableElement> targetGetters = Filters.getterMethodsIn(
|
|
||||||
elementUtils.getAllMembers( returnTypeElement )
|
|
||||||
);
|
|
||||||
|
|
||||||
reportErrorIfMappedPropertiesDontExist( method, sourceProperties, targetProperties, mappings );
|
reportErrorIfMappedPropertiesDontExist( method );
|
||||||
|
|
||||||
for ( ExecutableElement getterMethod : sourceGetters ) {
|
for ( ExecutableElement getterMethod : sourceGetters ) {
|
||||||
String sourcePropertyName = Executables.getPropertyName( getterMethod );
|
String sourcePropertyName = Executables.getPropertyName( getterMethod );
|
||||||
@ -665,22 +549,12 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
String targetPropertyName = Executables.getPropertyName( setterMethod );
|
String targetPropertyName = Executables.getPropertyName( setterMethod );
|
||||||
|
|
||||||
if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
|
if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
|
||||||
ExecutableElement correspondingSetter = Executables.getCorrespondingPropertyAccessor(
|
|
||||||
getterMethod,
|
|
||||||
sourceSetters
|
|
||||||
);
|
|
||||||
ExecutableElement correspondingGetter = Executables.getCorrespondingPropertyAccessor(
|
|
||||||
setterMethod,
|
|
||||||
targetGetters
|
|
||||||
);
|
|
||||||
properties.add(
|
properties.add(
|
||||||
new MappedProperty(
|
new MappedProperty(
|
||||||
sourcePropertyName,
|
sourcePropertyName,
|
||||||
getterMethod.getSimpleName().toString(),
|
getterMethod.getSimpleName().toString(),
|
||||||
correspondingSetter != null ? correspondingSetter.getSimpleName().toString() : null,
|
|
||||||
retrieveReturnType( getterMethod ),
|
retrieveReturnType( getterMethod ),
|
||||||
mapping != null ? mapping.getTargetName() : targetPropertyName,
|
mapping != null ? mapping.getTargetName() : targetPropertyName,
|
||||||
correspondingGetter != null ? correspondingGetter.getSimpleName().toString() : null,
|
|
||||||
setterMethod.getSimpleName().toString(),
|
setterMethod.getSimpleName().toString(),
|
||||||
retrieveParameter( setterMethod ).getType()
|
retrieveParameter( setterMethod ).getType()
|
||||||
)
|
)
|
||||||
@ -692,29 +566,26 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportErrorIfMappedPropertiesDontExist(ExecutableElement method, Set<String> sourcePropertyNames,
|
private void reportErrorIfMappedPropertiesDontExist(Method method) {
|
||||||
Set<String> targetPropertyNames,
|
for ( Mapping mappedProperty : method.getMappings().values() ) {
|
||||||
Map<String, Mapping> mappings) {
|
if ( !method.getSourceProperties().contains( mappedProperty.getSourceName() ) ) {
|
||||||
|
|
||||||
for ( Mapping mappedProperty : mappings.values() ) {
|
|
||||||
if ( !sourcePropertyNames.contains( mappedProperty.getSourceName() ) ) {
|
|
||||||
printMessage(
|
printMessage(
|
||||||
ReportingPolicy.ERROR,
|
ReportingPolicy.ERROR,
|
||||||
String.format(
|
String.format(
|
||||||
"Unknown property \"%s\" in parameter type %s.",
|
"Unknown property \"%s\" in parameter type %s.",
|
||||||
mappedProperty.getSourceName(),
|
mappedProperty.getSourceName(),
|
||||||
retrieveParameter( method ).getType()
|
method.getSourceType()
|
||||||
), method, mappedProperty.getMirror(), mappedProperty.getSourceAnnotationValue()
|
), method.getExecutable(), mappedProperty.getMirror(), mappedProperty.getSourceAnnotationValue()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( !targetPropertyNames.contains( mappedProperty.getTargetName() ) ) {
|
if ( !method.getTargetProeprties().contains( mappedProperty.getTargetName() ) ) {
|
||||||
printMessage(
|
printMessage(
|
||||||
ReportingPolicy.ERROR,
|
ReportingPolicy.ERROR,
|
||||||
String.format(
|
String.format(
|
||||||
"Unknown property \"%s\" in return type %s.",
|
"Unknown property \"%s\" in return type %s.",
|
||||||
mappedProperty.getTargetName(),
|
mappedProperty.getTargetName(),
|
||||||
retrieveReturnType( method )
|
method.getTargetType()
|
||||||
), method, mappedProperty.getMirror(), mappedProperty.getTargetAnnotationValue()
|
), method.getExecutable(), mappedProperty.getMirror(), mappedProperty.getTargetAnnotationValue()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2012-2013 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.model;
|
|
||||||
|
|
||||||
public class BeanMapping extends AbstractModelElement {
|
|
||||||
|
|
||||||
private final MappingMethod mappingMethod;
|
|
||||||
private final MappingMethod reverseMappingMethod;
|
|
||||||
|
|
||||||
public BeanMapping(MappingMethod mappingMethod, MappingMethod reverseMappingMethod) {
|
|
||||||
this.mappingMethod = mappingMethod;
|
|
||||||
this.reverseMappingMethod = reverseMappingMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappingMethod getMappingMethod() {
|
|
||||||
return mappingMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappingMethod getReverseMappingMethod() {
|
|
||||||
return reverseMappingMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder( "BeanMapping {" );
|
|
||||||
sb.append( "\n mappingMethod=" + mappingMethod.toString().replaceAll( "\n", "\n " ) + ',' );
|
|
||||||
sb.append( "\n reverseMappingMethod=" + reverseMappingMethod + ',' );
|
|
||||||
sb.append( "\n}" );
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -29,18 +29,18 @@ public class Mapper extends AbstractModelElement {
|
|||||||
private final String packageName;
|
private final String packageName;
|
||||||
private final String interfaceName;
|
private final String interfaceName;
|
||||||
private final String implementationName;
|
private final String implementationName;
|
||||||
private final List<BeanMapping> beanMappings;
|
private final List<MappingMethod> mappingMethods;
|
||||||
private final List<Type> usedMapperTypes;
|
private final List<Type> usedMapperTypes;
|
||||||
private final Options options;
|
private final Options options;
|
||||||
private final SortedSet<Type> importedTypes;
|
private final SortedSet<Type> importedTypes;
|
||||||
|
|
||||||
public Mapper(String packageName, String interfaceName,
|
public Mapper(String packageName, String interfaceName,
|
||||||
String implementationName, List<BeanMapping> beanMappings, List<Type> usedMapperTypes,
|
String implementationName, List<MappingMethod> mappingMethods, List<Type> usedMapperTypes,
|
||||||
Options options) {
|
Options options) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.interfaceName = interfaceName;
|
this.interfaceName = interfaceName;
|
||||||
this.implementationName = implementationName;
|
this.implementationName = implementationName;
|
||||||
this.beanMappings = beanMappings;
|
this.mappingMethods = mappingMethods;
|
||||||
this.usedMapperTypes = usedMapperTypes;
|
this.usedMapperTypes = usedMapperTypes;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.importedTypes = determineImportedTypes();
|
this.importedTypes = determineImportedTypes();
|
||||||
@ -50,9 +50,9 @@ public class Mapper extends AbstractModelElement {
|
|||||||
SortedSet<Type> importedTypes = new TreeSet<Type>();
|
SortedSet<Type> importedTypes = new TreeSet<Type>();
|
||||||
importedTypes.add( Type.forClass( Generated.class ) );
|
importedTypes.add( Type.forClass( Generated.class ) );
|
||||||
|
|
||||||
for ( BeanMapping beanMapping : beanMappings ) {
|
for ( MappingMethod mappingMethod : mappingMethods ) {
|
||||||
|
|
||||||
for ( Type type : beanMapping.getMappingMethod().getReferencedTypes() ) {
|
for ( Type type : mappingMethod.getReferencedTypes() ) {
|
||||||
addWithDependents( importedTypes, type );
|
addWithDependents( importedTypes, type );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ public class Mapper extends AbstractModelElement {
|
|||||||
sb.append( "\n implementationName='" + implementationName + "\'," );
|
sb.append( "\n implementationName='" + implementationName + "\'," );
|
||||||
sb.append( "\n beanMappings=[" );
|
sb.append( "\n beanMappings=[" );
|
||||||
|
|
||||||
for ( BeanMapping beanMapping : beanMappings ) {
|
for ( MappingMethod beanMapping : mappingMethods ) {
|
||||||
sb.append( "\n " + beanMapping.toString().replaceAll( "\n", "\n " ) );
|
sb.append( "\n " + beanMapping.toString().replaceAll( "\n", "\n " ) );
|
||||||
}
|
}
|
||||||
sb.append( "\n ]" );
|
sb.append( "\n ]" );
|
||||||
@ -107,8 +107,8 @@ public class Mapper extends AbstractModelElement {
|
|||||||
return implementationName;
|
return implementationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BeanMapping> getBeanMappings() {
|
public List<MappingMethod> getMappingMethods() {
|
||||||
return beanMappings;
|
return mappingMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Type> getUsedMapperTypes() {
|
public List<Type> getUsedMapperTypes() {
|
||||||
|
@ -30,23 +30,17 @@ public class MappedProperty {
|
|||||||
|
|
||||||
private final String sourceName;
|
private final String sourceName;
|
||||||
private final String sourceReadAccessorName;
|
private final String sourceReadAccessorName;
|
||||||
private final String sourceWriteAccessorName;
|
|
||||||
private final Type sourceType;
|
private final Type sourceType;
|
||||||
private final String targetName;
|
private final String targetName;
|
||||||
private final String targetReadAccessorName;
|
|
||||||
private final String targetWriteAccessorName;
|
private final String targetWriteAccessorName;
|
||||||
private final Type targetType;
|
private final Type targetType;
|
||||||
|
|
||||||
public MappedProperty(String sourceName, String sourceReadAccessorName, String sourceWriteAccessorName,
|
public MappedProperty(String sourceName, String sourceReadAccessorName, Type sourceType, String targetName,
|
||||||
Type sourceType, String targetName, String targetReadAccessorName,
|
String targetWriteAccessorName, Type targetType) {
|
||||||
String targetWriteAccessorName,
|
|
||||||
Type targetType) {
|
|
||||||
this.sourceName = sourceName;
|
this.sourceName = sourceName;
|
||||||
this.sourceReadAccessorName = sourceReadAccessorName;
|
this.sourceReadAccessorName = sourceReadAccessorName;
|
||||||
this.sourceWriteAccessorName = sourceWriteAccessorName;
|
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
this.targetName = targetName;
|
this.targetName = targetName;
|
||||||
this.targetReadAccessorName = targetReadAccessorName;
|
|
||||||
this.targetWriteAccessorName = targetWriteAccessorName;
|
this.targetWriteAccessorName = targetWriteAccessorName;
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
}
|
}
|
||||||
@ -59,10 +53,6 @@ public class MappedProperty {
|
|||||||
return sourceReadAccessorName;
|
return sourceReadAccessorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSourceWriteAccessorName() {
|
|
||||||
return sourceWriteAccessorName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type getSourceType() {
|
public Type getSourceType() {
|
||||||
return sourceType;
|
return sourceType;
|
||||||
}
|
}
|
||||||
@ -71,10 +61,6 @@ public class MappedProperty {
|
|||||||
return targetName;
|
return targetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTargetReadAccessorName() {
|
|
||||||
return targetReadAccessorName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTargetWriteAccessorName() {
|
public String getTargetWriteAccessorName() {
|
||||||
return targetWriteAccessorName;
|
return targetWriteAccessorName;
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,10 @@ public class Mapping {
|
|||||||
return targetAnnotationValue;
|
return targetAnnotationValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Mapping reverse() {
|
||||||
|
return new Mapping( targetName, sourceName, mirror, sourceAnnotationValue, targetAnnotationValue );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Mapping {" +
|
return "Mapping {" +
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
package org.mapstruct.ap.model.source;
|
package org.mapstruct.ap.model.source;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
|
||||||
@ -38,15 +38,15 @@ public class Method {
|
|||||||
private final String parameterName;
|
private final String parameterName;
|
||||||
private final Type sourceType;
|
private final Type sourceType;
|
||||||
private final Type targetType;
|
private final Type targetType;
|
||||||
private Set<String> sourceProperties;
|
private final Set<String> sourceProperties;
|
||||||
private Set<String> targetProeprties;
|
private final Set<String> targetProeprties;
|
||||||
private final List<MappedProperty> mappedProperties;
|
private Map<String, Mapping> mappings;
|
||||||
|
|
||||||
public static Method forMethodRequiringImplementation(ExecutableElement executable, String parameterName,
|
public static Method forMethodRequiringImplementation(ExecutableElement executable, String parameterName,
|
||||||
Type sourceType,
|
Type sourceType,
|
||||||
Type targetType, Set<String> sourceProperties,
|
Type targetType, Set<String> sourceProperties,
|
||||||
Set<String> targetProperties,
|
Set<String> targetProperties,
|
||||||
List<MappedProperty> mappedProperties) {
|
Map<String, Mapping> mappings) {
|
||||||
|
|
||||||
return new Method(
|
return new Method(
|
||||||
null,
|
null,
|
||||||
@ -56,13 +56,12 @@ public class Method {
|
|||||||
targetType,
|
targetType,
|
||||||
sourceProperties,
|
sourceProperties,
|
||||||
targetProperties,
|
targetProperties,
|
||||||
mappedProperties
|
mappings
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Method forReferencedMethod(Type declaringMapper, ExecutableElement executable, String parameterName,
|
public static Method forReferencedMethod(Type declaringMapper, ExecutableElement executable, String parameterName,
|
||||||
Type sourceType,
|
Type sourceType, Type targetType) {
|
||||||
Type targetType) {
|
|
||||||
|
|
||||||
return new Method(
|
return new Method(
|
||||||
declaringMapper,
|
declaringMapper,
|
||||||
@ -72,13 +71,13 @@ public class Method {
|
|||||||
targetType,
|
targetType,
|
||||||
Collections.<String>emptySet(),
|
Collections.<String>emptySet(),
|
||||||
Collections.<String>emptySet(),
|
Collections.<String>emptySet(),
|
||||||
Collections.<MappedProperty>emptyList()
|
Collections.<String, Mapping>emptyMap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Method(Type declaringMapper, ExecutableElement executable, String parameterName, Type sourceType,
|
private Method(Type declaringMapper, ExecutableElement executable, String parameterName, Type sourceType,
|
||||||
Type targetType, Set<String> sourceProperties, Set<String> targetProperties,
|
Type targetType, Set<String> sourceProperties, Set<String> targetProperties,
|
||||||
List<MappedProperty> mappedProperties) {
|
Map<String, Mapping> mappings) {
|
||||||
this.declaringMapper = declaringMapper;
|
this.declaringMapper = declaringMapper;
|
||||||
this.executable = executable;
|
this.executable = executable;
|
||||||
this.parameterName = parameterName;
|
this.parameterName = parameterName;
|
||||||
@ -86,7 +85,7 @@ public class Method {
|
|||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
this.sourceProperties = sourceProperties;
|
this.sourceProperties = sourceProperties;
|
||||||
this.targetProeprties = targetProperties;
|
this.targetProeprties = targetProperties;
|
||||||
this.mappedProperties = mappedProperties;
|
this.mappings = mappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,8 +127,12 @@ public class Method {
|
|||||||
return targetProeprties;
|
return targetProeprties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MappedProperty> getMappedProperties() {
|
public Map<String, Mapping> getMappings() {
|
||||||
return mappedProperties;
|
return mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappings(Map<String, Mapping> mappings) {
|
||||||
|
this.mappings = mappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reverses(Method method) {
|
public boolean reverses(Method method) {
|
||||||
@ -138,6 +141,10 @@ public class Method {
|
|||||||
equals( targetType, method.getSourceType() );
|
equals( targetType, method.getSourceType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isIterableMapping() {
|
||||||
|
return sourceType.isIterableType() && targetType.isIterableType();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean equals(Object o1, Object o2) {
|
private boolean equals(Object o1, Object o2) {
|
||||||
return ( o1 == null && o2 == null ) || ( o1 != null ) && o1.equals( o2 );
|
return ( o1 == null && o2 == null ) || ( o1 != null ) && o1.equals( o2 );
|
||||||
}
|
}
|
||||||
|
@ -88,30 +88,6 @@ public class Executables {
|
|||||||
throw new IllegalArgumentException( "Executable " + getterOrSetterMethod + " is not getter or setter method." );
|
throw new IllegalArgumentException( "Executable " + getterOrSetterMethod + " is not getter or setter method." );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns that setter or getter from the given list of executables which
|
|
||||||
* corresponds to the given getter or setter method.
|
|
||||||
*
|
|
||||||
* @param getterOrSetter The getter or setter method of interest.
|
|
||||||
* @param elements A list of executables to retrieve the corresponding accessor
|
|
||||||
* from.
|
|
||||||
*
|
|
||||||
* @return The setter corresponding to the given getter or the getter
|
|
||||||
* corresponding to the given getter
|
|
||||||
*/
|
|
||||||
public static ExecutableElement getCorrespondingPropertyAccessor(ExecutableElement getterOrSetter,
|
|
||||||
List<ExecutableElement> elements) {
|
|
||||||
String propertyName = getPropertyName( getterOrSetter );
|
|
||||||
|
|
||||||
for ( ExecutableElement method : elements ) {
|
|
||||||
if ( getPropertyName( method ).equals( propertyName ) ) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<String> getPropertyNames(List<ExecutableElement> propertyAccessors) {
|
public static Set<String> getPropertyNames(List<ExecutableElement> propertyAccessors) {
|
||||||
Set<String> propertyNames = new HashSet<String>();
|
Set<String> propertyNames = new HashSet<String>();
|
||||||
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
<#--
|
|
||||||
|
|
||||||
Copyright 2012-2013 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.
|
|
||||||
|
|
||||||
-->
|
|
||||||
<@includeModel object=mappingMethod/>
|
|
||||||
|
|
||||||
<#if reverseMappingMethod??>
|
|
||||||
<@includeModel object=reverseMappingMethod/>
|
|
||||||
</#if>
|
|
@ -34,7 +34,7 @@ public class ${implementationName} implements ${interfaceName} {
|
|||||||
private final ${mapperType.name} ${mapperType.name?uncap_first} = new ${mapperType.name}();
|
private final ${mapperType.name} ${mapperType.name?uncap_first} = new ${mapperType.name}();
|
||||||
</#list>
|
</#list>
|
||||||
|
|
||||||
<#list beanMappings as beanMapping>
|
<#list mappingMethods as mappingMethod>
|
||||||
<@includeModel object=beanMapping/>
|
<@includeModel object=mappingMethod/>
|
||||||
</#list>
|
</#list>
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user