#1001 remove ForgedMethod from MappingMethods and directly create MappingMethods instead

This commit is contained in:
Filip Hrisafov 2017-01-24 22:33:14 +01:00 committed by sjaakd
parent 6e545347d0
commit b3cbfb8206
21 changed files with 674 additions and 318 deletions

View File

@ -0,0 +1,88 @@
/**
* Copyright 2012-2017 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.internal.model;
import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.Method;
/**
* @author Filip Hrisafov
*/
class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
protected B myself;
protected MappingBuilderContext ctx;
protected Method method;
AbstractBaseBuilder(Class<B> selfType) {
myself = selfType.cast( this );
}
public B mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext;
return myself;
}
public B method(Method sourceMethod) {
this.method = sourceMethod;
return myself;
}
/**
* Creates a forged assignment from the provided {@code sourceRHS} and {@code forgedMethod}. If a mapping method
* for the {@code forgedMethod} already exists, then this method used for the assignment.
*
* @param sourceRHS that needs to be used for the assignment
* @param forgedMethod the forged method for which we want to create an {@link Assignment}
*
* @return See above
*/
Assignment createForgedBeanAssignment(SourceRHS sourceRHS, ForgedMethod forgedMethod) {
BeanMappingMethod forgedMappingMethod = new BeanMappingMethod.Builder()
.forgedMethod( forgedMethod )
.mappingContext( ctx )
.build();
return createForgedAssignment( sourceRHS, forgedMethod, forgedMappingMethod );
}
Assignment createForgedAssignment(SourceRHS source, ForgedMethod methodRef, MappingMethod mappingMethod) {
if ( mappingMethod == null ) {
return null;
}
if ( !ctx.getMappingsToGenerate().contains( mappingMethod ) ) {
ctx.getMappingsToGenerate().add( mappingMethod );
}
else {
String existingName = ctx.getExistingMappingMethod( mappingMethod ).getName();
methodRef = new ForgedMethod( existingName, methodRef );
}
Assignment assignment = new MethodReference(
methodRef,
null,
ParameterBinding.fromParameters( methodRef.getParameters() )
);
assignment.setAssignment( source );
return assignment;
}
}

View File

@ -19,25 +19,72 @@
package org.mapstruct.ap.internal.model;
import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.ForgedMethodHistory;
import org.mapstruct.ap.internal.util.Strings;
/**
* An abstract builder that can be reused for building {@link MappingMethod}(s).
*
* @author Filip Hrisafov
*/
public abstract class AbstractMappingMethodBuilder<B extends AbstractMappingMethodBuilder<B, M>,
M extends MappingMethod> {
protected B myself;
protected MappingBuilderContext ctx;
M extends MappingMethod> extends AbstractBaseBuilder<B> {
public AbstractMappingMethodBuilder(Class<B> selfType) {
myself = selfType.cast( this );
}
public B mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext;
return myself;
super( selfType );
}
public abstract M build();
/**
* @return {@code true} if property names should be used for the creation of the {@link ForgedMethodHistory}.
*/
protected abstract boolean shouldUsePropertyNamesInHistory();
Assignment forgeMapping(SourceRHS sourceRHS, Type sourceType, Type targetType) {
String name = getName( sourceType, targetType );
name = Strings.getSaveVariableName( name, ctx.getNamesOfMappingsToGenerate() );
ForgedMethodHistory history = null;
if ( method instanceof ForgedMethod ) {
history = ( (ForgedMethod) method ).getHistory();
}
ForgedMethod forgedMethod = new ForgedMethod(
name,
sourceType,
targetType,
method.getMapperConfiguration(),
method.getExecutable(),
method.getContextParameters(),
new ForgedMethodHistory(
history,
Strings.stubPropertyName( sourceRHS.getSourceType().getName() ),
Strings.stubPropertyName( targetType.getName() ),
sourceRHS.getSourceType(),
targetType,
shouldUsePropertyNamesInHistory(),
sourceRHS.getSourceErrorMessagePart()
)
);
return createForgedBeanAssignment( sourceRHS, forgedMethod );
}
private String getName(Type sourceType, Type targetType) {
String fromName = getName( sourceType );
String toName = getName( targetType );
return Strings.decapitalize( fromName + "To" + toName );
}
private String getName(Type type) {
StringBuilder builder = new StringBuilder();
for ( Type typeParam : type.getTypeParameters() ) {
builder.append( typeParam.getIdentification() );
}
builder.append( type.getIdentification() );
return builder.toString();
}
}

View File

