From 776bc3d1578d84924c3a517f354265c5a40e1fbf Mon Sep 17 00:00:00 2001
From: sjaakd
Date: Sat, 7 Feb 2015 20:03:01 +0100
Subject: [PATCH] #160 Refactoring into targetReadAccessor and
targetWriteAccessor and making them available to ftl templates
---
.../mapstruct/ap/model/BeanMappingMethod.java | 39 ++++--
.../mapstruct/ap/model/PropertyMapping.java | 126 +++++++++++-------
.../mapstruct/ap/model/TypeConversion.java | 6 +-
.../org/mapstruct/ap/model/common/Type.java | 31 +++--
.../mapstruct/ap/model/source/Mapping.java | 2 +-
.../ap/model/source/SourceReference.java | 12 +-
...pstruct.ap.model.IterableMappingMethod.ftl | 4 +-
...rg.mapstruct.ap.model.MapMappingMethod.ftl | 4 +-
...org.mapstruct.ap.model.MethodReference.ftl | 13 +-
...org.mapstruct.ap.model.PropertyMapping.ftl | 3 +-
.../org.mapstruct.ap.model.TypeConversion.ftl | 13 +-
...truct.ap.model.assignment.AdderWrapper.ftl | 10 +-
...t.ap.model.assignment.ArrayCopyWrapper.ftl | 12 +-
...ent.GetterWrapperForCollectionsAndMaps.ftl | 8 +-
...ct.ap.model.assignment.LocalVarWrapper.ftl | 15 ++-
...l.assignment.NewCollectionOrMapWrapper.ftl | 2 +-
...t.ap.model.assignment.NullCheckWrapper.ftl | 3 +-
...ruct.ap.model.assignment.SetterWrapper.ftl | 12 +-
...ent.SetterWrapperForCollectionsAndMaps.ftl | 12 +-
19 files changed, 215 insertions(+), 112 deletions(-)
diff --git a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java
index 6e2640fa2..d8f342e56 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java
@@ -90,7 +90,7 @@ public class BeanMappingMethod extends MappingMethod {
public Builder souceMethod(SourceMethod sourceMethod) {
this.method = sourceMethod;
CollectionMappingStrategyPrism cms = sourceMethod.getMapperConfiguration().getCollectionMappingStrategy();
- Map accessors = method.getResultType().getTargetAccessors( cms );
+ Map accessors = method.getResultType().getPropertyWriteAccessors( cms );
this.targetProperties = accessors.keySet();
this.unprocessedTargetProperties = new HashMap( accessors );
for ( Parameter sourceParameter : method.getSourceParameters() ) {
@@ -237,8 +237,8 @@ public class BeanMappingMethod extends MappingMethod {
PropertyMapping propertyMapping = null;
// fetch the target property
- ExecutableElement targetProperty = unprocessedTargetProperties.get( mapping.getTargetName() );
- if ( targetProperty == null ) {
+ ExecutableElement targetWriteAccessor = unprocessedTargetProperties.get( mapping.getTargetName() );
+ if ( targetWriteAccessor == null ) {
ctx.getMessager().printMessage(
method.getExecutable(),
mapping.getMirror(),
@@ -277,14 +277,15 @@ public class BeanMappingMethod extends MappingMethod {
SourceReference sourceRef = mapping.getSourceReference();
if ( sourceRef.isValid() ) {
- if ( targetProperty != null ) {
+ if ( targetWriteAccessor != null ) {
// targetProperty == null can occur: we arrived here because we want as many errors
// as possible before we stop analysing
propertyMapping = new PropertyMappingBuilder()
.mappingContext( ctx )
.souceMethod( method )
- .targetAccessor( targetProperty )
+ .targetWriteAccessor( targetWriteAccessor )
+ .targetReadAccessor( getTargetPropertyReadAccessor( mapping.getTargetName() ) )
.targetPropertyName( mapping.getTargetName() )
.sourceReference( sourceRef )
.qualifiers( mapping.getQualifiers() )
@@ -303,13 +304,14 @@ public class BeanMappingMethod extends MappingMethod {
}
// its a constant
- else if ( mapping.getConstant() != null && targetProperty != null ) {
+ else if ( mapping.getConstant() != null && targetWriteAccessor != null ) {
propertyMapping = new ConstantMappingBuilder()
.mappingContext( ctx )
.sourceMethod( method )
.constantExpression( "\"" + mapping.getConstant() + "\"" )
- .targetAccessor( targetProperty )
+ .targetWriteAccessor( targetWriteAccessor )
+ .targetReadAccessor( getTargetPropertyReadAccessor( mapping.getTargetName() ) )
.targetPropertyName( mapping.getTargetName() )
.dateFormat( mapping.getDateFormat() )
.qualifiers( mapping.getQualifiers() )
@@ -321,14 +323,15 @@ public class BeanMappingMethod extends MappingMethod {
}
// its an expression
- else if ( mapping.getJavaExpression() != null && targetProperty != null ) {
+ else if ( mapping.getJavaExpression() != null && targetWriteAccessor != null ) {
propertyMapping = new JavaExpressionMappingBuilder()
.mappingContext( ctx )
.souceMethod( method )
.javaExpression( mapping.getJavaExpression() )
- .targetAccessor( targetProperty )
.existingVariableNames( existingVariableNames )
+ .targetWriteAccessor( targetWriteAccessor )
+ .targetReadAccessor( targetWriteAccessor )
.targetPropertyName( mapping.getTargetName() )
.dependsOn( mapping.getDependsOn() )
.build();
@@ -378,11 +381,13 @@ public class BeanMappingMethod extends MappingMethod {
continue;
}
- for ( ExecutableElement sourceAccessor : sourceParameter.getType().getGetters() ) {
- String sourcePropertyName = Executables.getPropertyName( sourceAccessor );
+ Collection sourceReadAccessors =
+ sourceParameter.getType().getPropertyReadAccessors().values();
+ for ( ExecutableElement sourceReadAccessor : sourceReadAccessors ) {
+ String sourcePropertyName = Executables.getPropertyName( sourceReadAccessor );
if ( sourcePropertyName.equals( targetProperty.getKey() ) ) {
- candidates.add( sourceAccessor );
+ candidates.add( sourceReadAccessor );
}
}
@@ -401,7 +406,8 @@ public class BeanMappingMethod extends MappingMethod {
newPropertyMapping = new PropertyMappingBuilder()
.mappingContext( ctx )
.souceMethod( method )
- .targetAccessor( targetProperty.getValue() )
+ .targetWriteAccessor( targetProperty.getValue() )
+ .targetReadAccessor( getTargetPropertyReadAccessor( targetProperty.getKey() ) )
.targetPropertyName( targetProperty.getKey() )
.sourceReference( sourceRef )
.qualifiers( mapping != null ? mapping.getQualifiers() : null )
@@ -464,7 +470,8 @@ public class BeanMappingMethod extends MappingMethod {
PropertyMapping propertyMapping = new PropertyMappingBuilder()
.mappingContext( ctx )
.souceMethod( method )
- .targetAccessor( targetProperty.getValue() )
+ .targetWriteAccessor( targetProperty.getValue() )
+ .targetReadAccessor( getTargetPropertyReadAccessor( targetProperty.getKey() ) )
.targetPropertyName( targetProperty.getKey() )
.sourceReference( sourceRef )
.qualifiers( mapping != null ? mapping.getQualifiers() : null )
@@ -510,6 +517,10 @@ public class BeanMappingMethod extends MappingMethod {
}
}
+ private ExecutableElement getTargetPropertyReadAccessor( String propertyName ) {
+ return method.getResultType().getPropertyReadAccessors().get( propertyName );
+ }
+
/**
* Returns the effective policy for reporting unmapped getReturnType properties. If explicitly set via
* {@code Mapper}, this value will be returned. Otherwise the value from the corresponding processor option will
diff --git a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java
index fee5b3857..f1bd587e7 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java
@@ -61,7 +61,8 @@ public class PropertyMapping extends ModelElement {
private final String name;
private final String sourceBeanName;
- private final String targetAccessorName;
+ private final String targetWriteAccessorName;
+ private final String targetReadAccessorName;
private final Type targetType;
private final Assignment assignment;
private final List dependsOn;
@@ -71,7 +72,8 @@ public class PropertyMapping extends ModelElement {
// initial properties
private MappingBuilderContext ctx;
private SourceMethod method;
- private ExecutableElement targetAccessor;
+ private ExecutableElement targetWriteAccessor;
+ private ExecutableElement targetReadAccessor;
private String targetPropertyName;
private String dateFormat;
private List qualifiers;
@@ -90,8 +92,13 @@ public class PropertyMapping extends ModelElement {
return this;
}
- public PropertyMappingBuilder targetAccessor(ExecutableElement targetAccessor) {
- this.targetAccessor = targetAccessor;
+ public PropertyMappingBuilder targetReadAccessor(ExecutableElement targetReadAccessor) {
+ this.targetReadAccessor = targetReadAccessor;
+ return this;
+ }
+
+ public PropertyMappingBuilder targetWriteAccessor(ExecutableElement targetWriteAccessor) {
+ this.targetWriteAccessor = targetWriteAccessor;
return this;
}
@@ -130,8 +137,7 @@ public class PropertyMapping extends ModelElement {
return this;
}
- private enum TargetAccessorType {
-
+ private enum TargetWriteAccessorType {
GETTER,
SETTER,
ADDER
@@ -140,18 +146,18 @@ public class PropertyMapping extends ModelElement {
public PropertyMapping build() {
// handle target
- TargetAccessorType targetAccessorType = getTargetAcccessorType();
+ TargetWriteAccessorType targetAccessorType = getTargetAcccessorType();
Type targetType = getTargetType( targetAccessorType );
// handle source
String sourceElement = getSourceElement();
Type sourceType = getSourceType();
String sourceRefStr;
- if ( targetAccessorType == TargetAccessorType.ADDER && sourceType.isCollectionType() ) {
+ if ( targetAccessorType == TargetWriteAccessorType.ADDER && sourceType.isCollectionType() ) {
// handle adder, if source is collection then use iterator element type as source type.
// sourceRef becomes a local variable in the itereation.
sourceType = sourceType.getTypeParameters().get( 0 );
- sourceRefStr = Executables.getElementNameForAdder( targetAccessor );
+ sourceRefStr = Executables.getElementNameForAdder( targetWriteAccessor );
}
else {
sourceRefStr = getSourceRef();
@@ -208,19 +214,21 @@ public class PropertyMapping extends ModelElement {
return new PropertyMapping(
targetPropertyName,
sourceReference.getParameter().getName(),
- targetAccessor.getSimpleName().toString(),
+ targetWriteAccessor.getSimpleName().toString(),
+ targetReadAccessor != null ? targetReadAccessor.getSimpleName().toString() : null,
targetType,
assignment,
dependsOn
);
}
- private Assignment assignObject(Type sourceType, Type targetType, TargetAccessorType targetAccessorType,
+ private Assignment assignObject(Type sourceType, Type targetType, TargetWriteAccessorType targetAccessorType,
Assignment rhs) {
Assignment result = rhs;
- if ( targetAccessorType == TargetAccessorType.SETTER ) {
+ if ( targetAccessorType == TargetWriteAccessorType.SETTER ) {
+
result = new SetterWrapper( result, method.getThrownTypes() );
if ( !sourceType.isPrimitive()
&& !sourceReference.getPropertyEntries().isEmpty() /* parameter null taken care of by beanmapper */
@@ -252,12 +260,14 @@ public class PropertyMapping extends ModelElement {
}
- private Assignment assignCollection(Type targetType, TargetAccessorType targetAccessorType, Assignment rhs) {
+ private Assignment assignCollection(Type targetType,
+ TargetWriteAccessorType targetAccessorType,
+ Assignment rhs) {
Assignment result = rhs;
// wrap the setter in the collection / map initializers
- if ( targetAccessorType == TargetAccessorType.SETTER ) {
+ if ( targetAccessorType == TargetWriteAccessorType.SETTER ) {
// wrap the assignment in a new Map or Collection implementation if this is not done in a
// mapping method. Note, typeconversons do not apply to collections or maps
@@ -273,7 +283,7 @@ public class PropertyMapping extends ModelElement {
// target accessor is setter, so wrap the setter in setter map/ collection handling
result = new SetterWrapperForCollectionsAndMaps(
result,
- targetAccessor.getSimpleName().toString(),
+ targetWriteAccessor.getSimpleName().toString(),
newCollectionOrMap
);
}
@@ -379,26 +389,26 @@ public class PropertyMapping extends ModelElement {
}
}
- private TargetAccessorType getTargetAcccessorType() {
- if ( Executables.isSetterMethod( targetAccessor ) ) {
- return TargetAccessorType.SETTER;
+ private TargetWriteAccessorType getTargetAcccessorType() {
+ if ( Executables.isSetterMethod( targetWriteAccessor ) ) {
+ return TargetWriteAccessorType.SETTER;
}
- else if ( Executables.isAdderMethod( targetAccessor ) ) {
- return TargetAccessorType.ADDER;
+ else if ( Executables.isAdderMethod( targetWriteAccessor ) ) {
+ return TargetWriteAccessorType.ADDER;
}
else {
- return TargetAccessorType.GETTER;
+ return TargetWriteAccessorType.GETTER;
}
}
- private Type getTargetType(TargetAccessorType targetAccessorType) {
+ private Type getTargetType(TargetWriteAccessorType targetAccessorType) {
switch ( targetAccessorType ) {
case ADDER:
case SETTER:
- return ctx.getTypeFactory().getSingleParameter( targetAccessor ).getType();
+ return ctx.getTypeFactory().getSingleParameter( targetWriteAccessor ).getType();
case GETTER:
default:
- return ctx.getTypeFactory().getReturnType( targetAccessor );
+ return ctx.getTypeFactory().getReturnType( targetWriteAccessor );
}
}
@@ -477,8 +487,9 @@ public class PropertyMapping extends ModelElement {
private MappingBuilderContext ctx;
private SourceMethod method;
private String constantExpression;
- private ExecutableElement targetAccessor;
private String targetPropertyName;
+ private ExecutableElement targetWriteAccessor;
+ private ExecutableElement targetReadAccessor;
private String dateFormat;
private List qualifiers;
private TypeMirror resultType;
@@ -500,8 +511,13 @@ public class PropertyMapping extends ModelElement {
return this;
}
- public ConstantMappingBuilder targetAccessor(ExecutableElement targetAccessor) {
- this.targetAccessor = targetAccessor;
+ public ConstantMappingBuilder targetWriteAccessor(ExecutableElement targetAccessor) {
+ this.targetWriteAccessor = targetAccessor;
+ return this;
+ }
+
+ public ConstantMappingBuilder targetReadAccessor(ExecutableElement targetReadAccessor) {
+ this.targetReadAccessor = targetReadAccessor;
return this;
}
@@ -543,11 +559,11 @@ public class PropertyMapping extends ModelElement {
// target
Type targetType;
- if ( Executables.isSetterMethod( targetAccessor ) ) {
- targetType = ctx.getTypeFactory().getSingleParameter( targetAccessor ).getType();
+ if ( Executables.isSetterMethod( targetWriteAccessor ) ) {
+ targetType = ctx.getTypeFactory().getSingleParameter( targetWriteAccessor ).getType();
}
else {
- targetType = ctx.getTypeFactory().getReturnType( targetAccessor );
+ targetType = ctx.getTypeFactory().getReturnType( targetWriteAccessor );
}
Assignment assignment = ctx.getMappingResolver().getTargetAssignment(
@@ -564,7 +580,7 @@ public class PropertyMapping extends ModelElement {
if ( assignment != null ) {
- if ( Executables.isSetterMethod( targetAccessor ) ) {
+ if ( Executables.isSetterMethod( targetWriteAccessor ) ) {
// target accessor is setter, so decorate assignment as setter
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
}
@@ -591,7 +607,8 @@ public class PropertyMapping extends ModelElement {
return new PropertyMapping(
targetPropertyName,
- targetAccessor.getSimpleName().toString(),
+ targetWriteAccessor.getSimpleName().toString(),
+ targetReadAccessor != null ? targetReadAccessor.getSimpleName().toString() : null,
targetType,
assignment,
dependsOn
@@ -604,10 +621,11 @@ public class PropertyMapping extends ModelElement {
private MappingBuilderContext ctx;
private SourceMethod method;
private String javaExpression;
- private ExecutableElement targetAccessor;
private Collection existingVariableNames;
private String targetPropertyName;
private List dependsOn;
+ private ExecutableElement targetWriteAccessor;
+ private ExecutableElement targetReadAccessor;
public JavaExpressionMappingBuilder mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext;
@@ -624,8 +642,13 @@ public class PropertyMapping extends ModelElement {
return this;
}
- public JavaExpressionMappingBuilder targetAccessor(ExecutableElement targetAccessor) {
- this.targetAccessor = targetAccessor;
+ public JavaExpressionMappingBuilder targetWriteAccessor(ExecutableElement targetWriteAccessor) {
+ this.targetWriteAccessor = targetWriteAccessor;
+ return this;
+ }
+
+ public JavaExpressionMappingBuilder targetReadAccessor(ExecutableElement targetReadAccessor) {
+ this.targetReadAccessor = targetReadAccessor;
return this;
}
@@ -649,13 +672,13 @@ public class PropertyMapping extends ModelElement {
Assignment assignment = AssignmentFactory.createDirect( javaExpression );
Type targetType;
- if ( Executables.isSetterMethod( targetAccessor ) ) {
+ if ( Executables.isSetterMethod( targetWriteAccessor ) ) {
// setter, so wrap in setter
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
- targetType = ctx.getTypeFactory().getSingleParameter( targetAccessor ).getType();
+ targetType = ctx.getTypeFactory().getSingleParameter( targetWriteAccessor ).getType();
}
else {
- targetType = ctx.getTypeFactory().getReturnType( targetAccessor );
+ targetType = ctx.getTypeFactory().getReturnType( targetWriteAccessor );
// target accessor is getter, so wrap the setter in getter map/ collection handling
assignment = new GetterWrapperForCollectionsAndMaps(
assignment,
@@ -667,7 +690,8 @@ public class PropertyMapping extends ModelElement {
return new PropertyMapping(
targetPropertyName,
- targetAccessor.getSimpleName().toString(),
+ targetWriteAccessor.getSimpleName().toString(),
+ targetReadAccessor != null ? targetReadAccessor.getSimpleName().toString() : null,
targetType,
assignment,
dependsOn
@@ -677,16 +701,18 @@ public class PropertyMapping extends ModelElement {
}
// Constructor for creating mappings of constant expressions.
- private PropertyMapping(String name, String targetAccessorName, Type targetType, Assignment propertyAssignment,
- List dependsOn) {
- this( name, null, targetAccessorName, targetType, propertyAssignment, dependsOn );
+ private PropertyMapping(String name, String targetWriteAccessorName, String targetReadAccessorName, Type targetType,
+ Assignment propertyAssignment, List dependsOn) {
+ this( name, null, targetWriteAccessorName, targetReadAccessorName, targetType, propertyAssignment, dependsOn );
}
- private PropertyMapping(String name, String sourceBeanName, String targetAccessorName, Type targetType,
- Assignment assignment, List dependsOn) {
+ private PropertyMapping(String name, String sourceBeanName, String targetWriteAccessorName,
+ String targetReadAccessorName, Type targetType, Assignment assignment,
+ List dependsOn) {
this.name = name;
this.sourceBeanName = sourceBeanName;
- this.targetAccessorName = targetAccessorName;
+ this.targetWriteAccessorName = targetWriteAccessorName;
+ this.targetReadAccessorName = targetReadAccessorName;
this.targetType = targetType;
this.assignment = assignment;
this.dependsOn = dependsOn != null ? dependsOn : Collections.emptyList();
@@ -703,8 +729,12 @@ public class PropertyMapping extends ModelElement {
return sourceBeanName;
}
- public String getTargetAccessorName() {
- return targetAccessorName;
+ public String getTargetWriteAccessorName() {
+ return targetWriteAccessorName;
+ }
+
+ public String getTargetReadAccessorName() {
+ return targetReadAccessorName;
}
public Type getTargetType() {
@@ -728,6 +758,8 @@ public class PropertyMapping extends ModelElement {
public String toString() {
return "PropertyMapping {"
+ "\n name='" + name + "\',"
+ + "\n targetWriteAccessorName='" + targetWriteAccessorName + "\',"
+ + "\n targetReadAccessorName='" + targetReadAccessorName + "\',"
+ "\n targetType=" + targetType + ","
+ "\n propertyAssignment=" + assignment + ","
+ "\n dependsOn=" + dependsOn
diff --git a/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java b/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java
index ef43f0baf..cda8d4722 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java
@@ -92,13 +92,13 @@ public class TypeConversion extends ModelElement implements Assignment {
}
@Override
- public AssignmentType getType() {
+ public Assignment.AssignmentType getType() {
switch ( assignment.getType() ) {
case DIRECT:
- return AssignmentType.TYPE_CONVERTED;
+ return Assignment.AssignmentType.TYPE_CONVERTED;
case MAPPED:
- return AssignmentType.MAPPED_TYPE_CONVERTED;
+ return Assignment.AssignmentType.MAPPED_TYPE_CONVERTED;
default:
return null;
}
diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java
index b4b680bab..5bb9da615 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -81,8 +82,9 @@ public class Type extends ModelElement implements Comparable {
private final List enumConstants;
+ private Map getters = null;
+
private List allExecutables = null;
- private List getters = null;
private List setters = null;
private List adders = null;
private List alternativeTargetAccessors = null;
@@ -312,32 +314,38 @@ public class Type extends ModelElement implements Comparable {
}
/**
- * getGetters
+ * getPropertyReadAccessors
*
- * @return an unmodifiable list of all getters (including 'is' for booleans).
+ * @return an unmodifiable map of all read accessors (including 'is' for booleans), indexed by property name
*/
- public List getGetters() {
+ public Map getPropertyReadAccessors() {
if ( getters == null ) {
- getters = Collections.unmodifiableList( Filters.getterMethodsIn( getAllExecutables() ) );
+ List getterList = Filters.getterMethodsIn( getAllExecutables() );
+ Map modifiableGetters = new LinkedHashMap();
+ for (ExecutableElement getter : getterList) {
+ modifiableGetters.put( Executables.getPropertyName( getter ), getter );
+ }
+ getters = Collections.unmodifiableMap( modifiableGetters );
}
return getters;
}
/**
- * getTargetAccessors returns a list of the target accessors according to the CollectionMappingStrategy. These
- * accessors include:
+ * getPropertyWriteAccessors returns a map of the write accessors according to the CollectionMappingStrategy.
+ *
+ * These accessors include:
*
*
* - setters, the obvious candidate :-), {@link #getSetters() }
* - getters, for collections that do not have a setter, e.g. for JAXB generated collection attributes
- * {@link #getGetters() }
+ * {@link #getPropertyReadAccessors() }
* - adders, typically for from table generated entities, {@link #getAdders() }
*
*
* @param cmStrategy
- * @return an unmodifiable list of all getters (including 'is' for booleans).
+ * @return an unmodifiable map of all write accessors indexed by property name
*/
- public Map getTargetAccessors( CollectionMappingStrategyPrism cmStrategy ) {
+ public Map getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy ) {
// collect all candidate target accessors
List candidates = new ArrayList();
@@ -482,11 +490,12 @@ public class Type extends ModelElement implements Comparable {
* @return an unmodifiable list of alternative target accessors.
*/
private List getAlternativeTargetAccessors() {
+
if ( alternativeTargetAccessors == null ) {
List result = new ArrayList();
List setterMethods = getSetters();
- List getterMethods = getGetters();
+ List getterMethods = new ArrayList( getPropertyReadAccessors().values() );
// there could be a getter method for a list/map that is not present as setter.
// a getter could substitute the setter in that case and act as setter.
diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java
index 493a5271f..7d81827b2 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java
@@ -266,7 +266,7 @@ public class Mapping {
private boolean hasPropertyInReverseMethod(String name, SourceMethod method) {
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
- return method.getResultType().getTargetAccessors( cms ).containsKey( name );
+ return method.getResultType().getPropertyWriteAccessors( cms ).containsKey( name );
}
public Mapping reverse(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory) {
diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/SourceReference.java b/processor/src/main/java/org/mapstruct/ap/model/source/SourceReference.java
index 344c45f1b..2b1e91845 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/source/SourceReference.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/source/SourceReference.java
@@ -21,13 +21,13 @@ package org.mapstruct.ap.model.source;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import javax.lang.model.element.ExecutableElement;
import org.mapstruct.ap.model.common.Parameter;
import org.mapstruct.ap.model.common.Type;
import org.mapstruct.ap.model.common.TypeFactory;
-import org.mapstruct.ap.util.Executables;
import org.mapstruct.ap.util.FormattingMessager;
import org.mapstruct.ap.util.Message;
import org.mapstruct.ap.util.Strings;
@@ -173,11 +173,11 @@ public class SourceReference {
Type newType = type;
for ( String entryName : entryNames ) {
boolean matchFound = false;
- List getters = newType.getGetters();
- for ( ExecutableElement getter : getters ) {
- if ( Executables.getPropertyName( getter ).equals( entryName ) ) {
- newType = typeFactory.getType( getter.getReturnType() );
- sourceEntries.add( new PropertyEntry( entryName, getter, newType ) );
+ Map sourceReadAccessors = newType.getPropertyReadAccessors();
+ for ( Map.Entry getter : sourceReadAccessors.entrySet() ) {
+ if ( getter.getKey().equals( entryName ) ) {
+ newType = typeFactory.getType( getter.getValue().getReturnType() );
+ sourceEntries.add( new PropertyEntry( entryName, getter.getValue(), newType ) );
matchFound = true;
break;
}
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.IterableMappingMethod.ftl b/processor/src/main/resources/org.mapstruct.ap.model.IterableMappingMethod.ftl
index 4f977789f..2777b97b8 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.IterableMappingMethod.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.IterableMappingMethod.ftl
@@ -57,7 +57,7 @@
break;
}
#if>
- <@includeModel object=elementAssignment targetAccessorName=resultName+"[${index1Name}]" targetType=resultElementType isTargetDefined=true/>
+ <@includeModel object=elementAssignment targetWriteAccessorName=resultName+"[${index1Name}]" targetType=resultElementType isTargetDefined=true/>
${index1Name}++;
}
<#else>
@@ -69,7 +69,7 @@
#if>
for ( <@includeModel object=sourceElementType/> ${loopVariableName} : ${sourceParameter.name} ) {
- <@includeModel object=elementAssignment targetBeanName=resultName targetAccessorName="add" targetType=resultElementType/>
+ <@includeModel object=elementAssignment targetBeanName=resultName targetWriteAccessorName="add" targetType=resultElementType/>
}
#if>
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl b/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl
index 99869481c..56521af5f 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl
@@ -43,11 +43,11 @@
for ( java.util.Map.Entry<<#list sourceParameter.type.typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, #if>#list>> ${entryVariableName} : ${sourceParameter.name}.entrySet() ) {
<#-- key -->
<@includeModel object=keyAssignment
- targetAccessorName=keyVariableName
+ targetWriteAccessorName=keyVariableName
targetType=resultType.typeParameters[0]/>
<#-- value -->
<@includeModel object=valueAssignment
- targetAccessorName=valueVariableName
+ targetWriteAccessorName=valueVariableName
targetType=resultType.typeParameters[1]/>
${resultName}.put( ${keyVariableName}, ${valueVariableName} );
}
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.MethodReference.ftl b/processor/src/main/resources/org.mapstruct.ap.model.MethodReference.ftl
index 99f42cb54..579b8367e 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.MethodReference.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.MethodReference.ftl
@@ -26,12 +26,23 @@
<#if param.targetType>
<#-- a class is passed on for casting, see @TargetType -->
<@includeModel object=ext.targetType raw=true/>.class
+ <#elseif param.mappingTarget>
+ ${ext.targetBeanName}.${ext.targetReadAccessorName}()
<#else>
- <@includeModel object=assignment targetType=singleSourceParameterType raw=ext.raw/>
+ <@_assignment/>
#if>
<#if param_has_next>, #if>
#list>
<#-- context parameter, e.g. for builtin methods concerning date conversion -->
<#if contextParam??>, ${contextParam}#if>
#macro>
+ <#macro _assignment>
+ <@includeModel object=assignment
+ targetBeanName=ext.targetBeanName
+ raw=ext.raw
+ existingInstanceMapping=ext.existingInstanceMapping
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
+ targetType=singleSourceParameterType/>
+ #macro>
@compress>
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl b/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl
index 39f399c1d..60d98a0db 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.PropertyMapping.ftl
@@ -22,5 +22,6 @@
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName=targetAccessorName
+ targetReadAccessorName=targetReadAccessorName
+ targetWriteAccessorName=targetWriteAccessorName
targetType=targetType/>
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.TypeConversion.ftl b/processor/src/main/resources/org.mapstruct.ap.model.TypeConversion.ftl
index 6f3cd260e..5a379c211 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.TypeConversion.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.TypeConversion.ftl
@@ -18,4 +18,15 @@
limitations under the License.
-->
-${openExpression}<@includeModel object=assignment targetType=ext.targetType raw=ext.raw/>${closeExpression}
\ No newline at end of file
+<@compress single_line=true>
+${openExpression}<@_assignment/>${closeExpression}
+<#macro _assignment>
+ <@includeModel object=assignment
+ targetBeanName=ext.targetBeanName
+ raw=ext.raw
+ existingInstanceMapping=ext.existingInstanceMapping
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
+ targetType=ext.targetType/>
+#macro>
+@compress>
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl
index 752628a4e..7eef49f5f 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl
@@ -20,21 +20,23 @@
-->
<#if (exceptionTypes?size == 0) >
for ( <@includeModel object=sourceType/> ${iteratorReference} : ${sourceReference} ) {
- ${ext.targetBeanName}.${ext.targetAccessorName}( <@includeModel object=assignment
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}( <@includeModel object=assignment
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName=ext.targetAccessorName
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/> );
}
<#else>
try {
for ( <@includeModel object=sourceType/> ${iteratorReference} : ${sourceReference} ) {
- ${ext.targetBeanName}.${ext.targetAccessorName}( <@includeModel object=assignment
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}( <@includeModel object=assignment
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName=ext.targetAccessorName
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/> );
}
}
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.ArrayCopyWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.ArrayCopyWrapper.ftl
index 12399b726..218f27a80 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.ArrayCopyWrapper.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.ArrayCopyWrapper.ftl
@@ -20,11 +20,11 @@
-->
<#if (exceptionTypes?size == 0) >
<@includeModel object=ext.targetType/> ${localVarName} = <@_assignment/>;
- ${ext.targetBeanName}.${ext.targetAccessorName}( Arrays.copyOf( ${localVarName}, ${localVarName}.length ) );
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}( Arrays.copyOf( ${localVarName}, ${localVarName}.length ) );
<#else>
try {
<@includeModel object=ext.targetType/> ${localVarName} = <@_assignment/>;
- ${ext.targetBeanName}.${ext.targetAccessorName}( Arrays.copyOf( ${localVarName}, ${localVarName}.length ) );
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}( Arrays.copyOf( ${localVarName}, ${localVarName}.length ) );
}
<#list exceptionTypes as exceptionType>
catch ( <@includeModel object=exceptionType/> e ) {
@@ -33,5 +33,11 @@
#list>
#if>
<#macro _assignment>
- <@includeModel object=assignment raw=ext.raw targetType=ext.targetType/>
+ <@includeModel object=assignment
+ targetBeanName=ext.targetBeanName
+ raw=ext.raw
+ existingInstanceMapping=ext.existingInstanceMapping
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
+ targetType=ext.targetType/>
#macro>
\ No newline at end of file
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps.ftl
index 807dd5ae7..16a866418 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps.ftl
@@ -18,9 +18,9 @@
limitations under the License.
-->
-if ( ${ext.targetBeanName}.${ext.targetAccessorName}() != null ) {
+if ( ${ext.targetBeanName}.${ext.targetWriteAccessorName}() != null ) {
<#if ext.existingInstanceMapping>
- ${ext.targetBeanName}.${ext.targetAccessorName}().clear();
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}().clear();
#if>
<#if (exceptionTypes?size == 0) >
<@_assignmentLine/>
@@ -38,7 +38,7 @@ if ( ${ext.targetBeanName}.${ext.targetAccessorName}() != null ) {
<#macro _assignmentLine>
<@includeModel object=ext.targetType/> ${localVarName} = <@_assignment/>;
if ( ${localVarName} != null ) {
- ${ext.targetBeanName}.${ext.targetAccessorName}().<#if ext.targetType.collectionType>addAll<#else>putAll#if>( ${localVarName} );
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}().<#if ext.targetType.collectionType>addAll<#else>putAll#if>( ${localVarName} );
}
#macro>
<#macro _assignment>
@@ -49,4 +49,4 @@ if ( ${ext.targetBeanName}.${ext.targetAccessorName}() != null ) {
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
-#macro>
\ No newline at end of file
+#macro>
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.LocalVarWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.LocalVarWrapper.ftl
index b853f824d..973519746 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.LocalVarWrapper.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.LocalVarWrapper.ftl
@@ -19,11 +19,11 @@
-->
<#if (exceptionTypes?size == 0) >
- <#if !ext.isTargetDefined?? ><@includeModel object=ext.targetType/>#if> ${ext.targetAccessorName} = <@includeModel object=assignment targetType=ext.targetType raw=ext.raw/>;
+ <#if !ext.isTargetDefined?? ><@includeModel object=ext.targetType/>#if> ${ext.targetWriteAccessorName} = <@_assignment/>;
<#else>
- <#if !ext.isTargetDefined?? ><@includeModel object=ext.targetType/> ${ext.targetAccessorName};#if>
+ <#if !ext.isTargetDefined?? ><@includeModel object=ext.targetType/> ${ext.targetWriteAccessorName};#if>
try {
- ${ext.targetAccessorName} = <@includeModel object=assignment targetType=ext.targetType raw=ext.raw/>;
+ ${ext.targetWriteAccessorName} = <@_assignment/>;
}
<#list exceptionTypes as exceptionType>
catch ( <@includeModel object=exceptionType/> e ) {
@@ -31,3 +31,12 @@
}
#list>
#if>
+<#macro _assignment>
+ <@includeModel object=assignment
+ targetBeanName=ext.targetBeanName
+ raw=ext.raw
+ existingInstanceMapping=ext.existingInstanceMapping
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
+ targetType=ext.targetType/>
+#macro>
\ No newline at end of file
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.NewCollectionOrMapWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.NewCollectionOrMapWrapper.ftl
index f9009c3ec..1f87d64a0 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.NewCollectionOrMapWrapper.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.NewCollectionOrMapWrapper.ftl
@@ -24,5 +24,5 @@ new <#if ext.targetType.implementationType??>
<#else>
<@includeModel object=ext.targetType/>
#if>
-( <@includeModel object=assignment targetBeanName=ext.targetBeanName targetAccessorName=ext.targetAccessorName targetType=ext.targetType raw=ext.raw/> )
+( <@includeModel object=assignment targetBeanName=ext.targetBeanName targetReadAccessorName=ext.targetReadAccessorName targetWriteAccessorName=ext.targetWriteAccessorName targetType=ext.targetType raw=ext.raw/> )
@compress>
\ No newline at end of file
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.NullCheckWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.NullCheckWrapper.ftl
index 780e2cf11..b98c50e65 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.NullCheckWrapper.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.NullCheckWrapper.ftl
@@ -23,6 +23,7 @@ if ( ${sourceReference} != null ) {
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName=ext.targetAccessorName
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
}
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapper.ftl
index e5f76c26e..53643df1b 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapper.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapper.ftl
@@ -19,10 +19,10 @@
-->
<#if (exceptionTypes?size == 0) >
- ${ext.targetBeanName}.${ext.targetAccessorName}( <@_assignment/> );
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}( <@_assignment/> );
<#else>
try {
- ${ext.targetBeanName}.${ext.targetAccessorName}( <@_assignment/> );
+ ${ext.targetBeanName}.${ext.targetWriteAccessorName}( <@_assignment/> );
}
<#list exceptionTypes as exceptionType>
catch ( <@includeModel object=exceptionType/> e ) {
@@ -31,5 +31,11 @@
#list>
#if>
<#macro _assignment>
- <@includeModel object=assignment raw=ext.raw targetType=ext.targetType/>
+ <@includeModel object=assignment
+ targetBeanName=ext.targetBeanName
+ raw=ext.raw
+ existingInstanceMapping=ext.existingInstanceMapping
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
+ targetType=ext.targetType/>
#macro>
\ No newline at end of file
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapperForCollectionsAndMaps.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapperForCollectionsAndMaps.ftl
index 9e6769e06..920396ec5 100644
--- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapperForCollectionsAndMaps.ftl
+++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapperForCollectionsAndMaps.ftl
@@ -26,14 +26,16 @@
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName="${targetGetterName}().addAll"
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName="${targetGetterName}().addAll"
targetType=ext.targetType/>
<#else>
<@includeModel object=assignment
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName="${targetGetterName}().putAll"
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName="${targetGetterName}().putAll"
targetType=ext.targetType/>
#if>
}
@@ -56,7 +58,8 @@
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName=ext.targetAccessorName
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
#macro>
<#macro _newCollectionOrMapAssignment>
@@ -64,6 +67,7 @@
targetBeanName=ext.targetBeanName
raw=ext.raw
existingInstanceMapping=ext.existingInstanceMapping
- targetAccessorName=ext.targetAccessorName
+ targetReadAccessorName=ext.targetReadAccessorName
+ targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
#macro>
\ No newline at end of file