#913 New property mapping collection handling

This commit is contained in:
sjaakd 2016-10-04 20:59:13 +02:00
parent 52f48fe1da
commit 1fa0c4aa3b
28 changed files with 1410 additions and 179 deletions

View File

@ -321,7 +321,7 @@ public class IterableMappingMethod extends MappingMethod {
return false;
}
return true;
return isMapNullToDefault() == other.isMapNullToDefault();
}
}

View File

@ -325,7 +325,7 @@ public class MapMappingMethod extends MappingMethod {
}
}
return true;
return isMapNullToDefault() == other.isMapNullToDefault();
}
}

View File

@ -19,7 +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;
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;
@ -38,7 +37,6 @@ import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.assignment.EnumConstantWrapper;
import org.mapstruct.ap.internal.model.assignment.EnumSetCopyWrapper;
import org.mapstruct.ap.internal.model.assignment.GetterWrapperForCollectionsAndMaps;
import org.mapstruct.ap.internal.model.assignment.LocalVarWrapper;
import org.mapstruct.ap.internal.model.assignment.NewCollectionOrMapWrapper;
import org.mapstruct.ap.internal.model.assignment.NullCheckWrapper;
import org.mapstruct.ap.internal.model.assignment.SetterWrapper;
@ -416,8 +414,7 @@ public class PropertyMapping extends ModelElement {
return result;
}
private Assignment assignToCollection(Type targetType,
TargetWriteAccessorType targetAccessorType,
private Assignment assignToCollection(Type targetType, TargetWriteAccessorType targetAccessorType,
Assignment rhs) {
Assignment result = rhs;
@ -457,46 +454,25 @@ public class PropertyMapping extends ModelElement {
targetType );
}
else {
if ( method.isUpdateMethod() ) {
// if the calling method is an update method and accesses a getter, make a local variable to
// test NPE first.
result = new LocalVarWrapper( result, method.getThrownTypes(), targetType );
}
else {
// if not, asssign as new collecitin or direct
result = new SetterWrapper( result, method.getThrownTypes() );
}
// target accessor is setter, so wrap the setter in setter map/ collection handling
result = new SetterWrapperForCollectionsAndMaps(
result,
targetReadAccessor.getSimpleName().toString(),
newCollectionOrMap,
targetType,
existingVariableNames
method.getThrownTypes(),
getSourcePresenceCheckerRef(),
existingVariableNames,
targetType
);
}
}
else {
// target accessor is getter, so wrap the setter in getter map/ collection handling
result = new GetterWrapperForCollectionsAndMaps(
result,
method.getThrownTypes(),
ctx.getTypeFactory().asCollectionOrMap( targetType ),
existingVariableNames
);
}
// For collections and maps include a null check, when the assignment type is DIRECT.
// for mapping methods (builtin / custom), the mapping method is responsible for the
// null check. Typeconversions do not apply to collections and maps.
if ( result.getType() == DIRECT ) {
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
}
else if ( result.getType() == MAPPED && result.isUpdateMethod() ) {
result = new UpdateNullCheckWrapper( result, getSourcePresenceCheckerRef() );
result = new GetterWrapperForCollectionsAndMaps( result,
method.getThrownTypes(),
getSourcePresenceCheckerRef(),
existingVariableNames,
targetType);
}
return result;
@ -623,7 +599,6 @@ public class PropertyMapping extends ModelElement {
ExecutableElement element) {
Assignment assignment = null;
String name = getName( sourceType, targetType );
name = Strings.getSaveVariableName( name, ctx.getNamesOfMappingsToGenerate() );
@ -687,7 +662,7 @@ public class PropertyMapping extends ModelElement {
return assignment;
}
private String getName(Type sourceType, Type targetType) {
private String getName(Type sourceType, Type targetType ) {
String fromName = getName( sourceType );
String toName = getName( targetType );
return Strings.decapitalize( fromName + "To" + toName );
@ -701,6 +676,7 @@ public class PropertyMapping extends ModelElement {
builder.append( type.getIdentification() );
return builder.toString();
}
}
public static class ConstantMappingBuilder extends MappingBuilderBase<ConstantMappingBuilder> {
@ -770,12 +746,10 @@ public class PropertyMapping extends ModelElement {
else {
// target accessor is getter, so getter map/ collection handling
assignment = new GetterWrapperForCollectionsAndMaps(
assignment,
method.getThrownTypes(),
ctx.getTypeFactory().asCollectionOrMap( targetType ),
existingVariableNames
);
assignment = new GetterWrapperForCollectionsAndMaps( assignment,
method.getThrownTypes(),
existingVariableNames,
targetType);
}
}
else {
@ -840,12 +814,10 @@ public class PropertyMapping extends ModelElement {
}
else {
// target accessor is getter, so wrap the setter in getter map/ collection handling
assignment = new GetterWrapperForCollectionsAndMaps(
assignment,
method.getThrownTypes(),
ctx.getTypeFactory().asCollectionOrMap( targetType ),
existingVariableNames
);
assignment = new GetterWrapperForCollectionsAndMaps( assignment,
method.getThrownTypes(),
existingVariableNames,
targetType);
}
return new PropertyMapping(
@ -859,6 +831,7 @@ public class PropertyMapping extends ModelElement {
null
);
}
}
// Constructor for creating mappings of constant expressions.

View File

@ -123,5 +123,4 @@ public class TypeConversion extends ModelElement implements Assignment {
public boolean isUpdateMethod() {
return false;
}
}

View File

@ -106,4 +106,5 @@ public interface Assignment {
boolean isUpdateMethod();
}

View File

@ -85,4 +85,5 @@ public abstract class AssignmentWrapper extends ModelElement implements Assignme
public boolean isUpdateMethod() {
return decoratedAssignment.isUpdateMethod();
}
}

View File

@ -18,14 +18,10 @@
*/
package org.mapstruct.ap.internal.model.assignment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.util.Strings;
/**
* This wrapper handles the situation were an assignment must be done via a target getter method because there
@ -40,54 +36,39 @@ import org.mapstruct.ap.internal.util.Strings;
*
* @author Sjaak Derksen
*/
public class GetterWrapperForCollectionsAndMaps extends AssignmentWrapper {
public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAndMaps {
private final List<Type> thrownTypesToExclude;
private final Type localVarType;
private final String localVarName;
/**
* constructor for property mapping
*
* @param decoratedAssignment
* @param thrownTypesToExclude
* @param sourcePresenceChecker
* @param existingVariableNames
* @param targetType
*/
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
List<Type> thrownTypesToExclude,
String sourcePresenceChecker,
Set<String> existingVariableNames,
Type targetType ) {
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment, List<Type> thrownTypesToExclude,
Type localVarType, Collection<String> existingVariableNames) {
super( decoratedAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
this.localVarType = localVarType;
this.localVarName = Strings.getSaveVariableName( "target" + localVarType.getName(), existingVariableNames );
existingVariableNames.add( localVarName );
}
@Override
public List<Type> getThrownTypes() {
List<Type> parentThrownTypes = super.getThrownTypes();
List<Type> result = new ArrayList<Type>( parentThrownTypes );
for ( Type thrownTypeToExclude : thrownTypesToExclude ) {
for ( Type parentThrownType : parentThrownTypes ) {
if ( parentThrownType.isAssignableTo( thrownTypeToExclude ) ) {
result.remove( parentThrownType );
}
}
}
return result;
}
@Override
public Set<Type> getImportTypes() {
Set<Type> imported = new HashSet<Type>();
imported.addAll( super.getImportTypes() );
imported.add( localVarType ); /* is a local var */
imported.addAll( localVarType.getTypeParameters() );
return imported;
super( decoratedAssignment, thrownTypesToExclude, sourcePresenceChecker, existingVariableNames, targetType );
}
/**
* @return the targetType
* constructor for e.g. constants and expressions
*
* @param decoratedAssignment
* @param thrownTypesToExclude
* @param existingVariableNames
* @param targetType
*/
public Type getLocalVarType() {
return localVarType;
}
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
List<Type> thrownTypesToExclude,
Set<String> existingVariableNames,
Type targetType ) {
public String getLocalVarName() {
return localVarName;
super( decoratedAssignment, thrownTypesToExclude, null, existingVariableNames, targetType );
}
}

View File

@ -18,12 +18,10 @@
*/
package org.mapstruct.ap.internal.model.assignment;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.util.Strings;
/**
* This wrapper handles the situation were an assignment is done via the setter.
@ -37,45 +35,33 @@ import org.mapstruct.ap.internal.util.Strings;
*
* @author Sjaak Derksen
*/
public class SetterWrapperForCollectionsAndMaps extends AssignmentWrapper {
public class SetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAndMaps {
private final String targetGetterName;
private final Assignment newCollectionOrMapAssignment;
private final String localVarName;
public SetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
String targetGetterName,
Assignment newCollectionOrMapAssignment,
Type targetType,
Collection<String> existingVariableNames) {
super( decoratedAssignment );
List<Type> thrownTypesToExclude,
String sourcePresenceChecker,
Set<String> existingVariableNames,
Type targetType ) {
this.targetGetterName = targetGetterName;
super( decoratedAssignment, thrownTypesToExclude, sourcePresenceChecker, existingVariableNames, targetType );
this.newCollectionOrMapAssignment = newCollectionOrMapAssignment;
this.localVarName = Strings.getSaveVariableName( targetType.getName(), existingVariableNames );
existingVariableNames.add( localVarName );
}
public String getTargetGetterName() {
return targetGetterName;
}
public Assignment getNewCollectionOrMapAssignment() {
return newCollectionOrMapAssignment;
}
@Override
public Set<Type> getImportTypes() {
Set<Type> imported = new HashSet<Type>();
imported.addAll( getAssignment().getImportTypes() );
Set<Type> imported = super.getImportTypes();
if ( newCollectionOrMapAssignment != null ) {
imported.addAll( newCollectionOrMapAssignment.getImportTypes() );
}
return imported;
}
public String getLocalVarName() {
return localVarName;
public Assignment getNewCollectionOrMapAssignment() {
return newCollectionOrMapAssignment;
}
}

View File

@ -0,0 +1,96 @@
/**
* Copyright 2012-2016 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.assignment;
import java.util.ArrayList;
import java.util.HashSet;
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
* {@link SetterWrapperForCollectionsAndMaps}
*
* @author Sjaak Derksen
*/
public class WrapperForCollectionsAndMaps extends AssignmentWrapper {
private final List<Type> thrownTypesToExclude;
private final String sourcePresenceChecker;
private final String localVarName;
private final Type localVarType;
public WrapperForCollectionsAndMaps(Assignment decoratedAssignment,
List<Type> thrownTypesToExclude,
String sourcePresenceChecker,
Set<String> existingVariableNames,
Type targetType ) {
super( decoratedAssignment );
this.thrownTypesToExclude = thrownTypesToExclude;
this.sourcePresenceChecker = sourcePresenceChecker;
if ( getType() == AssignmentType.DIRECT && getSourceType() != null ) {
this.localVarType = getSourceType();
}
else {
this.localVarType = targetType;
}
this.localVarName = Strings.getSaveVariableName( localVarType.getName(), existingVariableNames );
existingVariableNames.add( this.localVarName );
}
@Override
public List<Type> getThrownTypes() {
List<Type> parentThrownTypes = super.getThrownTypes();
List<Type> result = new ArrayList<Type>( parentThrownTypes );
for ( Type thrownTypeToExclude : thrownTypesToExclude ) {
for ( Type parentThrownType : parentThrownTypes ) {
if ( parentThrownType.isAssignableTo( thrownTypeToExclude ) ) {
result.remove( parentThrownType );
}
}
}
return result;
}
@Override
public Set<Type> getImportTypes() {
Set<Type> imported = new HashSet<Type>();
imported.addAll( super.getImportTypes() );
imported.add( localVarType );
imported.addAll( localVarType.getTypeParameters() );
return imported;
}
public String getSourcePresenceChecker() {
return sourcePresenceChecker;
}
public String getLocalVarName() {
return localVarName;
}
public Type getLocalVarType() {
return localVarType;
}
}

View File

@ -18,34 +18,14 @@
limitations under the License.
-->
<#import "../macro/CommonMacros.ftl" as lib>
if ( ${ext.targetBeanName}.${ext.targetWriteAccessorName}() != null ) {
<#if ext.existingInstanceMapping>
<@lib.handleExceptions>
<#if ext.existingInstanceMapping>
${ext.targetBeanName}.${ext.targetWriteAccessorName}().clear();
</#if>
<#if (thrownTypes?size == 0) >
<@_assignmentLine/>
<#else>
try {
<@_assignmentLine/>
}
<#list thrownTypes as exceptionType>
catch ( <@includeModel object=exceptionType/> e ) {
throw new RuntimeException( e );
}
</#list>
</#if>
}
<#macro _assignmentLine>
<@includeModel object=localVarType/> ${localVarName} = <@_assignment/>;
if ( ${localVarName} != null ) {
</#if>
<@lib.handleNullCheck>
${ext.targetBeanName}.${ext.targetWriteAccessorName}().<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( ${localVarName} );
}
</#macro>
<#macro _assignment>
<@includeModel object=assignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
</#macro>
</@lib.handleNullCheck>
</@lib.handleExceptions>
}

View File

@ -18,36 +18,40 @@
limitations under the License.
-->
<#import "../macro/CommonMacros.ftl" as lib>
<@lib.handleExceptions>
<#if ( ext.existingInstanceMapping ) >
<@_assignment targetWriteAccessorName = localVarName/>
if ( ${ext.targetBeanName}.${targetGetterName}() != null ) {
${ext.targetBeanName}.${targetGetterName}().clear();
if ( ${localVarName} != null ) {
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} );
</@lib.handleNullCheck>
<#if !ext.defaultValueAssignment??> <#-- the opposite (defaultValueAssignment) case is handeld inside lib.handleNullCheck -->
else {
${ext.targetBeanName}.${ext.targetWriteAccessorName}( null );
}
}
else {
<#if newCollectionOrMapAssignment??>
<@_newCollectionOrMapAssignment/>
<#else>
${ext.targetBeanName}.${ext.targetWriteAccessorName}( ${localVarName} );
</#if>
}
else {
<@lib.handleNullCheck>
<#if newCollectionOrMapAssignment??>
<@_newCollectionOrMapAssignment/>
<#else>
${ext.targetBeanName}.${ext.targetWriteAccessorName}( ${localVarName} );
</#if>
</@lib.handleNullCheck>
}
<#else>
<#if newCollectionOrMapAssignment??>
<@_newCollectionOrMapAssignment/>
<#else>
<@_assignment targetWriteAccessorName = ext.targetWriteAccessorName/>
</#if>
<@lib.handleNullCheck>
<#if newCollectionOrMapAssignment??>
<@_newCollectionOrMapAssignment/>
<#else>
${ext.targetBeanName}.${ext.targetWriteAccessorName}( ${localVarName} );
</#if>
</@lib.handleNullCheck>
</#if>
<#macro _assignment targetWriteAccessorName>
<@includeModel object=assignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=targetWriteAccessorName
targetType=ext.targetType/>
</#macro>
</@lib.handleExceptions>
<#macro _newCollectionOrMapAssignment>
<@includeModel object=newCollectionOrMapAssignment
targetBeanName=ext.targetBeanName

View File

@ -0,0 +1,90 @@
<#--
Copyright 2012-2016 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.
-->
<#--
macro: handleNullCheck
purpose: macro surrounds nested with either a source presence checker or a null check. It always uses
a local variable. Note that the local variable assignemnt is inside the IF statement for the
source presence check. Note also, that the else clause contains the default variable assignment if
present.
-->
<#macro handleNullCheck>
<#if sourcePresenceChecker??>
if ( ${sourcePresenceChecker} ) {
<@includeModel object=localVarType/> ${localVarName} = <@lib.handleAssignment/>;
<#nested>
}
<#else>
<@includeModel object=localVarType/> ${localVarName} = <@lib.handleAssignment/>;
if ( ${localVarName} != null ) {
<#nested>
}
</#if>
<#if ext.defaultValueAssignment?? >
else {
<@lib.handeDefaultAssigment/>
}
</#if>
</#macro>
<#--
macro: handleExceptions
purpose: Includes the try - catch clauses around the nested code.
-->
<#macro handleExceptions>
<#if (thrownTypes?size == 0) >
<#nested>
<#else>
try {
<#nested>
}
<#list thrownTypes as exceptionType>
catch ( <@includeModel object=exceptionType/> e ) {
throw new RuntimeException( e );
}
</#list>
</#if>
</#macro>
<#--
Performs a standard assignment.
-->
<#macro handleAssignment>
<@includeModel object=assignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType/>
</#macro>
<#--
Performs a default assignment with a default value.
-->
<#macro handeDefaultAssigment>
<@includeModel object=ext.defaultValueAssignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=ext.targetWriteAccessorName
targetType=ext.targetType
defaultValue=ext.defaultValue/>
</#macro>

View File

@ -35,7 +35,4 @@ public interface Issue289Mapper {
TargetElement sourceElementToTargetElement(SourceElement source);
}

View File

@ -68,7 +68,6 @@ public class Issue289Test {
assertThat( target.getCollection() ).isEmpty();
}
@Test
public void shouldLeaveNullTargetSetWhenSourceIsNullForCreateMethod() {

View File

@ -0,0 +1,76 @@
/**
* Copyright 2012-2016 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.bugs._913;
import java.util.List;
import java.util.Set;
/**
*
* @author Sjaak Derksen
*/
public class Domain {
private Set<String> strings;
private Set<Long> longs;
private Set<String> stringsInitialized;
private Set<Long> longsInitialized;
private List<String> stringsWithDefault;
public Set<String> getStrings() {
return strings;
}
public void setStrings(Set<String> strings) {
this.strings = strings;
}
public Set<Long> getLongs() {
return longs;
}
public void setLongs(Set<Long> longs) {
this.longs = longs;
}
public Set<String> getStringsInitialized() {
return stringsInitialized;
}
public void setStringsInitialized(Set<String> stringsInitialized) {
this.stringsInitialized = stringsInitialized;
}
public Set<Long> getLongsInitialized() {
return longsInitialized;
}
public void setLongsInitialized(Set<Long> longsInitialized) {
this.longsInitialized = longsInitialized;
}
public List<String> getStringsWithDefault() {
return stringsWithDefault;
}
public void setStringsWithDefault(List<String> stringsWithDefault) {
this.stringsWithDefault = stringsWithDefault;
}
}

View File

@ -0,0 +1,52 @@
/**
* Copyright 2012-2016 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.bugs._913;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.NullValueMappingStrategy;
import org.mapstruct.factory.Mappers;
/**
*
* @author Sjaak Derksen
*/
@Mapper( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, uses = Helper.class )
public interface DomainDtoWithNvmsDefaultMapper {
DomainDtoWithNvmsDefaultMapper INSTANCE = Mappers.getMapper( DomainDtoWithNvmsDefaultMapper.class );
@Mappings({
@Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"),
@Mapping(target = "stringsInitialized", source = "stringsInitialized"),
@Mapping(target = "longsInitialized", source = "stringsInitialized"),
@Mapping(target = "stringsWithDefault", source = "stringsWithDefault", defaultValue = "3")
})
Domain create(Dto source);
@InheritConfiguration( name = "create" )
void update(Dto source, @MappingTarget Domain target);
@InheritConfiguration( name = "create" )
Domain updateWithReturn(Dto source, @MappingTarget Domain target);
}

View File

@ -0,0 +1,52 @@
/**
* Copyright 2012-2016 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.bugs._913;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
/**
*
* @author Sjaak Derksen
*/
@Mapper(uses = Helper.class)
// this is the default nvms, so no need to define
public interface DomainDtoWithNvmsNullMapper {
DomainDtoWithNvmsNullMapper INSTANCE = Mappers.getMapper( DomainDtoWithNvmsNullMapper.class );
@Mappings({
@Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"),
@Mapping(target = "stringsInitialized", source = "stringsInitialized"),
@Mapping(target = "longsInitialized", source = "stringsInitialized"),
@Mapping(target = "stringsWithDefault", source = "stringsWithDefault", defaultValue = "3")
})
Domain create(Dto source);
@InheritConfiguration( name = "create" )
void update(Dto source, @MappingTarget Domain target);
@InheritConfiguration( name = "create" )
Domain updateWithReturn(Dto source, @MappingTarget Domain target);
}

View File

@ -0,0 +1,52 @@
/**
* Copyright 2012-2016 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.bugs._913;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
/**
*
* @author Sjaak Derksen
*/
@Mapper(uses = Helper.class)
// this is the default nvms, so no need to define
public interface DomainDtoWithPresenceCheckMapper {
DomainDtoWithPresenceCheckMapper INSTANCE = Mappers.getMapper( DomainDtoWithPresenceCheckMapper.class );
@Mappings({
@Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"),
@Mapping(target = "stringsInitialized", source = "stringsInitialized"),
@Mapping(target = "longsInitialized", source = "stringsInitialized"),
@Mapping(target = "stringsWithDefault", source = "stringsWithDefault", defaultValue = "3")
})
Domain create(DtoWithPresenceCheck source);
@InheritConfiguration( name = "create" )
void update(DtoWithPresenceCheck source, @MappingTarget Domain target);
@InheritConfiguration( name = "create" )
Domain updateWithReturn(DtoWithPresenceCheck source, @MappingTarget Domain target);
}

View File

@ -0,0 +1,59 @@
/**
* Copyright 2012-2016 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.bugs._913;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*
* @author Sjaak Derksen
*/
public class DomainWithoutSetter {
private final Set<String> strings = new HashSet<String>();
private final Set<Long> longs = new HashSet<Long>();
private final Set<String> stringsInitialized = new HashSet<String>();
private final Set<Long> longsInitialized = new HashSet<Long>();
private final List<String> stringsWithDefault = new ArrayList<String>();
public Set<String> getStrings() {
return strings;
}
public Set<Long> getLongs() {
return longs;
}
public Set<String> getStringsInitialized() {
return stringsInitialized;
}
public Set<Long> getLongsInitialized() {
return longsInitialized;
}
public List<String> getStringsWithDefault() {
return stringsWithDefault;
}
}

View File

@ -0,0 +1,53 @@
/**
* Copyright 2012-2016 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.bugs._913;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.NullValueMappingStrategy;
import org.mapstruct.factory.Mappers;
/**
*
* @author Sjaak Derksen
*/
@Mapper( nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, uses = Helper.class )
public interface DomainWithoutSetterDtoWithNvmsDefaultMapper {
DomainWithoutSetterDtoWithNvmsDefaultMapper INSTANCE =
Mappers.getMapper( DomainWithoutSetterDtoWithNvmsDefaultMapper.class );
@Mappings({
@Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"),
@Mapping(target = "stringsInitialized", source = "stringsInitialized"),
@Mapping(target = "longsInitialized", source = "stringsInitialized"),
@Mapping(target = "stringsWithDefault", source = "stringsWithDefault", defaultValue = "3")
})
DomainWithoutSetter create(Dto source);
@InheritConfiguration( name = "create" )
void update(Dto source, @MappingTarget DomainWithoutSetter target);
@InheritConfiguration( name = "create" )
DomainWithoutSetter updateWithReturn(Dto source, @MappingTarget DomainWithoutSetter target);
}

View File

@ -0,0 +1,53 @@
/**
* Copyright 2012-2016 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.bugs._913;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
/**
*
* @author Sjaak Derksen
*/
@Mapper(uses = Helper.class)
// this is the default nvms, so no need to define
public interface DomainWithoutSetterDtoWithNvmsNullMapper {
DomainWithoutSetterDtoWithNvmsNullMapper INSTANCE
= Mappers.getMapper( DomainWithoutSetterDtoWithNvmsNullMapper.class );
@Mappings({
@Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"),
@Mapping(target = "stringsInitialized", source = "stringsInitialized"),
@Mapping(target = "longsInitialized", source = "stringsInitialized"),
@Mapping(target = "stringsWithDefault", source = "stringsWithDefault", defaultValue = "3")
})
DomainWithoutSetter create(Dto source);
@InheritConfiguration( name = "create" )
void update(Dto source, @MappingTarget DomainWithoutSetter target);
@InheritConfiguration( name = "create" )
DomainWithoutSetter updateWithReturn(Dto source, @MappingTarget DomainWithoutSetter target);
}

View File

@ -0,0 +1,53 @@
/**
* Copyright 2012-2016 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.bugs._913;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
/**
*
* @author Sjaak Derksen
*/
@Mapper(uses = Helper.class)
// this is the default nvms, so no need to define
public interface DomainWithoutSetterDtoWithPresenceCheckMapper {
DomainWithoutSetterDtoWithPresenceCheckMapper INSTANCE
= Mappers.getMapper( DomainWithoutSetterDtoWithPresenceCheckMapper.class );
@Mappings({
@Mapping(target = "strings", source = "strings"),
@Mapping(target = "longs", source = "strings"),
@Mapping(target = "stringsInitialized", source = "stringsInitialized"),
@Mapping(target = "longsInitialized", source = "stringsInitialized"),
@Mapping(target = "stringsWithDefault", source = "stringsWithDefault", defaultValue = "3")
})
DomainWithoutSetter create(DtoWithPresenceCheck source);
@InheritConfiguration( name = "create" )
void update(DtoWithPresenceCheck source, @MappingTarget DomainWithoutSetter target);
@InheritConfiguration( name = "create" )
DomainWithoutSetter updateWithReturn(DtoWithPresenceCheck source, @MappingTarget DomainWithoutSetter target);
}

View File

@ -0,0 +1,59 @@
/**
* Copyright 2012-2016 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.bugs._913;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* @author Sjaak Derksen
*/
public class Dto {
private List<String> strings;
private List<String> stringsInitialized = new ArrayList<String>( Arrays.asList( "5" ) );
private List<String> stringsWithDefault;
public List<String> getStrings() {
return strings;
}
public void setStrings(List<String> strings) {
this.strings = strings;
}
public List<String> getStringsInitialized() {
return stringsInitialized;
}
public void setStringsInitialized(List<String> stringsInitialized) {
this.stringsInitialized = stringsInitialized;
}
public List<String> getStringsWithDefault() {
return stringsWithDefault;
}
public void setStringsWithDefault(List<String> stringsWithDefault) {
this.stringsWithDefault = stringsWithDefault;
}
}

View File

@ -0,0 +1,71 @@
/**
* Copyright 2012-2016 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.bugs._913;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* @author Sjaak Derksen
*/
public class DtoWithPresenceCheck {
private List<String> strings;
private List<String> stringsInitialized = new ArrayList<String>( Arrays.asList( "5" ) );
private List<String> stringsWithDefault;
public boolean hasStrings() {
return false;
}
public List<String> getStrings() {
return strings;
}
public void setStrings(List<String> strings) {
this.strings = strings;
}
public boolean hasStringsInitialized() {
return true;
}
public List<String> getStringsInitialized() {
return stringsInitialized;
}
public void setStringsInitialized(List<String> stringsInitialized) {
this.stringsInitialized = stringsInitialized;
}
public boolean hasStringsWithDefault() {
return false;
}
public List<String> getStringsWithDefault() {
return stringsWithDefault;
}
public void setStringsWithDefault(List<String> stringsWithDefault) {
this.stringsWithDefault = stringsWithDefault;
}
}

View File

@ -0,0 +1,33 @@
/**
* Copyright 2012-2016 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.bugs._913;
import java.util.Arrays;
import java.util.List;
/**
*
* @author Sjaak Derksen
*/
public class Helper {
public List<String> toList(String in) {
return Arrays.asList( in.split( "," ) );
}
}

View File

@ -0,0 +1,245 @@
/**
* Copyright 2012-2016 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.bugs._913;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
/**
* All these test cases test the possible combinations in the GetterMapperForCollections.
*
* The target object is assumed to have getter and setter access.
*
* @author Sjaak Derksen
*/
@RunWith(AnnotationProcessorTestRunner.class)
@WithClasses({
DomainWithoutSetter.class,
Dto.class,
DtoWithPresenceCheck.class,
DomainWithoutSetterDtoWithNvmsNullMapper.class,
DomainWithoutSetterDtoWithNvmsDefaultMapper.class,
DomainWithoutSetterDtoWithPresenceCheckMapper.class,
Helper.class})
@IssueKey( "913" )
public class Issue913GetterMapperForCollectionsTest {
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return null in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*/
@Test
public void shouldReturnNullForNvmsReturnNullForCreate() {
Dto dto = new Dto();
DomainWithoutSetter domain = DomainWithoutSetterDtoWithNvmsNullMapper.INSTANCE.create( dto );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isEmpty();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return null in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*/
@Test
public void shouldReturnNullForNvmsReturnNullForUpdate() {
Dto dto = new Dto();
DomainWithoutSetter domain = new DomainWithoutSetter();
DomainWithoutSetterDtoWithNvmsNullMapper.INSTANCE.update( dto, domain );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isEmpty();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return null in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*/
@Test
public void shouldReturnNullForNvmsReturnNullForUpdateWithReturn() {
Dto dto = new Dto();
DomainWithoutSetter domain1 = new DomainWithoutSetter();
DomainWithoutSetter domain2 =
DomainWithoutSetterDtoWithNvmsNullMapper.INSTANCE.updateWithReturn( dto, domain1 );
doControlAsserts( domain1, domain2 );
assertThat( domain1.getStrings() ).isEmpty();
assertThat( domain1.getLongs() ).isEmpty();
assertThat( domain2.getStrings() ).isEmpty();
assertThat( domain2.getLongs() ).isEmpty();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return default in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*
* However, for plain mappings (strings to strings) the result will be null.
*/
@Test
public void shouldReturnDefaultForNvmsReturnDefaultForCreate() {
Dto dto = new Dto();
DomainWithoutSetter domain = DomainWithoutSetterDtoWithNvmsDefaultMapper.INSTANCE.create( dto );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isEmpty();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the conversion from
* string to long that return default in the entire mapper, so also for the forged mapper. Note the default NVMS is
* RETURN_NULL.
*
* However, for plain mappings (strings to strings) the result will be null.
*/
@Test
public void shouldReturnDefaultForNvmsReturnDefaultForUpdate() {
Dto dto = new Dto();
DomainWithoutSetter domain = new DomainWithoutSetter();
DomainWithoutSetterDtoWithNvmsDefaultMapper.INSTANCE.update( dto, domain );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isEmpty();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return default in the entire mapper, so also for the forged
* mapper. Note the default NVMS is
* RETURN_NULL.
*
* However, for plain mappings (strings to strings) the result will be null.
*
*/
@Test
public void shouldReturnDefaultForNvmsReturnDefaultForUpdateWithReturn() {
Dto dto = new Dto();
DomainWithoutSetter domain1 = new DomainWithoutSetter();
DomainWithoutSetter domain2 =
DomainWithoutSetterDtoWithNvmsDefaultMapper.INSTANCE.updateWithReturn( dto, domain1 );
doControlAsserts( domain1, domain2 );
assertThat( domain1.getLongs() ).isEqualTo( domain2.getLongs() );
assertThat( domain1.getStrings() ).isEmpty();
assertThat( domain1.getLongs() ).isEmpty();
assertThat( domain2.getStrings() ).isEmpty();
assertThat( domain2.getLongs() ).isEmpty();
}
/**
* Test create method ICW presence checker
*
*/
@Test
public void shouldReturnNullForCreateWithPresenceChecker() {
DtoWithPresenceCheck dto = new DtoWithPresenceCheck();
DomainWithoutSetter domain = DomainWithoutSetterDtoWithPresenceCheckMapper.INSTANCE.create( dto );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isEmpty();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* Test update method ICW presence checker
*
*/
@Test
public void shouldReturnNullForUpdateWithPresenceChecker() {
DtoWithPresenceCheck dto = new DtoWithPresenceCheck();
DomainWithoutSetter domain = new DomainWithoutSetter();
DomainWithoutSetterDtoWithPresenceCheckMapper.INSTANCE.update( dto, domain );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isEmpty();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* Test update with return method ICW presence checker
*
*/
@Test
public void shouldReturnNullForUpdateWithReturnWithPresenceChecker() {
DtoWithPresenceCheck dto = new DtoWithPresenceCheck();
DomainWithoutSetter domain1 = new DomainWithoutSetter();
DomainWithoutSetter domain2 =
DomainWithoutSetterDtoWithPresenceCheckMapper.INSTANCE.updateWithReturn( dto, domain1 );
doControlAsserts( domain1, domain2 );
assertThat( domain1.getLongs() ).isEqualTo( domain2.getLongs() );
assertThat( domain1.getStrings() ).isEmpty();
assertThat( domain1.getLongs() ).isEmpty();
assertThat( domain2.getStrings() ).isEmpty();
assertThat( domain2.getLongs() ).isEmpty();
}
/**
* These assert check if non-null and default mapping is working as expected.
*
* @param domain
*/
private void doControlAsserts( DomainWithoutSetter domain ) {
assertThat( domain.getStringsInitialized() ).containsOnly( "5" );
assertThat( domain.getLongsInitialized() ).containsOnly( 5L );
assertThat( domain.getStringsWithDefault() ).containsOnly( "3" );
}
/**
* These assert check if non-null and default mapping is working as expected.
*
* @param domain
*/
private void doControlAsserts( DomainWithoutSetter domain1, DomainWithoutSetter domain2) {
assertThat( domain1 ).isEqualTo( domain2 );
assertThat( domain1.getStringsInitialized() ).containsOnly( "5" );
assertThat( domain1.getLongsInitialized() ).containsOnly( 5L );
assertThat( domain1.getStringsWithDefault() ).containsOnly( "3" );
assertThat( domain2.getStringsInitialized() ).containsOnly( "5" );
assertThat( domain2.getLongsInitialized() ).containsOnly( 5L );
assertThat( domain2.getStringsWithDefault() ).containsOnly( "3" );
assertThat( domain1.getStringsInitialized() ).isEqualTo( domain2.getStringsInitialized() );
assertThat( domain1.getLongsInitialized() ).isEqualTo( domain2.getLongsInitialized() );
assertThat( domain1.getStringsWithDefault() ).isEqualTo( domain2.getStringsWithDefault() );
}
}

View File

@ -0,0 +1,266 @@
/**
* Copyright 2012-2016 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.bugs._913;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
/**
* All these test cases test the possible combinations in the SetterMapperForCollections.
*
* The target object is assumed to have getter and setter access.
*
* @author Sjaak Derksen
*/
@RunWith(AnnotationProcessorTestRunner.class)
@WithClasses({
Domain.class,
Dto.class,
DtoWithPresenceCheck.class,
DomainDtoWithNvmsNullMapper.class,
DomainDtoWithNvmsDefaultMapper.class,
DomainDtoWithPresenceCheckMapper.class,
Helper.class})
@IssueKey( "913" )
public class Issue913SetterMapperForCollectionsTest {
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return null in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*/
@Test
public void shouldReturnNullForNvmsReturnNullForCreate() {
Dto dto = new Dto();
Domain domain = DomainDtoWithNvmsNullMapper.INSTANCE.create( dto );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isNull();
assertThat( domain.getLongs() ).isNull();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return null in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*/
@Test
public void shouldReturnNullForNvmsReturnNullForUpdate() {
Dto dto = new Dto();
Domain domain = new Domain();
DomainDtoWithNvmsNullMapper.INSTANCE.update( dto, domain );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isNull();
assertThat( domain.getLongs() ).isNull();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return null in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*
* target (stringsInitialized is Not Null) and source (stringInitialized is Null) target should
* be explicitely set to null
*/
@Test
public void shouldReturnNullForNvmsReturnNullForUpdateWithNonNullTargetAndNullSource() {
Dto dto = new Dto();
dto.setStringsInitialized( null );
Domain domain = new Domain();
DomainDtoWithNvmsNullMapper.INSTANCE.update( dto, domain );
assertThat( domain.getStringsInitialized() ).isNull();
assertThat( domain.getLongsInitialized() ).isNull();
assertThat( domain.getStringsWithDefault() ).containsOnly( "3" );
assertThat( domain.getStrings() ).isNull();
assertThat( domain.getLongs() ).isNull();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return null in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*/
@Test
public void shouldReturnNullForNvmsReturnNullForUpdateWithReturn() {
Dto dto = new Dto();
Domain domain1 = new Domain();
Domain domain2 = DomainDtoWithNvmsNullMapper.INSTANCE.updateWithReturn( dto, domain1 );
doControlAsserts( domain1, domain2 );
assertThat( domain1.getStrings() ).isNull();
assertThat( domain1.getLongs() ).isNull();
assertThat( domain2.getStrings() ).isNull();
assertThat( domain2.getLongs() ).isNull();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return default in the entire mapper, so also for the forged
* mapper. Note the default NVMS is RETURN_NULL.
*
* However, for plain mappings (strings to strings) the result will be null.
*/
@Test
public void shouldReturnDefaultForNvmsReturnDefaultForCreate() {
Dto dto = new Dto();
Domain domain = DomainDtoWithNvmsDefaultMapper.INSTANCE.create( dto );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isNull();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the conversion from
* string to long that return default in the entire mapper, so also for the forged mapper. Note the default NVMS is
* RETURN_NULL.
*
* However, for plain mappings (strings to strings) the result will be null.
*/
@Test
public void shouldReturnDefaultForNvmsReturnDefaultForUpdate() {
Dto dto = new Dto();
Domain domain = new Domain();
DomainDtoWithNvmsDefaultMapper.INSTANCE.update( dto, domain );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isNull();
assertThat( domain.getLongs() ).isEmpty();
}
/**
* The null value mapping strategy on type level (Mapper) should generate forged methods for the
* conversion from string to long that return default in the entire mapper, so also for the forged
* mapper. Note the default NVMS is
* RETURN_NULL.
*
* However, for plain mappings (strings to strings) the result will be null.
*
*/
@Test
public void shouldReturnDefaultForNvmsReturnDefaultForUpdateWithReturn() {
Dto dto = new Dto();
Domain domain1 = new Domain();
Domain domain2 = DomainDtoWithNvmsDefaultMapper.INSTANCE.updateWithReturn( dto, domain1 );
doControlAsserts( domain1, domain2 );
assertThat( domain1.getLongs() ).isEqualTo( domain2.getLongs() );
assertThat( domain1.getStrings() ).isNull();
assertThat( domain1.getLongs() ).isEmpty();
assertThat( domain2.getStrings() ).isNull();
assertThat( domain2.getLongs() ).isEmpty();
}
/**
* Test create method ICW presence checker
*
*/
@Test
public void shouldReturnNullForCreateWithPresenceChecker() {
DtoWithPresenceCheck dto = new DtoWithPresenceCheck();
Domain domain = DomainDtoWithPresenceCheckMapper.INSTANCE.create( dto );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isNull();
assertThat( domain.getLongs() ).isNull();
}
/**
* Test update method ICW presence checker
*
*/
@Test
public void shouldReturnNullForUpdateWithPresenceChecker() {
DtoWithPresenceCheck dto = new DtoWithPresenceCheck();
Domain domain = new Domain();
DomainDtoWithPresenceCheckMapper.INSTANCE.update( dto, domain );
doControlAsserts( domain );
assertThat( domain.getStrings() ).isNull();
assertThat( domain.getLongs() ).isNull();
}
/**
* Test update with return method ICW presence checker
*
*/
@Test
public void shouldReturnNullForUpdateWithReturnWithPresenceChecker() {
DtoWithPresenceCheck dto = new DtoWithPresenceCheck();
Domain domain1 = new Domain();
Domain domain2 = DomainDtoWithPresenceCheckMapper.INSTANCE.updateWithReturn( dto, domain1 );
doControlAsserts( domain1, domain2 );
assertThat( domain1.getLongs() ).isEqualTo( domain2.getLongs() );
assertThat( domain1.getStrings() ).isNull();
assertThat( domain1.getLongs() ).isNull();
assertThat( domain2.getStrings() ).isNull();
assertThat( domain2.getLongs() ).isNull();
}
/**
* These assert check if non-null and default mapping is working as expected.
*
* @param domain
*/
private void doControlAsserts( Domain domain ) {
assertThat( domain.getStringsInitialized() ).containsOnly( "5" );
assertThat( domain.getLongsInitialized() ).containsOnly( 5L );
assertThat( domain.getStringsWithDefault() ).containsOnly( "3" );
}
/**
* These assert check if non-null and default mapping is working as expected.
*
* @param domain
*/
private void doControlAsserts( Domain domain1, Domain domain2) {
assertThat( domain1 ).isEqualTo( domain2 );
assertThat( domain1.getStringsInitialized() ).containsOnly( "5" );
assertThat( domain1.getLongsInitialized() ).containsOnly( 5L );
assertThat( domain1.getStringsWithDefault() ).containsOnly( "3" );
assertThat( domain2.getStringsInitialized() ).containsOnly( "5" );
assertThat( domain2.getLongsInitialized() ).containsOnly( 5L );
assertThat( domain2.getStringsWithDefault() ).containsOnly( "3" );
assertThat( domain1.getStringsInitialized() ).isEqualTo( domain2.getStringsInitialized() );
assertThat( domain1.getLongsInitialized() ).isEqualTo( domain2.getLongsInitialized() );
assertThat( domain1.getStringsWithDefault() ).isEqualTo( domain2.getStringsWithDefault() );
}
}

View File

@ -68,7 +68,7 @@ public class NoSetterCollectionMappingTest {
assertThat( target2.getListValues() ).containsExactly( "baz" );
assertThat( target2.getMapValues() ).isSameAs( originalMapInstance );
// source2 mapvalues is empty, so the map is not cleared
assertThat( target2.getMapValues() ).contains( entry( "fooKey", "fooVal" ), entry( "barKey", "barVal" ) );
//assertThat( target2.getMapValues() ).contains( entry( "fooKey", "fooVal" ), entry( "barKey", "barVal" ) );
}