Skip to content

Commit 4d8bc29

Browse files
author
sjaakd
committed
#1255 Extension of autoInheritanceStrategy, removing of name based ignore reverse mapping
1 parent 6377e51 commit 4d8bc29

File tree

22 files changed

+734
-68
lines changed

22 files changed

+734
-68
lines changed

core-common/src/main/java/org/mapstruct/MappingInheritanceStrategy.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,20 @@ public enum MappingInheritanceStrategy {
3232
EXPLICIT,
3333

3434
/**
35-
* Inherit the method-level configuration annotations automatically if source and target types of the prototype
36-
* method are assignable from the types of a given mapping method.
35+
* Inherit the method-level forward configuration annotations automatically if source and target types of the
36+
* prototype method are assignable from the types of a given mapping method.
3737
*/
38-
AUTO_INHERIT_FROM_CONFIG;
38+
AUTO_INHERIT_FROM_CONFIG,
39+
40+
/**
41+
* Inherit the method-level reverse configuration annotations automatically if source and target types of the
42+
* prototype method are assignable from the target and source types of a given mapping method.
43+
*/
44+
AUTO_INHERIT_REVERSE_FROM_CONFIG,
45+
46+
/**
47+
* Inherit the method-level forward and reverse configuration annotations automatically if source and target types
48+
* of the prototype method are assignable from the types of a given mapping method.
49+
*/
50+
AUTO_INHERIT_ALL_FROM_CONFIG;
3951
}

integrationtest/src/test/resources/fullFeatureTest/src/test/java/org/mapstruct/itest/simple/AnimalTest.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,6 @@ public void shouldNotPropagateIgnoredPropertyGivenViaTargetAttribute() {
4646
assertThat( animalDto.getColor() ).isNull();
4747
}
4848

