Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1117,8 +1117,8 @@ private String getPropertyName(ExecutableElement element) {
* Matching occurs on:
* <ol>
* <li>The generic type parameter type of the collection should match the adder method argument</li>
* <li>When there are more candidates, property name is made singular (as good as is possible). This routine
* looks for a matching add method name.</li>
* <li>The adder element name must match the property name or its singular form. A single type-compatible
* adder is not reused for other collection properties.</li>
* <li>The singularization rules of Dali are used to make a property name singular. This routine
* looks for a matching add method name.</li>
* </ol>
Expand Down Expand Up @@ -1146,18 +1146,22 @@ else if ( collectionProperty.isStreamType() ) {
return null;
}

if ( candidates.size() == 1 ) {
return candidates.get( 0 );
}

String singularPropertyName = Nouns.singularize( pluralPropertyName );
Accessor pluralNameMatch = null;
for ( Accessor candidate : candidates ) {
String elementName = accessorNaming.getElementNameForAdder( candidate );
if ( elementName != null && elementName.equals( Nouns.singularize( pluralPropertyName ) ) ) {
if ( elementName == null ) {
continue;
}
if ( elementName.equals( singularPropertyName ) ) {
return candidate;
}
if ( pluralNameMatch == null && elementName.equals( pluralPropertyName ) ) {
pluralNameMatch = candidate;
}
}

return null;
return pluralNameMatch;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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._4038;

import java.util.Arrays;
import java.util.LinkedHashSet;

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;

@IssueKey("4038")
@WithClasses({ Source.class, Target.class, SourceTargetMapper.class })
public class Issue4038Test {

@ProcessorTest
public void adderShouldOnlyBeUsedForMatchingProperty() {
Source source = new Source();
source.setName( "n" );
source.setItems( Arrays.asList( "a", "b" ) );
source.setMoreItems( Arrays.asList( "c", "d" ) );
source.setExtraItems( new LinkedHashSet<String>( Arrays.asList( "e" ) ) );

Target target = SourceTargetMapper.INSTANCE.toTarget( source );

assertThat( target.getName() ).isEqualTo( "n" );
assertThat( target.getItems() ).containsExactly( "a", "b" );
assertThat( target.getMoreItems() ).containsExactly( "c", "d" );
assertThat( target.getExtraItems() ).containsExactly( "e" );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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._4038;

import java.util.List;
import java.util.Set;

public class Source {

private String name;
private List<String> items;
private List<String> moreItems;
private Set<String> extraItems;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<String> getItems() {
return items;
}

public void setItems(List<String> items) {
this.items = items;
}

public List<String> getMoreItems() {
return moreItems;
}

public void setMoreItems(List<String> moreItems) {
this.moreItems = moreItems;
}

public Set<String> getExtraItems() {
return extraItems;
}

public void setExtraItems(Set<String> extraItems) {
this.extraItems = extraItems;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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._4038;

import org.mapstruct.CollectionMappingStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface SourceTargetMapper {

SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );

Target toTarget(Source source);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* 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._4038;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* Mimics a Lombok {@code @Value @Builder} type with {@code @Singular("addItem")} on {@code items}.
*/
public class Target {

private final String name;
private final List<String> items;
private final List<String> moreItems;
private final Set<String> extraItems;

private Target(Builder builder) {
this.name = builder.name;
this.items = builder.items;
this.moreItems = builder.moreItems;
this.extraItems = builder.extraItems;
}

public static Builder builder() {
return new Builder();
}

public String getName() {
return name;
}

public List<String> getItems() {
return items;
}

public List<String> getMoreItems() {
return moreItems;
}

public Set<String> getExtraItems() {
return extraItems;
}

public static class Builder {

private String name;
private List<String> items = new ArrayList<String>();
private List<String> moreItems;
private Set<String> extraItems;

public Builder name(String name) {
this.name = name;
return this;
}

public Builder addItem(String item) {
this.items.add( item );
return this;
}

public Builder items(Collection<? extends String> items) {
this.items.clear();
if ( items != null ) {
this.items.addAll( items );
}
return this;
}

public Builder moreItems(Collection<? extends String> moreItems) {
this.moreItems = moreItems == null ? null : new ArrayList<String>( moreItems );
return this;
}

public Builder extraItems(Collection<? extends String> extraItems) {
this.extraItems = extraItems == null ? null : new LinkedHashSet<String>( extraItems );
return this;
}

public Target build() {
return new Target( this );
}
}
}