#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.SimpleMappingMethod;
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.Method;
import org.mapstruct.ap.model.source.Parameter;
@ -224,43 +223,45 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
Set<String> mappedTargetProperties = new HashSet<String>();
List<MappedProperty> mappedProperties = retrieveMappedProperties( method );
Map<String, Mapping> mappings = method.getMappings();
for ( MappedProperty property : mappedProperties ) {
mappedTargetProperties.add( property.getTargetName() );
TypeElement returnTypeElement = (TypeElement) typeUtils.asElement( method.getExecutable().getReturnType() );
TypeElement parameterElement = (TypeElement) typeUtils.asElement(
method.getExecutable()
.getParameters()
.get( 0 )
.asType()
);
MappingMethodReference propertyMappingMethod = getMappingMethodReference(
methods,
property.getSourceType(),
property.getTargetType()
);
Conversion conversion = conversions.getConversion(
property.getSourceType(),
property.getTargetType()
);
List<ExecutableElement> sourceGetters = Filters.getterMethodsIn(
elementUtils.getAllMembers( parameterElement )
);
List<ExecutableElement> targetSetters = Filters.setterMethodsIn(
elementUtils.getAllMembers( returnTypeElement )
);
reportErrorIfPropertyCanNotBeMapped(
method,
property,
propertyMappingMethod,
conversion
);
reportErrorIfMappedPropertiesDontExist( method );
propertyMappings.add(
new PropertyMapping(
method.getParameterName(),
Introspector.decapitalize( method.getTargetType().getName() ),
property.getSourceReadAccessorName(),
property.getSourceType(),
property.getTargetWriteAccessorName(),
property.getTargetType(),
propertyMappingMethod,
conversion != null ? conversion.to(
method.getParameterName() + "." + property.getSourceReadAccessorName() + "()",
property.getTargetType()
) : null
)
);
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 ) ) {
PropertyMapping property = getPropertyMapping(
methods,
method,
getterMethod,
setterMethod
);
propertyMappings.add( property );
mappedTargetProperties.add( targetPropertyName );
}
}
}
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) {
String toConversionString = getIterableConversionString(
conversions,
@ -319,17 +355,15 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
}
}
private void reportErrorIfPropertyCanNotBeMapped(Method method, MappedProperty property,
MappingMethodReference propertyMappingMethod,
Conversion conversion) {
private void reportErrorIfPropertyCanNotBeMapped(Method method, PropertyMapping property) {
if ( property.getSourceType().equals( property.getTargetType() ) ) {
return;
}
//no mapping method nor conversion nor collection with default implementation
if ( !(
propertyMappingMethod != null ||
conversion != null ||
property.getMappingMethod() != null ||
property.getConversion() != null ||
( property.getTargetType().isCollectionType() && property.getTargetType()
.getCollectionImplementationType() != null ) ) ) {
@ -510,62 +544,6 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
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) {
for ( Mapping mappedProperty : method.getMappings().values() ) {
if ( !method.getSourceProperties().contains( mappedProperty.getSourceName() ) ) {

View File

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