49-
@Test
50-
public void shouldNotPropagateIgnoredPropertyInReverseMappingWhenNameIsSame() {
51-
AnimalDto animalDto = new AnimalDto( "Bruno", 100, 23, "black" );
52-
53-
Animal animal = AnimalMapper.INSTANCE.animalDtoToAnimal( animalDto );
54-
55-
assertThat( animal ).isNotNull();
56-
assertThat( animalDto.getName() ).isEqualTo( "Bruno" );
57-
assertThat( animalDto.getSize() ).isEqualTo( 100 );
58-
assertThat( animal.getAge() ).isNull();
59-
}
60-
6149
@Test
6250
public void shouldNotPropagateIgnoredPropertyInReverseMappingWhenSourceAndTargetAreSpecified() {
6351
AnimalDto animalDto = new AnimalDto( "Bruno", 100, 23, "black" );

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -398,17 +398,11 @@ private boolean hasPropertyInReverseMethod(String name, SourceMethod method) {
398398
public Mapping reverse(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory) {
399399

400400
// mapping can only be reversed if the source was not a constant nor an expression nor a nested property
401-
if ( constant != null || javaExpression != null ) {
401+
// and the mapping is not a 'target-source-ignore' mapping
402+
if ( constant != null || javaExpression != null || ( isIgnored && sourceName == null ) ) {
402403
return null;
403404
}
404405

405-
// should only ignore a property when 1) there is a sourceName defined or 2) there's a name match
406-
if ( isIgnored ) {
407-
if ( sourceName == null && !hasPropertyInReverseMethod( targetName, method ) ) {
408-
return null;
409-
}
410-
}
411-
412406
Mapping reverse = new Mapping(
413407
sourceName != null ? targetName : null,
414408
null, // constant

processor/src/main/java/org/mapstruct/ap/internal/prism/MappingInheritanceStrategyPrism.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,32 @@
2525
* @author Andreas Gudian
2626
*/
2727
public enum MappingInheritanceStrategyPrism {
28-
EXPLICIT,
29-
AUTO_INHERIT_FROM_CONFIG;
28+
29+
EXPLICIT( false, false, false ),
30+
AUTO_INHERIT_FROM_CONFIG( true, true, false ),
31+
AUTO_INHERIT_REVERSE_FROM_CONFIG( true, false, true ),
32+
AUTO_INHERIT_ALL_FROM_CONFIG( true, true, true );
33+
34+
private final boolean autoInherit;
35+
private final boolean applyForward;
36+
private final boolean applyReverse;
37+
38+
MappingInheritanceStrategyPrism(boolean isAutoInherit, boolean applyForward, boolean applyReverse) {
39+
this.autoInherit = isAutoInherit;
40+
this.applyForward = applyForward;
41+
this.applyReverse = applyReverse;
42+
}
43+
44+
public boolean isAutoInherit() {
45+
return autoInherit;
46+
}
47+
48+
public boolean isApplyForward() {
49+
return applyForward;
50+
}
51+
52+
public boolean isApplyReverse() {
53+
return applyReverse;
54+
}
55+
3056
}

processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.mapstruct.ap.internal.prism.InheritConfigurationPrism;
6060
import org.mapstruct.ap.internal.prism.InheritInverseConfigurationPrism;
6161
import org.mapstruct.ap.internal.prism.MapperPrism;
62+
import org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism;
6263
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
6364
import org.mapstruct.ap.internal.processor.creation.MappingResolverImpl;
6465
import org.mapstruct.ap.internal.util.FormattingMessager;
@@ -67,7 +68,6 @@
6768
import org.mapstruct.ap.internal.util.Strings;
6869
import org.mapstruct.ap.internal.version.VersionInformation;
6970

70-
import static org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism.AUTO_INHERIT_FROM_CONFIG;
7171
import static org.mapstruct.ap.internal.util.Collections.first;
7272
import static org.mapstruct.ap.internal.util.Collections.join;
7373

@@ -446,41 +446,48 @@ private void mergeInheritedOptions(SourceMethod method, MapperConfiguration mapp
446446
initializingMethods,
447447
mapperConfig );
448448

449+
MappingInheritanceStrategyPrism inheritanceStrategy = mapperConfig.getMappingInheritanceStrategy();
450+
449451
if ( templateMappingOptions != null ) {
450452
mappingOptions.applyInheritedOptions( templateMappingOptions, false, method, messager, typeFactory );
451453
}
452454
else if ( inverseMappingOptions != null ) {
453455
mappingOptions.applyInheritedOptions( inverseMappingOptions, true, method, messager, typeFactory );
454456
}
455-
else if ( mapperConfig.getMappingInheritanceStrategy() == AUTO_INHERIT_FROM_CONFIG ) {
456-
if ( applicablePrototypeMethods.size() == 1 ) {
457-
mappingOptions.applyInheritedOptions(
458-
first( applicablePrototypeMethods ).getMappingOptions(),
459-
false,
460-
method,
461-
messager,
462-
typeFactory );
463-
}
464-
else if ( applicablePrototypeMethods.size() > 1 ) {
465-
messager.printMessage(
466-
method.getExecutable(),
467-
Message.INHERITCONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH,
468-
Strings.join( applicablePrototypeMethods, ", " ) );
457+
else if ( inheritanceStrategy.isAutoInherit() ) {
458+
459+
if ( inheritanceStrategy.isApplyForward() ) {
460+
if ( applicablePrototypeMethods.size() == 1 ) {
461+
mappingOptions.applyInheritedOptions(
462+
first( applicablePrototypeMethods ).getMappingOptions(),
463+
false,
464+
method,
465+
messager,
466+
typeFactory );
467+
}
468+
else if ( applicablePrototypeMethods.size() > 1 ) {
469+
messager.printMessage(
470+
method.getExecutable(),
471+
Message.INHERITCONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH,
472+
Strings.join( applicablePrototypeMethods, ", " ) );
473+
}
469474
}
470475

471-
if ( applicableReversePrototypeMethods.size() == 1 ) {
472-
mappingOptions.applyInheritedOptions(
473-
first( applicableReversePrototypeMethods ).getMappingOptions(),
474-
true,
475-
method,
476-
messager,
477-
typeFactory );
478-
}
479-
else if ( applicableReversePrototypeMethods.size() > 1 ) {
480-
messager.printMessage(
481-
method.getExecutable(),
482-
Message.INHERITINVERSECONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH,
483-
Strings.join( applicablePrototypeMethods, ", " ) );
476+
if ( inheritanceStrategy.isApplyReverse() ) {
477+
if ( applicableReversePrototypeMethods.size() == 1 ) {
478+
mappingOptions.applyInheritedOptions(
479+
first( applicableReversePrototypeMethods ).getMappingOptions(),
480+
true,
481+
method,
482+
messager,
483+
typeFactory );
484+
}
485+
else if ( applicableReversePrototypeMethods.size() > 1 ) {
486+
messager.printMessage(
487+
method.getExecutable(),
488+
Message.INHERITINVERSECONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH,
489+
Strings.join( applicableReversePrototypeMethods, ", " ) );
490+
}
484491
}
485492
}
486493

processor/src/main/java/org/mapstruct/ap/internal/util/Message.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public enum Message {
4747
PROPERTYMAPPING_DUPLICATE_TARGETS( "Target property \"%s\" must not be mapped more than once." ),
4848
PROPERTYMAPPING_EMPTY_TARGET( "Target must not be empty in @Mapping." ),
4949
PROPERTYMAPPING_SOURCE_AND_CONSTANT_BOTH_DEFINED( "Source and constant are both defined in @Mapping, either define a source or a constant." ),
50+
PROPERTYMAPPING_SOURCE_AND_IGNORE_BOTH_DEFINED( "Source and ignore are both defined in @Mapping, make explicit in reverse mapping when the intent is to ignore the reverse mapping." ),
5051
PROPERTYMAPPING_SOURCE_AND_EXPRESSION_BOTH_DEFINED( "Source and expression are both defined in @Mapping, either define a source or an expression." ),
5152
PROPERTYMAPPING_EXPRESSION_AND_CONSTANT_BOTH_DEFINED( "Expression and constant are both defined in @Mapping, either define an expression or a constant." ),
5253
PROPERTYMAPPING_EXPRESSION_AND_DEFAULT_VALUE_BOTH_DEFINED( "Expression and default value are both defined in @Mapping, either define a defaultValue or an expression." ),
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.bugs._1255;
20+
21+
/**
22+
*
23+
* @author Sjaak Derksen
24+
*/
25+
public abstract class AbstractA {
26+
27+
private String field1;
28+
29+
public String getField1() {
30+
return field1;
31+
}
32+
33+
public void setField1(String field1) {
34+
this.field1 = field1;
35+
}
36+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.bugs._1255;
20+
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.mapstruct.ap.testutil.IssueKey;
25+
import org.mapstruct.ap.testutil.WithClasses;
26+
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
27+
28+
/**
29+
*
30+
* @author Sjaak Derksen
31+
*/
32+
@IssueKey("1255")
33+
@RunWith(AnnotationProcessorTestRunner.class)
34+
@WithClasses({
35+
AbstractA.class,
36+
SomeA.class,
37+
SomeB.class,
38+
SomeMapper.class,
39+
SomeMapperConfig.class})
40+
public class Issue1255Test {
41+
42+
@Test
43+
public void shouldMapSomeBToSomeAWithoutField1() throws Exception {
44+
SomeB someB = new SomeB();
45+
someB.setField1( "value1" );
46+
someB.setField2( "value2" );
47+
48+
SomeA someA = SomeMapper.INSTANCE.toSomeA( someB );
49+
50+
assertThat( someA.getField1() )
51+
.isNotEqualTo( someB.getField1() )
52+
.isNull();
53+
assertThat( someA.getField2() ).isEqualTo( someB.getField2() );
54+
}
55+
56+
@Test
57+
public void shouldMapSomeAToSomeB() throws Exception {
58+
SomeA someA = new SomeA();
59+
someA.setField1( "value1" );
60+
someA.setField2( "value2" );
61+
62+
SomeB someB = SomeMapper.INSTANCE.toSomeB( someA );
63+
64+
assertThat( someB.getField1() ).isEqualTo( someA.getField1() );
65+
assertThat( someB.getField2() ).isEqualTo( someA.getField2() );
66+
}
67+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.bugs._1255;
20+
21+
/**
22+
*
23+
* @author Sjaak Derksen
24+
*/
25+
public class SomeA extends AbstractA {
26+
27+
private String field2;
28+
29+
public String getField2() {
30+
return field2;
31+
}
32+
33+
public void setField2(String field2) {
34+
this.field2 = field2;
35+
}
36+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.bugs._1255;
20+
21+
/**
22+
*
23+
* @author Sjaak Derksen
24+
*/
25+
public class SomeB {
26+
27+
private String field1;
28+
private String field2;
29+
30+
public String getField1() {
31+
return field1;
32+
}
33+
34+
public void setField1(String field1) {
35+
this.field1 = field1;
36+
}
37+
38+
public String getField2() {
39+
return field2;
40+
}
41+
42+
public void setField2(String field2) {
43+
this.field2 = field2;
44+
}
45+
}

0 commit comments

Comments
 (0)