#973 Setter and Update wrapper refactoring and cleanup

This commit is contained in:
sjaakd 2016-12-05 23:15:20 +01:00
parent d398618aa5
commit 70896245d7
18 changed files with 256 additions and 202 deletions

View File

@ -152,6 +152,11 @@ public class MethodReference extends MappingMethod implements Assignment {
assignment.setSourceLocalVarName( sourceLocalVarName );
}
@Override
public String getSourceParameterName() {
return assignment.getSourceParameterName();
}
/**
* @return the type of the single source parameter that is not the {@code @TargetType} parameter
*/
@ -206,7 +211,7 @@ public class MethodReference extends MappingMethod implements Assignment {
}
@Override
public boolean isUpdateMethod() {
public boolean isCallingUpdateMethod() {
return isUpdateMethod;
}
}

View File

@ -19,9 +19,6 @@
package org.mapstruct.ap.internal.model;
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.DIRECT;
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.MAPPED_TYPE_CONVERTED;
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED;
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED_MAPPED;
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS;
import static org.mapstruct.ap.internal.util.Collections.first;
import static org.mapstruct.ap.internal.util.Collections.last;
@ -43,7 +40,6 @@ import org.mapstruct.ap.internal.model.assignment.GetterWrapperForCollectionsAnd
import org.mapstruct.ap.internal.model.assignment.NullCheckWrapper;
import org.mapstruct.ap.internal.model.assignment.SetterWrapper;
import org.mapstruct.ap.internal.model.assignment.SetterWrapperForCollectionsAndMaps;
import org.mapstruct.ap.internal.model.assignment.UpdateNullCheckWrapper;
import org.mapstruct.ap.internal.model.assignment.UpdateWrapper;
import org.mapstruct.ap.internal.model.common.ModelElement;
import org.mapstruct.ap.internal.model.common.Parameter;
@ -55,6 +51,7 @@ import org.mapstruct.ap.internal.model.source.PropertyEntry;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SourceReference;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Message;
@ -335,7 +332,7 @@ public class PropertyMapping extends ModelElement {
if ( targetAccessorType == TargetWriteAccessorType.SETTER ||
targetAccessorType == TargetWriteAccessorType.FIELD ) {
result = assignToPlainViaSetter( sourceType, targetType, rightHandSide );
result = assignToPlainViaSetter( targetType, rightHandSide );
}
else {
result = assignToPlainViaAdder( rightHandSide );
@ -344,11 +341,9 @@ public class PropertyMapping extends ModelElement {
}
private Assignment assignToPlainViaSetter(Type sourceType, Type targetType, Assignment rhs) {
private Assignment assignToPlainViaSetter(Type targetType, Assignment rhs) {
Assignment result;
if ( rhs.isUpdateMethod() ) {
if ( rhs.isCallingUpdateMethod() ) {
if ( targetReadAccessor == null ) {
ctx.getMessager().printMessage(
method.getExecutable(),
@ -356,59 +351,13 @@ public class PropertyMapping extends ModelElement {
targetPropertyName
);
}
Assignment factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
result = new UpdateWrapper( rhs, method.getThrownTypes(), factoryMethod,
targetType, isFieldAssignment()
);
Assignment factory = ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
return new UpdateWrapper( rhs, method.getThrownTypes(), factory, isFieldAssignment(), targetType,
true );
}
else {
result = new SetterWrapper( rhs, method.getThrownTypes(), isFieldAssignment() );
}
// if the sourceReference is the bean mapping method parameter itself, no null check is required
// since this is handled by the BeanMapping
if ( sourceReference.getPropertyEntries().isEmpty() ) {
return result;
}
// add a null / presence checked when required
if ( sourceType.isPrimitive() ) {
if ( rhs.getSourcePresenceCheckerReference() != null ) {
result = new NullCheckWrapper( result );
}
}
else {
if ( result.isUpdateMethod() ) {
result = new UpdateNullCheckWrapper( result, isFieldAssignment() );
}
else if ( rhs.getSourcePresenceCheckerReference() != null ) {
result = new NullCheckWrapper( result );
}
else if ( ALWAYS.equals( method.getMapperConfiguration().getNullValueCheckStrategy() ) ) {
result = new NullCheckWrapper( result );
useLocalVarWhenNested( result );
}
else if ( result.getType() == TYPE_CONVERTED
|| result.getType() == TYPE_CONVERTED_MAPPED
|| result.getType() == MAPPED_TYPE_CONVERTED
|| (result.getType() == DIRECT && targetType.isPrimitive() ) ) {
// for primitive types null check is not possible at all, but a conversion needs
// a null check.
result = new NullCheckWrapper( result );
useLocalVarWhenNested( result );
}
}
return result;
}
private void useLocalVarWhenNested(Assignment rightHandSide) {
if ( sourceReference.getPropertyEntries().size() > 1 ) {
String name = first( sourceReference.getPropertyEntries() ).getName();
String safeName = Strings.getSaveVariableName( name, existingVariableNames );
existingVariableNames.add( safeName );
rightHandSide.setSourceLocalVarName( safeName );
NullValueCheckStrategyPrism nvcs = method.getMapperConfiguration().getNullValueCheckStrategy();
return new SetterWrapper( rhs, method.getThrownTypes(), nvcs, isFieldAssignment(), targetType );
}
}
@ -421,8 +370,7 @@ public class PropertyMapping extends ModelElement {
}
else {
// Possibly adding null to a target collection. So should be surrounded by an null check.
result = new SetterWrapper( result, method.getThrownTypes(), isFieldAssignment() );
result = new NullCheckWrapper( result );
result = new SetterWrapper( result, method.getThrownTypes(), ALWAYS, isFieldAssignment(), targetType );
}
return result;
}
@ -435,7 +383,7 @@ public class PropertyMapping extends ModelElement {
if ( targetAccessorType == TargetWriteAccessorType.SETTER ||
targetAccessorType == TargetWriteAccessorType.FIELD ) {
if ( result.isUpdateMethod() ) {
if ( result.isCallingUpdateMethod() ) {
// call to an update method
if ( targetReadAccessor == null ) {
ctx.getMessager().printMessage(
@ -449,8 +397,9 @@ public class PropertyMapping extends ModelElement {
result,
method.getThrownTypes(),
factoryMethod,
isFieldAssignment(),
targetType,
isFieldAssignment()
true
);
}
else {
@ -458,9 +407,8 @@ public class PropertyMapping extends ModelElement {
result = new SetterWrapperForCollectionsAndMaps(
result,
method.getThrownTypes(),
existingVariableNames,
targetType,
ALWAYS == method.getMapperConfiguration().getNullValueCheckStrategy(),
method.getMapperConfiguration().getNullValueCheckStrategy(),
ctx.getTypeFactory(),
targetWriteAccessorType == TargetWriteAccessorType.FIELD
);
@ -470,7 +418,6 @@ public class PropertyMapping extends ModelElement {
// target accessor is getter, so wrap the setter in getter map/ collection handling
result = new GetterWrapperForCollectionsAndMaps( result,
method.getThrownTypes(),
existingVariableNames,
targetType,
isFieldAssignment()
);
@ -560,6 +507,11 @@ public class PropertyMapping extends ModelElement {
existingVariableNames,
sourceReference.toString()
);
// create a local variable to which forged method can be assigned.
String desiredName = first( sourceReference.getPropertyEntries() ).getName();
sourceRhs.setSourceLocalVarName( sourceRhs.createLocalVarName( desiredName ) );
return sourceRhs;
}
@ -767,7 +719,7 @@ public class PropertyMapping extends ModelElement {
Executables.isFieldAccessor( targetWriteAccessor ) ) {
// target accessor is setter, so decorate assignment as setter
if ( assignment.isUpdateMethod() ) {
if ( assignment.isCallingUpdateMethod() ) {
if ( targetReadAccessor == null ) {
ctx.getMessager().printMessage(
method.getExecutable(),
@ -778,8 +730,7 @@ public class PropertyMapping extends ModelElement {
Assignment factoryMethod =
ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
assignment = new UpdateWrapper( assignment, method.getThrownTypes(), factoryMethod,
targetType, isFieldAssignment()
);
isFieldAssignment(), targetType, false );
}
else {
assignment = new SetterWrapper( assignment, method.getThrownTypes(), isFieldAssignment() );
@ -790,7 +741,6 @@ public class PropertyMapping extends ModelElement {
// target accessor is getter, so getter map/ collection handling
assignment = new GetterWrapperForCollectionsAndMaps( assignment,
method.getThrownTypes(),
existingVariableNames,
targetType,
isFieldAssignment()
);
@ -863,7 +813,6 @@ public class PropertyMapping extends ModelElement {
// target accessor is getter, so wrap the setter in getter map/ collection handling
assignment = new GetterWrapperForCollectionsAndMaps( assignment,
method.getThrownTypes(),
existingVariableNames,
targetType,
isFieldAssignment()
);

View File

@ -47,7 +47,7 @@ public class SourceRHS extends ModelElement implements Assignment {
public SourceRHS(String sourceReference, Type sourceType, Set<String> existingVariableNames,
String sourceErrorMessagePart ) {
this( null, sourceReference, null, sourceType, existingVariableNames, sourceErrorMessagePart );
this( sourceReference, sourceReference, null, sourceType, existingVariableNames, sourceErrorMessagePart );
}
public SourceRHS(String sourceParameterName, String sourceReference, String sourcePresenceCheckerReference,
@ -77,7 +77,9 @@ public class SourceRHS extends ModelElement implements Assignment {
@Override
public String createLocalVarName(String desiredName) {
return Strings.getSaveVariableName( desiredName, existingVariableNames );
String result = Strings.getSaveVariableName( desiredName, existingVariableNames );
existingVariableNames.add( result );
return result;
}
@Override
@ -111,7 +113,7 @@ public class SourceRHS extends ModelElement implements Assignment {
}
@Override
public boolean isUpdateMethod() {
public boolean isCallingUpdateMethod() {
return false;
}
@ -137,12 +139,13 @@ public class SourceRHS extends ModelElement implements Assignment {
/**
* For collection type, use element as source type to find a suitable mapping method.
*
* @param useElementAsSourceTypeForMatching
* @param useElementAsSourceTypeForMatching uses the element of a collection as source type for the matching process
*/
public void setUseElementAsSourceTypeForMatching(boolean useElementAsSourceTypeForMatching) {
this.useElementAsSourceTypeForMatching = useElementAsSourceTypeForMatching;
}
@Override
public String getSourceParameterName() {
return sourceParameterName;
}

View File

@ -111,6 +111,11 @@ public class TypeConversion extends ModelElement implements Assignment {
assignment.setSourceLocalVarName( sourceLocalVarName );
}
@Override
public String getSourceParameterName() {
return assignment.getSourceParameterName();
}
@Override
public void setAssignment( Assignment assignment ) {
this.assignment = assignment;
@ -130,7 +135,7 @@ public class TypeConversion extends ModelElement implements Assignment {
}
@Override
public boolean isUpdateMethod() {
public boolean isCallingUpdateMethod() {
return false;
}
}

View File

@ -33,14 +33,12 @@ import org.mapstruct.ap.internal.model.common.Type;
public class AdderWrapper extends AssignmentWrapper {
private final List<Type> thrownTypesToExclude;
private final String sourceIteratorName;
public AdderWrapper( Assignment decoratedAssignment, List<Type> thrownTypesToExclude, boolean fieldAssignment ) {
super( decoratedAssignment, fieldAssignment );
public AdderWrapper( Assignment rhs, List<Type> thrownTypesToExclude, boolean fieldAssignment ) {
super( rhs, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
String desiredName = decoratedAssignment.getSourceType().getTypeParameters().get( 0 ).getName();
this.sourceIteratorName = decoratedAssignment.createLocalVarName( desiredName );
decoratedAssignment.setSourceLocalVarName( sourceIteratorName );
String desiredName = rhs.getSourceType().getTypeParameters().get( 0 ).getName();
rhs.setSourceLocalVarName( rhs.createLocalVarName( desiredName ) );
}
@Override
@ -65,7 +63,4 @@ public class AdderWrapper extends AssignmentWrapper {
return imported;
}
public String getSourceIteratorName() {
return sourceIteratorName;
}
}

View File

@ -32,17 +32,34 @@ public interface Assignment {
enum AssignmentType {
/** assignment is direct */
DIRECT,
DIRECT( true, false ),
/** assignment is type converted */
TYPE_CONVERTED,
TYPE_CONVERTED( false, true ),
/** assignment is mapped (builtin/custom) */
MAPPED,
MAPPED( false, false ),
/** 2 mapping methods (builtin/custom) are applied to get the target */
MAPPED_TWICE,
MAPPED_TWICE( false, false ),
/** assignment is first mapped (builtin/custom), then the result is type converted */
MAPPED_TYPE_CONVERTED,
MAPPED_TYPE_CONVERTED( false, true ),
/** assignment is first type converted, and then mapped (builtin/custom) */
TYPE_CONVERTED_MAPPED
TYPE_CONVERTED_MAPPED( false, true );
private final boolean direct;
private final boolean converted;
AssignmentType( boolean isDirect, boolean isConverted ) {
this.direct = isDirect;
this.converted = isConverted;
}
public boolean isDirect() {
return direct;
}
public boolean isConverted() {
return converted;
}
}
/**
@ -106,6 +123,14 @@ public interface Assignment {
*/
String getSourceLocalVarName();
/**
* Returns the source parameter name, to which this assignment applies. Note: the source parameter itself might
* be mapped by this assignment, or one of its properties
*
* @return the source parameter name
*/
String getSourceParameterName();
/**
* Use sourceLocalVarName iso sourceReference
* @param sourceLocalVarName source local variable name
@ -119,5 +144,5 @@ public interface Assignment {
*/
AssignmentType getType();
boolean isUpdateMethod();
boolean isCallingUpdateMethod();
}

View File

@ -83,14 +83,19 @@ public abstract class AssignmentWrapper extends ModelElement implements Assignme
decoratedAssignment.setSourceLocalVarName( sourceLocalVarName );
}
@Override
public String getSourceParameterName() {
return decoratedAssignment.getSourceParameterName();
}
@Override
public AssignmentType getType() {
return decoratedAssignment.getType();
}
@Override
public boolean isUpdateMethod() {
return decoratedAssignment.isUpdateMethod();
public boolean isCallingUpdateMethod() {
return decoratedAssignment.isCallingUpdateMethod();
}
@Override

View File

@ -19,7 +19,6 @@
package org.mapstruct.ap.internal.model.assignment;
import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.common.Type;
@ -39,22 +38,19 @@ import org.mapstruct.ap.internal.model.common.Type;
public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAndMaps {
/**
* @param decoratedAssignment
* @param thrownTypesToExclude
* @param existingVariableNames
* @param targetType
* @param fieldAssignment
* @param decoratedAssignment source RHS
* @param thrownTypesToExclude set of types to exclude from re-throwing
* @param targetType the target type
* @param fieldAssignment true when this the assignment is to a field rather than via accessors
*/
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
List<Type> thrownTypesToExclude,
Set<String> existingVariableNames,
Type targetType,
boolean fieldAssignment) {
super(
decoratedAssignment,
thrownTypesToExclude,
existingVariableNames,
targetType,
fieldAssignment
);

View File

@ -22,6 +22,9 @@ import java.util.ArrayList;
import java.util.List;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS;
/**
* Wraps the assignment in a target setter.
@ -31,10 +34,23 @@ import org.mapstruct.ap.internal.model.common.Type;
public class SetterWrapper extends AssignmentWrapper {
private final List<Type> thrownTypesToExclude;
private final boolean includeSourceNullCheck;
public SetterWrapper(Assignment decoratedAssignment, List<Type> thrownTypesToExclude, boolean fieldAssignment) {
super( decoratedAssignment, fieldAssignment );
public SetterWrapper(Assignment rhs,
List<Type> thrownTypesToExclude,
NullValueCheckStrategyPrism nvms,
boolean fieldAssignment,
Type targetType) {
super( rhs, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
this.includeSourceNullCheck = includeSourceNullCheck( rhs, nvms, targetType );
}
public SetterWrapper(Assignment rhs, List<Type> thrownTypesToExclude, boolean fieldAssignment ) {
super( rhs, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
this.includeSourceNullCheck = false;
}
@Override
@ -51,4 +67,30 @@ public class SetterWrapper extends AssignmentWrapper {
return result;
}
public boolean isIncludeSourceNullCheck() {
return includeSourceNullCheck;
}
/**
* Wraps the assignment in a target setter. include a null check when
*
* - Not if source is the parameter iso property, because the null check is than handled by the bean mapping
* - Not when source is primitive, you can't null check a primitive
* - The source property is fed to a conversion somehow before its assigned to the target
* - The user decided to ALLWAYS include a null check
* - When there's a source local variable name defined (e.g. nested source properties)
* - TODO: The last one I forgot..?
*
* @param rhs the source righthand side
* @param nvms null value check strategy
* @param targetType the target type
*
* @return include a null check
*/
private boolean includeSourceNullCheck(Assignment rhs, NullValueCheckStrategyPrism nvms, Type targetType) {
return !rhs.getSourceReference().equals( rhs.getSourceParameterName() )
&& !rhs.getSourceType().isPrimitive()
&& (ALWAYS == nvms || rhs.getType().isConverted() || rhs.getSourceLocalVarName() != null
|| (rhs.getType().isDirect() && targetType.isPrimitive()));
}
}

View File

@ -26,6 +26,9 @@ import java.util.Set;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism.ALWAYS;
/**
* This wrapper handles the situation were an assignment is done via the setter.
@ -41,26 +44,24 @@ import org.mapstruct.ap.internal.model.common.TypeFactory;
*/
public class SetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAndMaps {
private final boolean allwaysIncludeNullCheck;
private final boolean includeSourceNullCheck;
private final Type targetType;
private final TypeFactory typeFactory;
public SetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
List<Type> thrownTypesToExclude,
Set<String> existingVariableNames,
Type targetType,
boolean allwaysIncludeNullCheck,
NullValueCheckStrategyPrism nvms,
TypeFactory typeFactory,
boolean fieldAssignment) {
super(
decoratedAssignment,
thrownTypesToExclude,
existingVariableNames,
targetType,
fieldAssignment
);
this.allwaysIncludeNullCheck = allwaysIncludeNullCheck;
this.includeSourceNullCheck = ALWAYS == nvms;
this.targetType = targetType;
this.typeFactory = typeFactory;
}
@ -83,8 +84,8 @@ public class SetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAnd
return imported;
}
public boolean isAllwaysIncludeNullCheck() {
return allwaysIncludeNullCheck;
public boolean isIncludeSourceNullCheck() {
return includeSourceNullCheck;
}
public boolean isDirectAssignment() {

View File

@ -35,13 +35,19 @@ public class UpdateWrapper extends AssignmentWrapper {
private final List<Type> thrownTypesToExclude;
private final Assignment factoryMethod;
private final Type targetImplementationType;
private final boolean includeSourceNullCheck;
public UpdateWrapper(Assignment decoratedAssignment, List<Type> thrownTypesToExclude, Assignment factoryMethod,
Type targetImplementationType, boolean fieldAssignment ) {
public UpdateWrapper( Assignment decoratedAssignment,
List<Type> thrownTypesToExclude,
Assignment factoryMethod,
boolean fieldAssignment,
Type targetType,
boolean includeSourceNullCheck ) {
super( decoratedAssignment, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
this.factoryMethod = factoryMethod;
this.targetImplementationType = determineImplType( factoryMethod, targetImplementationType );
this.targetImplementationType = determineImplType( factoryMethod, targetType );
this.includeSourceNullCheck = includeSourceNullCheck;
}
private static Type determineImplType(Assignment factoryMethod, Type targetType) {
@ -87,4 +93,7 @@ public class UpdateWrapper extends AssignmentWrapper {
return factoryMethod;
}
public boolean isIncludeSourceNullCheck() {
return includeSourceNullCheck;
}
}

View File

@ -24,7 +24,6 @@ import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.util.Strings;
/**
* This is the base class for the {@link GetterWrapperForCollectionsAndMaps} and
@ -35,26 +34,24 @@ import org.mapstruct.ap.internal.util.Strings;
public class WrapperForCollectionsAndMaps extends AssignmentWrapper {
private final List<Type> thrownTypesToExclude;
private final String localVarName;
private final Type localVarType;
private final String nullCheckLocalVarName;
private final Type nullCheckLocalVarType;
public WrapperForCollectionsAndMaps(Assignment decoratedAssignment,
public WrapperForCollectionsAndMaps(Assignment rhs,
List<Type> thrownTypesToExclude,
Set<String> existingVariableNames,
Type targetType,
boolean fieldAssignment) {
super( decoratedAssignment, fieldAssignment );
super( rhs, fieldAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
if ( getType() == AssignmentType.DIRECT && getSourceType() != null ) {
this.localVarType = getSourceType();
if ( rhs.getType() == AssignmentType.DIRECT && rhs.getSourceType() != null ) {
this.nullCheckLocalVarType = rhs.getSourceType();
}
else {
this.localVarType = targetType;
this.nullCheckLocalVarType = targetType;
}
this.localVarName = Strings.getSaveVariableName( localVarType.getName(), existingVariableNames );
existingVariableNames.add( this.localVarName );
this.nullCheckLocalVarName = rhs.createLocalVarName( nullCheckLocalVarType.getName() );
}
@Override
@ -75,16 +72,16 @@ public class WrapperForCollectionsAndMaps extends AssignmentWrapper {
public Set<Type> getImportTypes() {
Set<Type> imported = new HashSet<Type>();
imported.addAll( super.getImportTypes() );
imported.add( localVarType );
imported.addAll( localVarType.getTypeParameters() );
imported.add( nullCheckLocalVarType );
imported.addAll( nullCheckLocalVarType.getTypeParameters() );
return imported;
}
public String getLocalVarName() {
return localVarName;
public String getNullCheckLocalVarName() {
return nullCheckLocalVarName;
}
public Type getLocalVarType() {
return localVarType;
public Type getNullCheckLocalVarType() {
return nullCheckLocalVarType;
}
}

View File

@ -21,7 +21,7 @@
<#import "../macro/CommonMacros.ftl" as lib>
<@lib.handleExceptions>
if ( ${sourceReference} != null ) {
for ( <@includeModel object=sourceType.typeParameters[0]/> ${sourceIteratorName} : ${sourceReference} ) {
for ( <@includeModel object=sourceType.typeParameters[0]/> ${sourceLocalVarName} : ${sourceReference} ) {
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><@lib.handleAssignment/></@lib.handleWrite>;
}
}

View File

@ -19,13 +19,14 @@
-->
<#import "../macro/CommonMacros.ftl" as lib>
<@lib.sourceLocalVarAssignment/>
if ( ${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing /> != null ) {
<@lib.handleExceptions>
<#if ext.existingInstanceMapping>
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.clear();
</#if>
<@lib.handleNullCheck>
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( ${localVarName} );
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( ${nullCheckLocalVarName} );
</@lib.handleNullCheck>
</@lib.handleExceptions>
}

View File

@ -19,44 +19,33 @@
-->
<#import "../macro/CommonMacros.ftl" as lib>
<#if (thrownTypes?size == 0) >
<@assignment_w_defaultValue/>
<#else>
try {
<@assignment_w_defaultValue/>
}
<#list thrownTypes as exceptionType>
catch ( <@includeModel object=exceptionType/> e ) {
throw new RuntimeException( e );
}
</#list>
</#if>
<#macro _assignment>
<@includeModel object=assignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType
defaultValueAssignment=ext.defaultValueAssignment/>
</#macro>
<#macro _defaultValueAssignment>
<@includeModel object=ext.defaultValueAssignment.assignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
</#macro>
<#macro assignment_w_defaultValue>
<#if ext.defaultValueAssignment?? >
<#-- if the assignee property is a primitive, defaulValueAssignment will not be set -->
if ( ${sourceReference} != null ) {
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><@_assignment/></@lib.handleWrite>;
<@lib.handleExceptions>
<@lib.sourceLocalVarAssignment/>
<#if sourcePresenceCheckerReference??>
if ( ${sourcePresenceCheckerReference} ) {
<@assignment/>;
}
else {
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><@_defaultValueAssignment/></@lib.handleWrite>;
<@elseDefaultAssignment/>
<#elseif includeSourceNullCheck || ext.defaultValueAssignment??>
if ( <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference}</#if> != null ) {
<@assignment/>;
}
<@elseDefaultAssignment/>
<#else>
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><@_assignment/></@lib.handleWrite>;
<@assignment/>;
</#if>
</#macro>
</@lib.handleExceptions>
<#--
standard assignment
-->
<#macro assignment>${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><@lib.handleAssignment/></@lib.handleWrite></#macro>
<#--
add default assignment when required
-->
<#macro elseDefaultAssignment>
<#if ext.defaultValueAssignment?? >
else {
<@lib.handeDefaultAssigment/>
}
</#if>
</#macro>

View File

@ -19,14 +19,15 @@
-->
<#import "../macro/CommonMacros.ftl" as lib>
<@lib.sourceLocalVarAssignment/>
<@lib.handleExceptions>
<#if ext.existingInstanceMapping>
if ( ${ext.targetBeanName}.${ext.targetReadAccessorName} != null ) {
<@lib.handleNullCheck>
${ext.targetBeanName}.${ext.targetReadAccessorName}.clear();
${ext.targetBeanName}.${ext.targetReadAccessorName}.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( ${localVarName} );
${ext.targetBeanName}.${ext.targetReadAccessorName}.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( ${nullCheckLocalVarName} );
</@lib.handleNullCheck>
<#if !ext.defaultValueAssignment?? && !sourcePresenceCheckerReference?? && !allwaysIncludeNullCheck>else {<#-- the opposite (defaultValueAssignment) case is handeld inside lib.handleNullCheck -->
<#if !ext.defaultValueAssignment?? && !sourcePresenceCheckerReference?? && !includeSourceNullCheck>else {<#-- the opposite (defaultValueAssignment) case is handeld inside lib.handleNullCheck -->
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite>null</@lib.handleWrite>;
}
</#if>
@ -43,7 +44,7 @@
-->
<#macro callTargetWriteAccessor>
<@lib.handleNullCheck>
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if directAssignment><@wrapLocalVarInCollectionInitializer/><#else>${localVarName}</#if></@lib.handleWrite>;
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if directAssignment><@wrapLocalVarInCollectionInitializer/><#else>${nullCheckLocalVarName}</#if></@lib.handleWrite>;
</@lib.handleNullCheck>
</#macro>
<#--
@ -51,8 +52,8 @@
-->
<#macro wrapLocalVarInCollectionInitializer><@compress single_line=true>
<#if enumSet>
EnumSet.copyOf( ${localVarName} )
EnumSet.copyOf( ${nullCheckLocalVarName} )
<#else>
new <#if ext.targetType.implementationType??><@includeModel object=ext.targetType.implementationType/><#else><@includeModel object=ext.targetType/></#if>( ${localVarName} )
new <#if ext.targetType.implementationType??><@includeModel object=ext.targetType.implementationType/><#else><@includeModel object=ext.targetType/></#if>( ${nullCheckLocalVarName} )
</#if>
</@compress></#macro>

View File

@ -19,28 +19,25 @@
-->
<#import '../macro/CommonMacros.ftl' as lib >
<#if (thrownTypes?size == 0) >
<@_assignment/>;
<#else>
try {
<@_assignment/>;
<@lib.handleExceptions>
<#if includeSourceNullCheck>
if ( <#if sourcePresenceCheckerReference?? >${sourcePresenceCheckerReference}<#else>${sourceReference} != null</#if> ) {
<@assignToExistingTarget/>
<@lib.handleAssignment/>;
}
<#list thrownTypes as exceptionType>
catch ( <@includeModel object=exceptionType/> e ) {
throw new RuntimeException( e );
else {
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite>null</@lib.handleWrite>;
}
</#list>
</#if>
<#macro _assignment>
<#else>
<@assignToExistingTarget/>
<@lib.handleAssignment/>;
</#if>
</@lib.handleExceptions>
<#--
target innner check and assignment
-->
<#macro assignToExistingTarget>
if ( ${ext.targetBeanName}.${ext.targetReadAccessorName} == null ) {
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if factoryMethod??><@includeModel object=factoryMethod targetType=ext.targetType/><#else><@_newObject/></#if></@lib.handleWrite>;
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><@lib.initTargetObject/></@lib.handleWrite>;
}
<@includeModel object=assignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
</#macro>
<#macro _newObject>new <#if ext.targetType.implementationType??><@includeModel object=ext.targetType.implementationType/><#else><@includeModel object=ext.targetType/></#if>()</#macro>

View File

@ -30,18 +30,18 @@
<#macro handleNullCheck>
<#if sourcePresenceCheckerReference??>
if ( ${sourcePresenceCheckerReference} ) {
<@includeModel object=localVarType/> ${localVarName} = <@lib.handleAssignment/>;
<@includeModel object=nullCheckLocalVarType/> ${nullCheckLocalVarName} = <@lib.handleAssignment/>;
<#nested>
}
<#else>
<@includeModel object=localVarType/> ${localVarName} = <@lib.handleAssignment/>;
if ( ${localVarName} != null ) {
<@includeModel object=nullCheckLocalVarType/> ${nullCheckLocalVarName} = <@lib.handleAssignment/>;
if ( ${nullCheckLocalVarName} != null ) {
<#nested>
}
</#if>
<#if ext.defaultValueAssignment?? >
else {
<@lib.handeDefaultAssigment/>
<@handeDefaultAssigment/>
}
</#if>
</#macro>
@ -104,4 +104,38 @@ Performs a default assignment with a default value.
-->
<#macro handleWriteAccesing>
<#t><#if fieldAssignment><#else>()</#if>
</#macro>
</#macro>
<#--
macro: initTargetObject
purpose: To factorize or construct a new target object
-->
<#macro initTargetObject><@compress single_line=true>
<#if factoryMethod??>
<@includeModel object=factoryMethod targetType=ext.targetType/>
<#else>
new <@constructTargetObject/>()
</#if>
</@compress></#macro>
<#--
macro: constructTargetObject
purpose: Either call the constructor of the target object directly or of the implementing type.
-->
<#macro constructTargetObject><@compress single_line=true>
<#if ext.targetType.implementationType??>
<@includeModel object=ext.targetType.implementationType/>
<#else>
<@includeModel object=ext.targetType/>
</#if>
</@compress></#macro>
<#--
macro: sourceLocalVarAssignment
purpose: assigment for source local variables
-->
<#macro sourceLocalVarAssignment>
<#if sourceLocalVarName??>
<@includeModel object=sourceType/> ${sourceLocalVarName} = ${sourceReference};
</#if>
</#macro>