Skip to content

Commit 0c51f7a

Browse files
sjaakdsjaakd
authored andcommitted
#2278 inherited property ignored due to ignore on nested level (#2332)
Co-authored-by: sjaakd <sjaakderksen@zonnet.nl>
1 parent 15b3469 commit 0c51f7a

7 files changed

Lines changed: 435 additions & 4 deletions

File tree

processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,11 @@ private void addAllNonRedefined(Set<MappingOptions> inheritedMappings) {
230230
}
231231

232232
private boolean isRedefined(Set<String> redefinedNames, String inheritedName ) {
233-
for ( String redefinedName : redefinedNames ) {
234-
if ( elementsAreContainedIn( redefinedName, inheritedName ) ) {
235-
return true;
233+
if ( inheritedName != null ) {
234+
for ( String redefinedName : redefinedNames ) {
235+
if ( elementsAreContainedIn( inheritedName, redefinedName ) ) {
236+
return true;
237+
}
236238
}
237239
}
238240
return false;
@@ -241,7 +243,7 @@ private boolean isRedefined(Set<String> redefinedNames, String inheritedName ) {
241243
private boolean elementsAreContainedIn( String redefinedName, String inheritedName ) {
242244
if ( inheritedName != null && redefinedName.startsWith( inheritedName ) ) {
243245
// it is possible to redefine an exact matching source name, because the same source can be mapped to
244-
// multiple targets. It is not possible for target, but caught by the Set and equals methoded in
246+
// multiple targets. It is not possible for target, but caught by the Set and equals method in
245247
// MappingOptions. SourceName == null also could hint at redefinition
246248
if ( redefinedName.length() > inheritedName.length() ) {
247249
// redefined.lenght() > inherited.length(), first following character should be separator
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright MapStruct Authors.
3+
*
4+
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
package org.mapstruct.ap.test.bugs._2278;
7+
8+
import org.mapstruct.InheritInverseConfiguration;
9+
import org.mapstruct.Mapper;
10+
import org.mapstruct.Mapping;
11+
import org.mapstruct.factory.Mappers;
12+
13+
/**
14+
* ReproducerA
15+
*
16+
*/
17+
@Mapper
18+
public interface Issue2278MapperA {
19+
20+
Issue2278MapperA INSTANCE = Mappers.getMapper( Issue2278MapperA.class );
21+
22+
@Mapping( target = "detailsDTO", source = "details" )
23+
@Mapping( target = "detailsDTO.fuelType", ignore = true )
24+
CarDTO map(Car in);
25+
26+
// checkout the Issue2278ReferenceMapper, the @InheritInverseConfiguration
27+
// is de-facto @Mapping( target = "details", source = "detailsDTO" )
28+
@InheritInverseConfiguration
29+
@Mapping( target = "details.model", ignore = true )
30+
@Mapping( target = "details.type", constant = "gto")
31+
@Mapping( target = "details.fuel", source = "detailsDTO.fuelType")
32+
Car map(CarDTO in);
33+
34+
class Car {
35+
//CHECKSTYLE:OFF
36+
public Details details;
37+
//CHECKSTYLE:ON
38+
}
39+
40+
class CarDTO {
41+
//CHECKSTYLE:OFF
42+
public DetailsDTO detailsDTO;
43+
//CHECKSTYLE:ON
44+
}
45+
46+
class Details {
47+
//CHECKSTYLE:OFF
48+
public String brand;
49+
public String model;
50+
public String type;
51+
public String fuel;
52+
//CHECKSTYLE:ON
53+
}
54+
55+
class DetailsDTO {
56+
//CHECKSTYLE:OFF
57+
public String brand;
58+
public String fuelType;
59+
//CHECKSTYLE:ON
60+
}
61+
62+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright MapStruct Authors.
3+
*
4+
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
package org.mapstruct.ap.test.bugs._2278;
7+
8+
import org.mapstruct.InheritInverseConfiguration;
9+
import org.mapstruct.Mapper;
10+
import org.mapstruct.Mapping;
11+
import org.mapstruct.factory.Mappers;
12+
13+
/**
14+
* ReproducerB
15+
*
16+
*/
17+
@Mapper
18+
public interface Issue2278MapperB {
19+
20+
Issue2278MapperB INSTANCE = Mappers.getMapper( Issue2278MapperB.class );
21+
22+
// id mapping is cros-linked
23+
@Mapping( target = "amount", source = "price" )
24+
@Mapping( target = "detailsDTO.brand", source = "details.type" )
25+
@Mapping( target = "detailsDTO.id1", source = "details.id2" )
26+
@Mapping( target = "detailsDTO.id2", source = "details.id1" )
27+
CarDTO map(Car in);
28+
29+
// inherit inverse, but undo cross-link in one sweep
30+
@InheritInverseConfiguration // inherits all
31+
@Mapping( target = "details", source = "detailsDTO" ) // resets everything on details <> detailsDto
32+
@Mapping( target = "details.type", source = "detailsDTO.brand" ) // so this needs to be redone
33+
Car map2(CarDTO in);
34+
35+
class Car {
36+
//CHECKSTYLE:OFF
37+
public float price;
38+
public Details details;
39+
//CHECKSTYLE:ON
40+
}
41+
42+
class CarDTO {
43+
//CHECKSTYLE:OFF
44+
public float amount;
45+
public DetailsDTO detailsDTO;
46+
//CHECKSTYLE:ON
47+
}
48+
49+
class Details {
50+
//CHECKSTYLE:OFF
51+
public String type;
52+
public String id1;
53+
public String id2;
54+
//CHECKSTYLE:ON
55+
}
56+
57+
class DetailsDTO {
58+
//CHECKSTYLE:OFF
59+
public String brand;
60+
public String id1;
61+
public String id2;
62+
//CHECKSTYLE:ON
63+
}
64+
65+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright MapStruct Authors.
3+
*
4+
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
package org.mapstruct.ap.test.bugs._2278;
7+
8+
import org.mapstruct.Mapper;
9+
import org.mapstruct.Mapping;
10+
import org.mapstruct.factory.Mappers;
11+
12+
/**
13+
* A reference mapper, that checks how a regular forward merge works
14+
*/
15+
@Mapper
16+
public interface Issue2278ReferenceMapper {
17+
18+
Issue2278ReferenceMapper INSTANCE = Mappers.getMapper( Issue2278ReferenceMapper.class );
19+
20+
@Mapping( target = "details", source = "detailsDTO" )
21+
@Mapping( target = "details.model", ignore = true )
22+
@Mapping( target = "details.type", constant = "gto")
23+
@Mapping( target = "details.fuel", source = "detailsDTO.fuelType")
24+
Car map(CarDTO in);
25+
26+
class Car {
27+
//CHECKSTYLE:OFF
28+
public Details details;
29+
//CHECKSTYLE:ON
30+
}
31+
32+
class CarDTO {
33+
//CHECKSTYLE:OFF
34+
public DetailsDTO detailsDTO;
35+
//CHECKSTYLE:ON
36+
}
37+
38+
class Details {
39+
//CHECKSTYLE:OFF
40+
public String brand;
41+
public String model;
42+
public String type;
43+
public String fuel;
44+
//CHECKSTYLE:ON
45+
}
46+
47+
class DetailsDTO {
48+
//CHECKSTYLE:OFF
49+
public String brand;
50+
public String fuelType;
51+
//CHECKSTYLE:ON
52+
}
53+
54+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright MapStruct Authors.
3+
*
4+
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
package org.mapstruct.ap.test.bugs._2278;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import org.junit.Test;
11+
import org.junit.runner.RunWith;
12+
import org.mapstruct.ap.testutil.IssueKey;
13+
import org.mapstruct.ap.testutil.WithClasses;
14+
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
15+
16+
@IssueKey("2278")
17+
@RunWith( AnnotationProcessorTestRunner.class)
18+
public class Issue2278Test {
19+
20+
@Test
21+
@WithClasses( Issue2278ReferenceMapper.class )
22+
public void testReferenceMergeBehaviour() {
23+
24+
Issue2278ReferenceMapper.CarDTO dto = new Issue2278ReferenceMapper.CarDTO();
25+
dto.detailsDTO = new Issue2278ReferenceMapper.DetailsDTO();
26+
dto.detailsDTO.brand = "Ford";
27+
dto.detailsDTO.fuelType = "petrol";
28+
29+
Issue2278ReferenceMapper.Car target = Issue2278ReferenceMapper.INSTANCE.map( dto );
30+
31+
assertThat( target ).isNotNull();
32+
assertThat( target.details ).isNotNull();
33+
assertThat( target.details.brand ).isEqualTo( "Ford" );
34+
assertThat( target.details.model ).isNull();
35+
assertThat( target.details.type ).isEqualTo( "gto" );
36+
assertThat( target.details.fuel ).isEqualTo( "petrol" );
37+
38+
}
39+
40+
@Test
41+
@WithClasses( Issue2278MapperA.class )
42+
public void shouldBehaveJustAsTestReferenceMergeBehaviour() {
43+
44+
Issue2278MapperA.CarDTO dto = new Issue2278MapperA.CarDTO();
45+
dto.detailsDTO = new Issue2278MapperA.DetailsDTO();
46+
dto.detailsDTO.brand = "Ford";
47+
dto.detailsDTO.fuelType = "petrol";
48+
49+
Issue2278MapperA.Car target = Issue2278MapperA.INSTANCE.map( dto );
50+
51+
assertThat( target ).isNotNull();
52+
assertThat( target.details ).isNotNull();
53+
assertThat( target.details.brand ).isEqualTo( "Ford" );
54+
assertThat( target.details.model ).isNull();
55+
assertThat( target.details.type ).isEqualTo( "gto" );
56+
assertThat( target.details.fuel ).isEqualTo( "petrol" );
57+
58+
}
59+
60+
@Test
61+
@WithClasses( Issue2278MapperB.class )
62+
public void shouldOverrideDetailsMappingWithRedefined() {
63+
64+
Issue2278MapperB.Car source = new Issue2278MapperB.Car();
65+
source.details = new Issue2278MapperB.Details();
66+
source.details.type = "Ford";
67+
source.details.id1 = "id1";
68+
source.details.id2 = "id2";
69+
source.price = 20000f;
70+
71+
Issue2278MapperB.CarDTO target1 = Issue2278MapperB.INSTANCE.map( source );
72+
73+
assertThat( target1 ).isNotNull();
74+
assertThat( target1.amount ).isEqualTo( 20000f );
75+
assertThat( target1.detailsDTO ).isNotNull();
76+
assertThat( target1.detailsDTO.brand ).isEqualTo( "Ford" );
77+
assertThat( target1.detailsDTO.id1 ).isEqualTo( "id2" );
78+
assertThat( target1.detailsDTO.id2 ).isEqualTo( "id1" );
79+
80+
// restore the mappings, just to make it logical again
81+
target1.detailsDTO.id1 = "id1";
82+
target1.detailsDTO.id2 = "id2";
83+
84+
// now check the reverse inheritance
85+
Issue2278MapperB.Car target2 = Issue2278MapperB.INSTANCE.map2( target1 );
86+
87+
assertThat( target2 ).isNotNull();
88+
assertThat( target2.price ).isEqualTo( 20000f );
89+
assertThat( target2.details ).isNotNull();
90+
assertThat( target2.details.type ).isEqualTo( "Ford" ); // should inherit
91+
assertThat( target2.details.id1 ).isEqualTo( "id1" ); // should be undone
92+
assertThat( target2.details.id2 ).isEqualTo( "id2" ); // should be undone
93+
}
94+
95+
}

0 commit comments

Comments
 (0)