mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#3806: Properly apply NullValuePropertyMappingStrategy.IGNORE
for collections / maps without setters
Signed-off-by: TangYang <tangyang9464@163.com>
This commit is contained in:
parent
5464c3cff8
commit
8fc97f5f62
@ -240,6 +240,7 @@ public class CollectionAssignmentBuilder {
|
|||||||
result,
|
result,
|
||||||
method.getThrownTypes(),
|
method.getThrownTypes(),
|
||||||
targetType,
|
targetType,
|
||||||
|
nvpms,
|
||||||
targetAccessorType.isFieldAssignment()
|
targetAccessorType.isFieldAssignment()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,12 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem;
|
||||||
import org.mapstruct.ap.internal.model.common.Assignment;
|
import org.mapstruct.ap.internal.model.common.Assignment;
|
||||||
import org.mapstruct.ap.internal.model.common.Type;
|
import org.mapstruct.ap.internal.model.common.Type;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.IGNORE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This wrapper handles the situation were an assignment must be done via a target getter method because there
|
* This wrapper handles the situation were an assignment must be done via a target getter method because there
|
||||||
* is no setter available.
|
* is no setter available.
|
||||||
@ -26,6 +29,14 @@ import org.mapstruct.ap.internal.model.common.Type;
|
|||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAndMaps {
|
public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAndMaps {
|
||||||
|
private final boolean ignoreMapNull;
|
||||||
|
|
||||||
|
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
|
||||||
|
List<Type> thrownTypesToExclude,
|
||||||
|
Type targetType,
|
||||||
|
boolean fieldAssignment) {
|
||||||
|
this( decoratedAssignment, thrownTypesToExclude, targetType, null, fieldAssignment );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param decoratedAssignment source RHS
|
* @param decoratedAssignment source RHS
|
||||||
@ -36,6 +47,7 @@ public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAnd
|
|||||||
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
|
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
|
||||||
List<Type> thrownTypesToExclude,
|
List<Type> thrownTypesToExclude,
|
||||||
Type targetType,
|
Type targetType,
|
||||||
|
NullValuePropertyMappingStrategyGem nvpms,
|
||||||
boolean fieldAssignment) {
|
boolean fieldAssignment) {
|
||||||
|
|
||||||
super(
|
super(
|
||||||
@ -44,6 +56,7 @@ public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAnd
|
|||||||
targetType,
|
targetType,
|
||||||
fieldAssignment
|
fieldAssignment
|
||||||
);
|
);
|
||||||
|
this.ignoreMapNull = nvpms == IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,4 +67,8 @@ public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAnd
|
|||||||
}
|
}
|
||||||
return imported;
|
return imported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isIgnoreMapNull() {
|
||||||
|
return ignoreMapNull;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,13 @@
|
|||||||
<@lib.sourceLocalVarAssignment/>
|
<@lib.sourceLocalVarAssignment/>
|
||||||
if ( ${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing /> != null ) {
|
if ( ${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing /> != null ) {
|
||||||
<@lib.handleExceptions>
|
<@lib.handleExceptions>
|
||||||
<#if ext.existingInstanceMapping>
|
<#if ext.existingInstanceMapping && !ignoreMapNull>
|
||||||
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.clear();
|
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.clear();
|
||||||
</#if>
|
</#if>
|
||||||
<@lib.handleLocalVarNullCheck needs_explicit_local_var=false>
|
<@lib.handleLocalVarNullCheck needs_explicit_local_var=false>
|
||||||
|
<#if ext.existingInstanceMapping && ignoreMapNull>
|
||||||
|
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.clear();
|
||||||
|
</#if>
|
||||||
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( <@lib.handleWithAssignmentOrNullCheckVar/> );
|
${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWriteAccesing />.<#if ext.targetType.collectionType>addAll<#else>putAll</#if>( <@lib.handleWithAssignmentOrNullCheckVar/> );
|
||||||
</@lib.handleLocalVarNullCheck>
|
</@lib.handleLocalVarNullCheck>
|
||||||
</@lib.handleExceptions>
|
</@lib.handleExceptions>
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._3806;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.MappingTarget;
|
||||||
|
import org.mapstruct.NullValuePropertyMappingStrategy;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
|
||||||
|
public interface Issue3806Mapper {
|
||||||
|
|
||||||
|
Issue3806Mapper INSTANCE = Mappers.getMapper( Issue3806Mapper.class );
|
||||||
|
|
||||||
|
void update(@MappingTarget Target target, Target source);
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
|
||||||
|
private final Collection<String> authors;
|
||||||
|
private final Map<String, String> booksByAuthor;
|
||||||
|
|
||||||
|
protected Collection<String> books;
|
||||||
|
protected Map<String, String> booksByPublisher;
|
||||||
|
|
||||||
|
public Target(Collection<String> authors, Map<String, String> booksByAuthor) {
|
||||||
|
this.authors = authors != null ? new ArrayList<>( authors ) : null;
|
||||||
|
this.booksByAuthor = booksByAuthor != null ? new HashMap<>( booksByAuthor ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getAuthors() {
|
||||||
|
return authors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getBooksByAuthor() {
|
||||||
|
return booksByAuthor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getBooks() {
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBooks(Collection<String> books) {
|
||||||
|
this.books = books;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getBooksByPublisher() {
|
||||||
|
return booksByPublisher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBooksByPublisher(Map<String, String> booksByPublisher) {
|
||||||
|
this.booksByPublisher = booksByPublisher;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.bugs._3806;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.entry;
|
||||||
|
|
||||||
|
@WithClasses(Issue3806Mapper.class)
|
||||||
|
@IssueKey("3806")
|
||||||
|
class Issue3806Test {
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
void shouldNotClearGetterOnlyCollectionsInUpdateMapping() {
|
||||||
|
Map<String, String> booksByAuthor = new HashMap<>();
|
||||||
|
booksByAuthor.put( "author1", "book1" );
|
||||||
|
booksByAuthor.put( "author2", "book2" );
|
||||||
|
List<String> authors = new ArrayList<>();
|
||||||
|
authors.add( "author1" );
|
||||||
|
authors.add( "author2" );
|
||||||
|
|
||||||
|
List<String> books = new ArrayList<>();
|
||||||
|
books.add( "book1" );
|
||||||
|
books.add( "book2" );
|
||||||
|
Map<String, String> booksByPublisher = new HashMap<>();
|
||||||
|
booksByPublisher.put( "publisher1", "book1" );
|
||||||
|
booksByPublisher.put( "publisher2", "book2" );
|
||||||
|
Issue3806Mapper.Target target = new Issue3806Mapper.Target( authors, booksByAuthor );
|
||||||
|
target.setBooks( books );
|
||||||
|
target.setBooksByPublisher( booksByPublisher );
|
||||||
|
|
||||||
|
Issue3806Mapper.Target source = new Issue3806Mapper.Target( null, null );
|
||||||
|
Issue3806Mapper.INSTANCE.update( target, source );
|
||||||
|
|
||||||
|
assertThat( target.getAuthors() ).containsExactly( "author1", "author2" );
|
||||||
|
assertThat( target.getBooksByAuthor() )
|
||||||
|
.containsOnly(
|
||||||
|
entry( "author1", "book1" ),
|
||||||
|
entry( "author2", "book2" )
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat( target.getBooks() ).containsExactly( "book1", "book2" );
|
||||||
|
assertThat( target.getBooksByPublisher() )
|
||||||
|
.containsOnly(
|
||||||
|
entry( "publisher1", "book1" ),
|
||||||
|
entry( "publisher2", "book2" )
|
||||||
|
);
|
||||||
|
|
||||||
|
booksByAuthor = new HashMap<>();
|
||||||
|
booksByAuthor.put( "author3", "book3" );
|
||||||
|
authors = new ArrayList<>();
|
||||||
|
authors.add( "author3" );
|
||||||
|
|
||||||
|
books = new ArrayList<>();
|
||||||
|
books.add( "book3" );
|
||||||
|
booksByPublisher = new HashMap<>();
|
||||||
|
booksByPublisher.put( "publisher3", "book3" );
|
||||||
|
source = new Issue3806Mapper.Target( authors, booksByAuthor );
|
||||||
|
source.setBooks( books );
|
||||||
|
source.setBooksByPublisher( booksByPublisher );
|
||||||
|
Issue3806Mapper.INSTANCE.update( target, source );
|
||||||
|
|
||||||
|
assertThat( target.getAuthors() ).containsExactly( "author3" );
|
||||||
|
assertThat( target.getBooksByAuthor() )
|
||||||
|
.containsOnly(
|
||||||
|
entry( "author3", "book3" )
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat( target.getBooks() ).containsExactly( "book3" );
|
||||||
|
assertThat( target.getBooksByPublisher() )
|
||||||
|
.containsOnly(
|
||||||
|
entry( "publisher3", "book3" )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user