@ -217,11 +217,6 @@ public class BeanMappingMethod extends MappingMethod {
List<LifecycleCallbackMethodReference> afterMappingMethods =
LifecycleCallbackFactory.afterMappingMethods( method, selectionParameters, ctx, existingVariableNames );
List<ForgedMethod> allForgedMethods = new ArrayList<ForgedMethod>();
for ( PropertyMapping propertyMapping : propertyMappings ) {
allForgedMethods.addAll( propertyMapping.getForgedMethods() );
}
return new BeanMappingMethod(
method,
propertyMappings,
@ -231,8 +226,7 @@ public class BeanMappingMethod extends MappingMethod {
existingVariableNames,
beforeMappingMethods,
afterMappingMethods,
nestedTargetObjects,
allForgedMethods
nestedTargetObjects
);
}
@ -637,9 +631,8 @@ public class BeanMappingMethod extends MappingMethod {
Collection<String> existingVariableNames,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
NestedTargetObjects nestedTargetObjects,
List<ForgedMethod> allForgedMethods) {
super( method, existingVariableNames, beforeMappingReferences, afterMappingReferences, allForgedMethods );
NestedTargetObjects nestedTargetObjects) {
super( method, existingVariableNames, beforeMappingReferences, afterMappingReferences );
this.propertyMappings = propertyMappings;
// intialize constant mappings as all mappings, but take out the ones that can be contributed to a

View File

@ -18,16 +18,13 @@
*/
package org.mapstruct.ap.internal.model;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.lang.model.type.TypeKind;
import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.util.Strings;
@ -48,14 +45,11 @@ public abstract class ContainerMappingMethod extends MappingMethod {
private final SelectionParameters selectionParameters;
ContainerMappingMethod(Method method, Assignment parameterAssignment, MethodReference factoryMethod,
boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters, ForgedMethod forgedMethod) {
super( method, beforeMappingReferences, afterMappingReferences,
forgedMethod == null ? Collections.<ForgedMethod>emptyList() :
java.util.Collections.singletonList( forgedMethod )
);
boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters) {
super( method, beforeMappingReferences, afterMappingReferences );
this.elementAssignment = parameterAssignment;
this.factoryMethod = factoryMethod;
this.overridden = method.overridesMethod();

View File

@ -23,10 +23,8 @@ import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.ForgedMethodHistory;
import org.mapstruct.ap.internal.model.source.FormattingParameters;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
@ -46,11 +44,9 @@ import static org.mapstruct.ap.internal.util.Collections.first;
public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMethodBuilder<B, M>,
M extends ContainerMappingMethod> extends AbstractMappingMethodBuilder<B, M> {
private Method method;
private SelectionParameters selectionParameters;
private FormattingParameters formattingParameters;
private NullValueMappingStrategyPrism nullValueMappingStrategy;
private ForgedMethod forgedMethod;
private String errorMessagePart;
private String callingContextTargetPropertyName;
@ -59,11 +55,6 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
this.errorMessagePart = errorMessagePart;
}
public B method(Method sourceMethod) {
this.method = sourceMethod;
return myself;
}
public B formattingParameters(FormattingParameters formattingParameters) {
this.formattingParameters = formattingParameters;
return myself;
@ -157,8 +148,7 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
loopVariableName,
beforeMappingMethods,
afterMappingMethods,
selectionParameters,
forgedMethod
selectionParameters
);
}
@ -166,58 +156,14 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingMethods,
List<LifecycleCallbackMethodReference> afterMappingMethods,
SelectionParameters selectionParameters, ForgedMethod forgedMethod);
SelectionParameters selectionParameters);
protected abstract Type getElementType(Type parameterType);
protected abstract Assignment getWrapper(Assignment assignment, Method method);
private Assignment forgeMapping(SourceRHS sourceRHS, Type sourceType, Type targetType) {
ForgedMethodHistory forgedMethodHistory = null;
if ( method instanceof ForgedMethod ) {
forgedMethodHistory = ( (ForgedMethod) method ).getHistory();
}
String name = getName( sourceType, targetType );
forgedMethod = new ForgedMethod(
name,
sourceType,
targetType,
method.getMapperConfiguration(),
method.getExecutable(),
method.getContextParameters(),
new ForgedMethodHistory( forgedMethodHistory,
Strings.stubPropertyName( sourceRHS.getSourceType().getName() ),
Strings.stubPropertyName( targetType.getName() ),
sourceRHS.getSourceType(),
targetType,
false,
sourceRHS.getSourceErrorMessagePart()
)
);
Assignment assignment = new MethodReference(
forgedMethod,
null,
ParameterBinding.fromParameters( forgedMethod.getParameters() )
);
assignment.setAssignment( sourceRHS );
return assignment;
}
private String getName(Type sourceType, Type targetType) {
String fromName = getName( sourceType );
String toName = getName( targetType );
return Strings.decapitalize( fromName + "To" + toName );
}
private String getName(Type type) {
StringBuilder builder = new StringBuilder();
for ( Type typeParam : type.getTypeParameters() ) {
builder.append( typeParam.getIdentification() );
}
builder.append( type.getIdentification() );
return builder.toString();
@Override
protected boolean shouldUsePropertyNamesInHistory() {
return false;
}
}

View File

@ -26,7 +26,6 @@ import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.assignment.LocalVarWrapper;
import org.mapstruct.ap.internal.model.assignment.SetterWrapper;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
@ -66,8 +65,7 @@ public class IterableMappingMethod extends ContainerMappingMethod {
protected IterableMappingMethod instantiateMappingMethod(Method method, Assignment assignment,
MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingMethods,
List<LifecycleCallbackMethodReference> afterMappingMethods, SelectionParameters selectionParameters,
ForgedMethod forgedMethod) {
List<LifecycleCallbackMethodReference> afterMappingMethods, SelectionParameters selectionParameters) {
return new IterableMappingMethod(
method,
assignment,
@ -76,8 +74,7 @@ public class IterableMappingMethod extends ContainerMappingMethod {
loopVariableName,
beforeMappingMethods,
afterMappingMethods,
selectionParameters,
forgedMethod
selectionParameters
);
}
}
@ -86,7 +83,7 @@ public class IterableMappingMethod extends ContainerMappingMethod {
boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters, ForgedMethod forgedMethod) {
SelectionParameters selectionParameters) {
super(
method,
parameterAssignment,
@ -95,8 +92,7 @@ public class IterableMappingMethod extends ContainerMappingMethod {
loopVariableName,
beforeMappingReferences,
afterMappingReferences,
selectionParameters,
forgedMethod
selectionParameters
);
}

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.internal.model;
import static org.mapstruct.ap.internal.util.Collections.first;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -29,10 +28,8 @@ import java.util.Set;
import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.assignment.LocalVarWrapper;
import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.ForgedMethodHistory;
import org.mapstruct.ap.internal.model.source.FormattingParameters;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
@ -53,25 +50,16 @@ public class MapMappingMethod extends MappingMethod {
private final boolean overridden;
private final boolean mapNullToDefault;
public static class Builder {
public static class Builder extends AbstractMappingMethodBuilder<Builder, MapMappingMethod> {
private FormattingParameters keyFormattingParameters;
private FormattingParameters valueFormattingParameters;
private Method method;
private MappingBuilderContext ctx;
private NullValueMappingStrategyPrism nullValueMappingStrategy;
private SelectionParameters keySelectionParameters;
private SelectionParameters valueSelectionParameters;
private List<ForgedMethod> forgedMethods = new ArrayList<ForgedMethod>();
public Builder mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext;
return this;
}
public Builder method(Method sourceMethod) {
this.method = sourceMethod;
return this;
public Builder() {
super( Builder.class );
}
public Builder keySelectionParameters(SelectionParameters keySelectionParameters) {
@ -181,70 +169,21 @@ public class MapMappingMethod extends MappingMethod {
factoryMethod,
mapNullToDefault,
beforeMappingMethods,
afterMappingMethods,
forgedMethods
afterMappingMethods
);
}
private Assignment forgeMapping(SourceRHS sourceRHS, Type sourceType, Type targetType) {
String name = getName( sourceType, targetType );
ForgedMethodHistory history = null;
if ( method instanceof ForgedMethod ) {
history = ( (ForgedMethod) method ).getHistory();
}
ForgedMethod forgedMethod = new ForgedMethod(
name,
sourceType,
targetType,
method.getMapperConfiguration(),
method.getExecutable(),
method.getContextParameters(),
new ForgedMethodHistory( history,
Strings.stubPropertyName( sourceRHS.getSourceType().getName() ),
Strings.stubPropertyName( targetType.getName() ),
sourceRHS.getSourceType(),
targetType,
true,
sourceRHS.getSourceErrorMessagePart()
)
);
Assignment assignment = new MethodReference(
forgedMethod,
null,
ParameterBinding.fromParameters( forgedMethod.getParameters() ) );
assignment.setAssignment( sourceRHS );
forgedMethods.add( forgedMethod );
return assignment;
@Override
protected boolean shouldUsePropertyNamesInHistory() {
return true;
}
private String getName(Type sourceType, Type targetType) {
String fromName = getName( sourceType );
String toName = getName( targetType );
return Strings.decapitalize( fromName + "To" + toName );
}
private String getName(Type type) {
StringBuilder builder = new StringBuilder();
for ( Type typeParam : type.getTypeParameters() ) {
builder.append( typeParam.getIdentification() );
}
builder.append( type.getIdentification() );
return builder.toString();
}
}
private MapMappingMethod(Method method, Assignment keyAssignment, Assignment valueAssignment,
MethodReference factoryMethod, boolean mapNullToDefault,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
List<ForgedMethod> forgedMethods) {
super( method, beforeMappingReferences, afterMappingReferences, forgedMethods );
List<LifecycleCallbackMethodReference> afterMappingReferences) {
super( method, beforeMappingReferences, afterMappingReferences );
this.keyAssignment = keyAssignment;
this.valueAssignment = valueAssignment;

View File

@ -23,7 +23,6 @@ import static org.mapstruct.ap.internal.util.Strings.join;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -32,7 +31,6 @@ import org.mapstruct.ap.internal.model.common.Accessibility;
import org.mapstruct.ap.internal.model.common.ModelElement;
import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.Method;
/**
@ -54,7 +52,6 @@ public abstract class MappingMethod extends ModelElement {
private final List<LifecycleCallbackMethodReference> beforeMappingReferencesWithMappingTarget;
private final List<LifecycleCallbackMethodReference> beforeMappingReferencesWithoutMappingTarget;
private final List<LifecycleCallbackMethodReference> afterMappingReferences;
private final List<ForgedMethod> forgedMethods;
/**
* constructor to be overloaded when local variable names are required prior to calling this constructor. (e.g. for
@ -68,14 +65,12 @@ public abstract class MappingMethod extends ModelElement {
protected MappingMethod(Method method, Collection<String> existingVariableNames,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences) {
this( method, method.getParameters(), existingVariableNames, beforeMappingReferences, afterMappingReferences,
Collections.<ForgedMethod>emptyList() );
this( method, method.getParameters(), existingVariableNames, beforeMappingReferences, afterMappingReferences );
}
protected MappingMethod(Method method, List<Parameter> parameters, Collection<String> existingVariableNames,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
List<ForgedMethod> forgedMethods) {
List<LifecycleCallbackMethodReference> afterMappingReferences) {
this.name = method.getName();
this.parameters = parameters;
this.sourceParameters = Parameter.getSourceParameters( parameters );
@ -88,12 +83,10 @@ public abstract class MappingMethod extends ModelElement {
this.beforeMappingReferencesWithMappingTarget = filterMappingTarget( beforeMappingReferences, true );
this.beforeMappingReferencesWithoutMappingTarget = filterMappingTarget( beforeMappingReferences, false );
this.afterMappingReferences = afterMappingReferences;
this.forgedMethods = forgedMethods;
}
protected MappingMethod(Method method, List<Parameter> parameters) {
this( method, parameters, new ArrayList<String>( method.getParameterNames() ), null, null,
Collections.<ForgedMethod>emptyList() );
this( method, parameters, new ArrayList<String>( method.getParameterNames() ), null, null );
}
protected MappingMethod(Method method) {
@ -106,21 +99,6 @@ public abstract class MappingMethod extends ModelElement {
afterMappingReferences );
}
protected MappingMethod(Method method, List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
List<ForgedMethod> forgedMethods) {
this( method, method.getParameters(), new ArrayList<String>( method.getParameterNames() ),
beforeMappingReferences, afterMappingReferences, forgedMethods );
}
public MappingMethod(Method method, Collection<String> existingVariableNames,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
List<ForgedMethod> allForgedMethods) {
this( method, method.getParameters(), existingVariableNames, beforeMappingReferences, afterMappingReferences,
allForgedMethods );
}
private String initResultName(Collection<String> existingVarNames) {
if ( targetParameter != null ) {
return targetParameter.getName();
@ -239,10 +217,6 @@ public abstract class MappingMethod extends ModelElement {
return beforeMappingReferencesWithoutMappingTarget;
}
public List<ForgedMethod> getForgedMethods() {
return forgedMethods;
}
@Override
public int hashCode() {
int hash = 7;

View File

@ -36,7 +36,6 @@ import org.mapstruct.ap.internal.model.assignment.SetterWrapperForCollectionsAnd
import org.mapstruct.ap.internal.model.assignment.UpdateWrapper;
import org.mapstruct.ap.internal.model.common.ModelElement;
import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.ForgedMethodHistory;
@ -76,7 +75,6 @@ public class PropertyMapping extends ModelElement {
private final Assignment assignment;
private final List<String> dependsOn;
private final Assignment defaultValueAssignment;
private List<ForgedMethod> forgedMethods = new ArrayList<ForgedMethod>();
private enum TargetWriteAccessorType {
FIELD,
@ -101,10 +99,7 @@ public class PropertyMapping extends ModelElement {
}
@SuppressWarnings("unchecked")
private static class MappingBuilderBase<T extends MappingBuilderBase<T>> {
protected MappingBuilderContext ctx;
protected Method method;
private static class MappingBuilderBase<T extends MappingBuilderBase<T>> extends AbstractBaseBuilder<T> {
protected Accessor targetWriteAccessor;
protected TargetWriteAccessorType targetWriteAccessorType;
@ -117,14 +112,12 @@ public class PropertyMapping extends ModelElement {
protected List<String> dependsOn;
protected Set<String> existingVariableNames;
public T mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext;
return (T) this;
MappingBuilderBase(Class<T> selfType) {
super( selfType );
}
public T sourceMethod(Method sourceMethod) {
this.method = sourceMethod;
return (T) this;
return super.method( sourceMethod );
}
public T targetProperty(PropertyEntry targetProp) {
@ -205,7 +198,10 @@ public class PropertyMapping extends ModelElement {
private SourceRHS rightHandSide;
private FormattingParameters formattingParameters;
private SelectionParameters selectionParameters;
private List<ForgedMethod> forgedMethods = new ArrayList<ForgedMethod>();
PropertyMappingBuilder() {
super( PropertyMappingBuilder.class );
}
public PropertyMappingBuilder sourceReference(SourceReference sourceReference) {
this.sourceReference = sourceReference;
@ -303,8 +299,7 @@ public class PropertyMapping extends ModelElement {
localTargetVarName,
assignment,
dependsOn,
getDefaultValueAssignment( assignment ),
forgedMethods
getDefaultValueAssignment( assignment )
);
}
@ -563,31 +558,7 @@ public class PropertyMapping extends ModelElement {
.callingContextTargetPropertyName( targetPropertyName )
.build();
return getForgedAssignment( source, methodRef, iterableMappingMethod );
}
private Assignment getForgedAssignment(SourceRHS source, ForgedMethod methodRef,
MappingMethod mappingMethod) {
Assignment assignment = null;
if ( mappingMethod != null ) {
if ( !ctx.getMappingsToGenerate().contains( mappingMethod ) ) {
ctx.getMappingsToGenerate().add( mappingMethod );
}
else {
String existingName = ctx.getExistingMappingMethod( mappingMethod ).getName();
methodRef = new ForgedMethod( existingName, methodRef );
}
assignment = new MethodReference(
methodRef,
null,
ParameterBinding.fromParameters( methodRef.getParameters() )
);
assignment.setAssignment( source );
forgedMethods.addAll( mappingMethod.getForgedMethods() );
}
return assignment;
return createForgedAssignment( source, methodRef, iterableMappingMethod );
}
private ForgedMethod prepareForgedMethod(Type sourceType, Type targetType, SourceRHS source,
@ -619,7 +590,7 @@ public class PropertyMapping extends ModelElement {
.method( methodRef )
.build();
return getForgedAssignment( source, methodRef, mapMappingMethod );
return createForgedAssignment( source, methodRef, mapMappingMethod );
}
private Assignment forgeMapping(SourceRHS sourceRHS) {
@ -632,6 +603,7 @@ public class PropertyMapping extends ModelElement {
}
String name = getName( sourceType, targetType );
name = Strings.getSaveVariableName( name, ctx.getNamesOfMappingsToGenerate() );
List<Parameter> parameters = new ArrayList( method.getContextParameters() );
Type returnType;
if ( method.isUpdateMethod() ) {
@ -651,16 +623,8 @@ public class PropertyMapping extends ModelElement {
getForgedMethodHistory( sourceRHS )
);
Assignment assignment = new MethodReference(
forgedMethod,
null,
ParameterBinding.fromParameters( forgedMethod.getParameters() ) );
assignment.setAssignment( sourceRHS );
this.forgedMethods.add( forgedMethod );
return assignment;
return createForgedBeanAssignment( sourceRHS, forgedMethod );
}
private ForgedMethodHistory getForgedMethodHistory(SourceRHS sourceRHS) {
@ -715,6 +679,10 @@ public class PropertyMapping extends ModelElement {
private FormattingParameters formattingParameters;
private SelectionParameters selectionParameters;
ConstantMappingBuilder() {
super( ConstantMappingBuilder.class );
}
public ConstantMappingBuilder constantExpression(String constantExpression) {
this.constantExpression = constantExpression;
return this;
@ -834,6 +802,10 @@ public class PropertyMapping extends ModelElement {
private String javaExpression;
JavaExpressionMappingBuilder() {
super( JavaExpressionMappingBuilder.class );
}
public JavaExpressionMappingBuilder javaExpression(String javaExpression) {
this.javaExpression = javaExpression;
return this;
@ -876,15 +848,14 @@ public class PropertyMapping extends ModelElement {
Type targetType, String localTargetVarName, Assignment propertyAssignment,
List<String> dependsOn, Assignment defaultValueAssignment ) {
this( name, null, targetWriteAccessorName, targetReadAccessorProvider,
targetType, localTargetVarName, propertyAssignment, dependsOn, defaultValueAssignment,
Collections.<ForgedMethod>emptyList() );
targetType, localTargetVarName, propertyAssignment, dependsOn, defaultValueAssignment
);
}
private PropertyMapping(String name, String sourceBeanName, String targetWriteAccessorName,
ValueProvider targetReadAccessorProvider, Type targetType, String localTargetVarName,
Assignment assignment,
List<String> dependsOn, Assignment defaultValueAssignment,
List<ForgedMethod> forgedMethods) {
List<String> dependsOn, Assignment defaultValueAssignment) {
this.name = name;
this.sourceBeanName = sourceBeanName;
this.targetWriteAccessorName = targetWriteAccessorName;
@ -895,7 +866,6 @@ public class PropertyMapping extends ModelElement {
this.assignment = assignment;
this.dependsOn = dependsOn != null ? dependsOn : Collections.<String>emptyList();
this.defaultValueAssignment = defaultValueAssignment;
this.forgedMethods = forgedMethods;
}
/**
@ -950,10 +920,6 @@ public class PropertyMapping extends ModelElement {
return dependsOn;
}
public List<ForgedMethod> getForgedMethods() {
return forgedMethods;
}
@Override
public String toString() {
return "PropertyMapping {"

View File

@ -28,7 +28,6 @@ import java.util.stream.StreamSupport;
import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.assignment.Java8FunctionWrapper;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
@ -64,8 +63,7 @@ public class StreamMappingMethod extends ContainerMappingMethod {
protected StreamMappingMethod instantiateMappingMethod(Method method, Assignment assignment,
MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingMethods,
List<LifecycleCallbackMethodReference> afterMappingMethods, SelectionParameters selectionParameters,
ForgedMethod forgedMethod) {
List<LifecycleCallbackMethodReference> afterMappingMethods, SelectionParameters selectionParameters) {
Set<Type> helperImports = new HashSet<Type>();
if ( method.getResultType().isIterableType() ) {
@ -87,8 +85,7 @@ public class StreamMappingMethod extends ContainerMappingMethod {
beforeMappingMethods,
afterMappingMethods,
selectionParameters,
helperImports,
forgedMethod
helperImports
);
}
}
@ -97,8 +94,7 @@ public class StreamMappingMethod extends ContainerMappingMethod {
boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters, Set<Type> helperImports,
ForgedMethod forgedMethod) {
SelectionParameters selectionParameters, Set<Type> helperImports) {
super(
method,
parameterAssignment,
@ -107,8 +103,7 @@ public class StreamMappingMethod extends ContainerMappingMethod {
loopVariableName,
beforeMappingReferences,
afterMappingReferences,
selectionParameters,
forgedMethod
selectionParameters
);
this.helperImports = helperImports;
}

View File

@ -19,12 +19,9 @@
package org.mapstruct.ap.internal.processor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.lang.model.element.ExecutableElement;
@ -52,7 +49,6 @@ import org.mapstruct.ap.internal.model.StreamMappingMethod;
import org.mapstruct.ap.internal.model.ValueMappingMethod;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.FormattingParameters;
import org.mapstruct.ap.internal.model.source.MappingOptions;
import org.mapstruct.ap.internal.model.source.Method;
@ -153,7 +149,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
private Mapper getMapper(TypeElement element, MapperConfiguration mapperConfig, List<SourceMethod> methods) {
List<MapperReference> mapperReferences = mappingContext.getMapperReferences();
List<MappingMethod> mappingMethods = getAllMappingMethods( mapperConfig, methods );
List<MappingMethod> mappingMethods = getMappingMethods( mapperConfig, methods );
mappingMethods.addAll( mappingContext.getUsedVirtualMappings() );
mappingMethods.addAll( mappingContext.getMappingsToGenerate() );
@ -262,55 +258,6 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
return extraImports;
}
private List<MappingMethod> getAllMappingMethods(MapperConfiguration mapperConfig, List<SourceMethod> methods) {
List<MappingMethod> mappingMethods = getMappingMethods( mapperConfig, methods );
Collection<ForgedMethod> excludedForgedMethods = new HashSet<ForgedMethod>( );
Collection<ForgedMethod> forgedMethods = collectAllForgedMethods( mappingMethods, excludedForgedMethods );
while ( !forgedMethods.isEmpty() ) {
List<MappingMethod> mappingMethodsFromForged = createBeanMapping( forgedMethods );
forgedMethods = collectAllForgedMethods( mappingMethodsFromForged, excludedForgedMethods );
mappingMethods.addAll( mappingMethodsFromForged );
}
return mappingMethods;
}
private List<MappingMethod> createBeanMapping(Collection<ForgedMethod> forgedMethods) {
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();
for ( ForgedMethod method : forgedMethods ) {
BeanMappingMethod.Builder builder = new BeanMappingMethod.Builder();
BeanMappingMethod beanMappingMethod = builder
.mappingContext( mappingContext )
.forgedMethod( method )
.build();
if ( beanMappingMethod != null ) {
mappingMethods.add( beanMappingMethod );
}
}
return mappingMethods;
}
private Collection<ForgedMethod> collectAllForgedMethods(Collection<MappingMethod> mappingMethods,
Collection<ForgedMethod> excludedForgedMethods) {
Set<ForgedMethod> forgedMethods = new HashSet<ForgedMethod>();
for ( MappingMethod mappingMethod : mappingMethods ) {
for ( ForgedMethod forgedMethod : mappingMethod.getForgedMethods() ) {
if ( !excludedForgedMethods.contains( forgedMethod )) {
forgedMethods.add( forgedMethod );
excludedForgedMethods.add( forgedMethod );
}
}
}
return forgedMethods;
}
private List<MappingMethod> getMappingMethods(MapperConfiguration mapperConfig, List<SourceMethod> methods) {
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();

View File

@ -122,6 +122,11 @@ public class CollectionMappingTest {
line = 30,
messageRegExp = "Can't map Map key \".* nonMappableMap\\{:key\\}\" to \".* nonMappableMap\\{:key\\}\". "
+ "Consider to declare/implement a mapping method: .*."),
@Diagnostic(type = ErroneousCollectionNonMappableMapMapper.class,
kind = Kind.ERROR,
line = 30,
messageRegExp = "Can't map Map value \".* nonMappableMap\\{:value\\}\" to \".* " +
"nonMappableMap\\{:value\\}\". Consider to declare/implement a mapping method: .*."),
}
)
public void shouldGenerateNonMappleMethodForMapMapping() {

View File

@ -29,6 +29,11 @@ import static org.assertj.core.api.Assertions.assertThat;
User.class, UserDto.class, Car.class, CarDto.class, House.class, HouseDto.class,
Wheel.class, WheelDto.class,
Roof.class, RoofDto.class,
org.mapstruct.ap.test.nestedbeans.other.CarDto.class,
org.mapstruct.ap.test.nestedbeans.other.UserDto.class,
org.mapstruct.ap.test.nestedbeans.other.HouseDto.class,
org.mapstruct.ap.test.nestedbeans.other.RoofDto.class,
org.mapstruct.ap.test.nestedbeans.other.WheelDto.class,
UserDtoMapperClassic.class,
UserDtoMapperSmart.class,
UserDtoUpdateMapperSmart.class

View File

@ -22,6 +22,7 @@ public class User {
private String name;
private Car car;
private Car secondCar;
private House house;
public User() {
@ -49,6 +50,14 @@ public class User {
this.car = car;
}
public Car getSecondCar() {
return secondCar;
}
public void setSecondCar(Car secondCar) {
this.secondCar = secondCar;
}
public House getHouse() {
return house;
}

View File

@ -22,6 +22,7 @@ public class UserDto {
private String name;
private CarDto car;
private CarDto secondCar;
private HouseDto house;
public UserDto() {
@ -49,6 +50,14 @@ public class UserDto {
this.car = car;
}
public CarDto getSecondCar() {
return secondCar;
}
public void setSecondCar(CarDto secondCar) {
this.secondCar = secondCar;
}
public HouseDto getHouse() {
return house;
}

View File

@ -28,4 +28,5 @@ public interface UserDtoMapperSmart {
UserDto userToUserDto(User user);
org.mapstruct.ap.test.nestedbeans.other.UserDto userToUserDto2( User user );
}

View File

@ -0,0 +1,100 @@
/**
* Copyright 2012-2017 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.test.nestedbeans.other;
import java.util.List;
public class CarDto {
private String name;
private int year;
private List<WheelDto> wheels;
public CarDto() {
}
public CarDto(String name, int year, List<WheelDto> wheels) {
this.name = name;
this.year = year;
this.wheels = wheels;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public List<WheelDto> getWheels() {
return wheels;
}
public void setWheels(List<WheelDto> wheels) {
this.wheels = wheels;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
CarDto carDto = (CarDto) o;
if ( year != carDto.year ) {
return false;
}
if ( name != null ? !name.equals( carDto.name ) : carDto.name != null ) {
return false;
}
return wheels != null ? wheels.equals( carDto.wheels ) : carDto.wheels == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + year;
result = 31 * result + ( wheels != null ? wheels.hashCode() : 0 );
return result;
}
@Override
public String toString() {
return "CarDto{" +
"name='" + name + '\'' +
", year=" + year +
", wheels=" + wheels +
'}';
}
}

View File

@ -0,0 +1,98 @@
/**
* Copyright 2012-2017 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.test.nestedbeans.other;
public class HouseDto {
private String name;
private int year;
private RoofDto roof;
public HouseDto() {
}
public HouseDto(String name, int year, RoofDto roof) {
this.name = name;
this.year = year;
this.roof = roof;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public RoofDto getRoof() {
return roof;
}
public void setRoof(RoofDto roof) {
this.roof = roof;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
HouseDto houseDto = (HouseDto) o;
if ( year != houseDto.year ) {
return false;
}
if ( name != null ? !name.equals( houseDto.name ) : houseDto.name != null ) {
return false;
}
return roof != null ? roof.equals( houseDto.roof ) : houseDto.roof == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + year;
result = 31 * result + ( roof != null ? roof.hashCode() : 0 );
return result;
}
@Override
public String toString() {
return "HouseDto{" +
"name='" + name + '\'' +
", year=" + year +
", roof=" + roof +
'}';
}
}

View File

@ -0,0 +1,66 @@
/**
* Copyright 2012-2017 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.test.nestedbeans.other;
public class RoofDto {
private String color;
public RoofDto() {
}
public RoofDto(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
RoofDto roofDto = (RoofDto) o;
return color != null ? color.equals( roofDto.color ) : roofDto.color == null;
}
@Override
public int hashCode() {
return color != null ? color.hashCode() : 0;
}
@Override
public String toString() {
return "RoofDto{" +
"color='" + color + '\'' +
'}';
}
}

View File

@ -0,0 +1,98 @@
/**
* Copyright 2012-2017 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.test.nestedbeans.other;
public class UserDto {
private String name;
private CarDto car;
private HouseDto house;
public UserDto() {
}
public UserDto(String name, CarDto car, HouseDto house) {
this.name = name;
this.car = car;
this.house = house;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CarDto getCar() {
return car;
}
public void setCar(CarDto car) {
this.car = car;
}
public HouseDto getHouse() {
return house;
}
public void setHouse(HouseDto house) {
this.house = house;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
UserDto userDto = (UserDto) o;
if ( name != null ? !name.equals( userDto.name ) : userDto.name != null ) {
return false;
}
if ( car != null ? !car.equals( userDto.car ) : userDto.car != null ) {
return false;
}
return house != null ? house.equals( userDto.house ) : userDto.house == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + ( car != null ? car.hashCode() : 0 );
result = 31 * result + ( house != null ? house.hashCode() : 0 );
return result;
}
@Override
public String toString() {
return "UserDto{" +
"name='" + name + '\'' +
", car=" + car +
", house=" + house +
'}';
}
}

View File

@ -0,0 +1,80 @@
/**
* Copyright 2012-2017 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.test.nestedbeans.other;
public class WheelDto {
private boolean front;
private boolean right;
public WheelDto() {
}
public WheelDto(boolean front, boolean right) {
this.front = front;
this.right = right;
}
public boolean isFront() {
return front;
}
public void setFront(boolean front) {
this.front = front;
}
public boolean isRight() {
return right;
}
public void setRight(boolean right) {
this.right = right;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
WheelDto wheel = (WheelDto) o;
if ( front != wheel.front ) {
return false;
}
return right == wheel.right;
}
@Override
public int hashCode() {
int result = ( front ? 1 : 0 );
result = 31 * result + ( right ? 1 : 0 );
return result;
}
@Override
public String toString() {
return "Wheel{" + ( front ? "front" : "rear" ) + ";" + ( right ? "right" : "left" ) + '}';
}
}