#32 Removing MappedProperty, creating PropertyMappings directly

This commit is contained in:
Gunnar Morling 2013-06-23 10:11:45 +02:00
parent cd0306683f
commit cadc20f7b3
3 changed files with 93 additions and 174 deletions

View File

@ -54,7 +54,6 @@ import org.mapstruct.ap.model.PropertyMapping;
import org.mapstruct.ap.model.ReportingPolicy; import org.mapstruct.ap.model.ReportingPolicy;
import org.mapstruct.ap.model.SimpleMappingMethod; import org.mapstruct.ap.model.SimpleMappingMethod;
import org.mapstruct.ap.model.Type; import org.mapstruct.ap.model.Type;
import org.mapstruct.ap.model.source.MappedProperty;
import org.mapstruct.ap.model.source.Mapping; import org.mapstruct.ap.model.source.Mapping;
import org.mapstruct.ap.model.source.Method; import org.mapstruct.ap.model.source.Method;
import org.mapstruct.ap.model.source.Parameter; import org.mapstruct.ap.model.source.Parameter;
@ -224,43 +223,45 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>(); List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
Set<String> mappedTargetProperties = new HashSet<String>(); Set<String> mappedTargetProperties = new HashSet<String>();
List<MappedProperty> mappedProperties = retrieveMappedProperties( method ); Map<String, Mapping> mappings = method.getMappings();
for ( MappedProperty property : mappedProperties ) { TypeElement returnTypeElement = (TypeElement) typeUtils.asElement( method.getExecutable().getReturnType() );
mappedTargetProperties.add( property.getTargetName() ); TypeElement parameterElement = (TypeElement) typeUtils.asElement(
method.getExecutable()
.getParameters()
.get( 0 )
.asType()
);
MappingMethodReference propertyMappingMethod = getMappingMethodReference( List<ExecutableElement> sourceGetters = Filters.getterMethodsIn(
methods, elementUtils.getAllMembers( parameterElement )
property.getSourceType(), );
property.getTargetType() List<ExecutableElement> targetSetters = Filters.setterMethodsIn(
); elementUtils.getAllMembers( returnTypeElement )
Conversion conversion = conversions.getConversion( );
property.getSourceType(),
property.getTargetType()
);
reportErrorIfPropertyCanNotBeMapped( reportErrorIfMappedPropertiesDontExist( method );
method,
property,
propertyMappingMethod,
conversion
);
propertyMappings.add( for ( ExecutableElement getterMethod : sourceGetters ) {
new PropertyMapping( String sourcePropertyName = Executables.getPropertyName( getterMethod );
method.getParameterName(), Mapping mapping = mappings.get( sourcePropertyName );
Introspector.decapitalize( method.getTargetType().getName() ),
property.getSourceReadAccessorName(), for ( ExecutableElement setterMethod : targetSetters ) {
property.getSourceType(), String targetPropertyName = Executables.getPropertyName( setterMethod );
property.getTargetWriteAccessorName(),
property.getTargetType(), if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
propertyMappingMethod, PropertyMapping property = getPropertyMapping(
conversion != null ? conversion.to( methods,
method.getParameterName() + "." + property.getSourceReadAccessorName() + "()", method,
property.getTargetType() getterMethod,
) : null setterMethod
) );
);
propertyMappings.add( property );
mappedTargetProperties.add( targetPropertyName );
}
}
} }
reportErrorForUnmappedTargetPropertiesIfRequired( reportErrorForUnmappedTargetPropertiesIfRequired(
@ -278,6 +279,41 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
); );
} }
private PropertyMapping getPropertyMapping(List<Method> methods, Method method, ExecutableElement getterMethod,
ExecutableElement setterMethod) {
Type sourceType = retrieveReturnType( getterMethod );
Type targetType = retrieveParameter( setterMethod ).getType();
MappingMethodReference propertyMappingMethod = getMappingMethodReference( methods, sourceType, targetType );
Conversion conversion = conversions.getConversion(
sourceType,
targetType
);
PropertyMapping property = new PropertyMapping(
method.getParameterName(),
Introspector.decapitalize( method.getTargetType().getName() ),
Executables.getPropertyName( getterMethod ),
getterMethod.getSimpleName().toString(),
sourceType,
Executables.getPropertyName( setterMethod ),
setterMethod.getSimpleName().toString(),
targetType,
propertyMappingMethod,
conversion != null ? conversion.to(
method.getParameterName() + "." + getterMethod.getSimpleName().toString() + "()",
targetType
) : null
);
reportErrorIfPropertyCanNotBeMapped(
method,
property
);
return property;
}
private MappingMethod getIterableMappingMethod(List<Method> methods, Method method) { private MappingMethod getIterableMappingMethod(List<Method> methods, Method method) {
String toConversionString = getIterableConversionString( String toConversionString = getIterableConversionString(
conversions, conversions,
@ -319,17 +355,15 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
} }
} }
private void reportErrorIfPropertyCanNotBeMapped(Method method, MappedProperty property, private void reportErrorIfPropertyCanNotBeMapped(Method method, PropertyMapping property) {
MappingMethodReference propertyMappingMethod,
Conversion conversion) {
if ( property.getSourceType().equals( property.getTargetType() ) ) { if ( property.getSourceType().equals( property.getTargetType() ) ) {
return; return;
} }
//no mapping method nor conversion nor collection with default implementation //no mapping method nor conversion nor collection with default implementation
if ( !( if ( !(
propertyMappingMethod != null || property.getMappingMethod() != null ||
conversion != null || property.getConversion() != null ||
( property.getTargetType().isCollectionType() && property.getTargetType() ( property.getTargetType().isCollectionType() && property.getTargetType()
.getCollectionImplementationType() != null ) ) ) { .getCollectionImplementationType() != null ) ) ) {
@ -510,62 +544,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
return methods; return methods;
} }
/**
* Returns all properties of the parameter type of the given method which
* are mapped to a corresponding property of the return type of the given
* method.
*
* @param method The method of interest
*
* @return All mapped properties for the given method
*/
private List<MappedProperty> retrieveMappedProperties(Method method) {
Map<String, Mapping> mappings = method.getMappings();
TypeElement returnTypeElement = (TypeElement) typeUtils.asElement( method.getExecutable().getReturnType() );
TypeElement parameterElement = (TypeElement) typeUtils.asElement(
method.getExecutable()
.getParameters()
.get( 0 )
.asType()
);
List<MappedProperty> properties = new ArrayList<MappedProperty>();
List<ExecutableElement> sourceGetters = Filters.getterMethodsIn(
elementUtils.getAllMembers( parameterElement )
);
List<ExecutableElement> targetSetters = Filters.setterMethodsIn(
elementUtils.getAllMembers( returnTypeElement )
);
reportErrorIfMappedPropertiesDontExist( method );
for ( ExecutableElement getterMethod : sourceGetters ) {
String sourcePropertyName = Executables.getPropertyName( getterMethod );
Mapping mapping = mappings.get( sourcePropertyName );
for ( ExecutableElement setterMethod : targetSetters ) {
String targetPropertyName = Executables.getPropertyName( setterMethod );
if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
properties.add(
new MappedProperty(
sourcePropertyName,
getterMethod.getSimpleName().toString(),
retrieveReturnType( getterMethod ),
mapping != null ? mapping.getTargetName() : targetPropertyName,
setterMethod.getSimpleName().toString(),
retrieveParameter( setterMethod ).getType()
)
);
}
}
}
return properties;
}
private void reportErrorIfMappedPropertiesDontExist(Method method) { private void reportErrorIfMappedPropertiesDontExist(Method method) {
for ( Mapping mappedProperty : method.getMappings().values() ) { for ( Mapping mappedProperty : method.getMappings().values() ) {
if ( !method.getSourceProperties().contains( mappedProperty.getSourceName() ) ) { if ( !method.getSourceProperties().contains( mappedProperty.getSourceName() ) ) {

View File

@ -30,23 +30,32 @@ public class PropertyMapping extends AbstractModelElement {
private final String sourceBeanName; private final String sourceBeanName;
private final String targetBeanName; private final String targetBeanName;
private final String sourceName;
private final String sourceAccessorName; private final String sourceAccessorName;
private final Type sourceType; private final Type sourceType;
private final String targetName;
private final String targetAccessorName; private final String targetAccessorName;
private final Type targetType; private final Type targetType;
private final MappingMethodReference mappingMethod; private final MappingMethodReference mappingMethod;
private final String conversion; private final String conversion;
public PropertyMapping(String sourceBeanName, String targetBeanName, String sourceAccessorName, Type sourceType, public PropertyMapping(String sourceBeanName, String targetBeanName, String sourceName, String sourceAccessorName,
String targetAccessorName, Type targetType, MappingMethodReference mappingMethod, Type sourceType, String targetName, String targetAccessorName, Type targetType,
String conversion) { MappingMethodReference mappingMethod, String conversion) {
this.sourceBeanName = sourceBeanName; this.sourceBeanName = sourceBeanName;
this.targetBeanName = targetBeanName; this.targetBeanName = targetBeanName;
this.sourceName = sourceName;
this.sourceAccessorName = sourceAccessorName; this.sourceAccessorName = sourceAccessorName;
this.sourceType = sourceType; this.sourceType = sourceType;
this.targetName = targetName;
this.targetAccessorName = targetAccessorName; this.targetAccessorName = targetAccessorName;
this.targetType = targetType; this.targetType = targetType;
this.mappingMethod = mappingMethod; this.mappingMethod = mappingMethod;
this.conversion = conversion; this.conversion = conversion;
} }
@ -59,6 +68,10 @@ public class PropertyMapping extends AbstractModelElement {
return targetBeanName; return targetBeanName;
} }
public String getSourceName() {
return sourceName;
}
public String getSourceAccessorName() { public String getSourceAccessorName() {
return sourceAccessorName; return sourceAccessorName;
} }
@ -67,6 +80,10 @@ public class PropertyMapping extends AbstractModelElement {
return sourceType; return sourceType;
} }
public String getTargetName() {
return targetName;
}
public String getTargetAccessorName() { public String getTargetAccessorName() {
return targetAccessorName; return targetAccessorName;
} }

View File

@ -1,76 +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.source;
import org.mapstruct.ap.model.Type;
/**
* Represents a property mapped from source to target with the names of its
* accessor methods.
*
* @author Gunnar Morling
*/
public class MappedProperty {
private final String sourceName;
private final String sourceReadAccessorName;
private final Type sourceType;
private final String targetName;
private final String targetWriteAccessorName;
private final Type targetType;
public MappedProperty(String sourceName, String sourceReadAccessorName, Type sourceType, String targetName,
String targetWriteAccessorName, Type targetType) {
this.sourceName = sourceName;
this.sourceReadAccessorName = sourceReadAccessorName;
this.sourceType = sourceType;
this.targetName = targetName;
this.targetWriteAccessorName = targetWriteAccessorName;
this.targetType = targetType;
}
public String getSourceName() {
return sourceName;
}
public String getSourceReadAccessorName() {
return sourceReadAccessorName;
}
public Type getSourceType() {
return sourceType;
}
public String getTargetName() {
return targetName;
}
public String getTargetWriteAccessorName() {
return targetWriteAccessorName;
}
public Type getTargetType() {
return targetType;
}
@Override
public String toString() {
return sourceType + " " + sourceName + " <=> " + targetType + " " + targetName;
}
}