Skip to content

Commit 58da2d2

Browse files
authored
mapstruct#695 user control over mapping means (direct, method, conversion, 2step)
1 parent 2d37610 commit 58da2d2

47 files changed

Lines changed: 1237 additions & 61 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/src/main/java/org/mapstruct/BeanMapping.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import java.lang.annotation.RetentionPolicy;
1212
import java.lang.annotation.Target;
1313

14+
import org.mapstruct.control.MappingControl;
15+
1416
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
1517

1618
/**
@@ -156,4 +158,18 @@ NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy()
156158
* @since 1.3
157159
*/
158160
Builder builder() default @Builder;
161+
162+
/**
163+
* Allows detailed control over the mapping process.
164+
*
165+
* @return the mapping control
166+
*
167+
* @since 1.4
168+
*
169+
* @see org.mapstruct.control.DeepClone
170+
* @see org.mapstruct.control.NoComplexMapping
171+
* @see org.mapstruct.control.MappingControl
172+
*/
173+
Class<? extends Annotation> mappingControl() default MappingControl.class;
174+
159175
}

core/src/main/java/org/mapstruct/IterableMapping.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import java.lang.annotation.Retention;
1111
import java.lang.annotation.RetentionPolicy;
1212
import java.lang.annotation.Target;
13-
import java.text.SimpleDateFormat;
1413
import java.text.DecimalFormat;
14+
import java.text.SimpleDateFormat;
1515
import java.util.Date;
1616

17+
import org.mapstruct.control.MappingControl;
18+
1719
/**
1820
* Configures the mapping between two iterable like types, e.g. {@code List<String>} and {@code List<Date>}.
1921
*
@@ -121,4 +123,18 @@
121123
* @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapping.
122124
*/
123125
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL;
126+
127+
/**
128+
* Allows detailed control over the mapping process.
129+
*
130+
* @return the mapping control
131+
*
132+
* @since 1.4
133+
*
134+
* @see org.mapstruct.control.DeepClone
135+
* @see org.mapstruct.control.NoComplexMapping
136+
* @see org.mapstruct.control.MappingControl
137+
*/
138+
Class<? extends Annotation> elementMappingControl() default MappingControl.class;
139+
124140
}

core/src/main/java/org/mapstruct/MapMapping.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import java.lang.annotation.Retention;
1111
import java.lang.annotation.RetentionPolicy;
1212
import java.lang.annotation.Target;
13-
import java.text.SimpleDateFormat;
1413
import java.text.DecimalFormat;
14+
import java.text.SimpleDateFormat;
1515
import java.util.Date;
1616

17+
import org.mapstruct.control.MappingControl;
18+
1719
/**
1820
* Configures the mapping between two map types, e.g. Map&lt;String, String&gt; and Map&lt;Long, Date&gt;.
1921
*
@@ -167,4 +169,32 @@
167169
* @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapping.
168170
*/
169171
NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL;
172+
173+
/**
174+
* Allows detailed control over the key mapping process.
175+
*
176+
* @return the mapping control
177+
*
178+
* @since 1.4
179+
180+
* @see org.mapstruct.control.DeepClone
181+
* @see org.mapstruct.control.NoComplexMapping
182+
* @see org.mapstruct.control.MappingControl
183+
*/
184+
Class<? extends Annotation> keyMappingControl() default MappingControl.class;
185+
186+
187+
/**
188+
* Allows detailed control over the value mapping process.
189+
*
190+
* @return the mapping control
191+
*
192+
* @since 1.4
193+
*
194+
* @see org.mapstruct.control.DeepClone
195+
* @see org.mapstruct.control.NoComplexMapping
196+
* @see org.mapstruct.control.MappingControl
197+
*/
198+
Class<? extends Annotation> valueMappingControl() default MappingControl.class;
199+
170200
}

core/src/main/java/org/mapstruct/Mapper.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
*/
66
package org.mapstruct;
77

8+
import java.lang.annotation.Annotation;
89
import java.lang.annotation.ElementType;
910
import java.lang.annotation.Retention;
1011
import java.lang.annotation.RetentionPolicy;
1112
import java.lang.annotation.Target;
1213

14+
import org.mapstruct.control.MappingControl;
1315
import org.mapstruct.factory.Mappers;
1416

1517
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
@@ -281,4 +283,17 @@ NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() default
281283
* @since 1.3
282284
*/
283285
Builder builder() default @Builder;
286+
287+
/**
288+
* Allows detailed control over the mapping process.
289+
*
290+
* @return the mapping control
291+
*
292+
* @since 1.4
293+
*
294+
* @see org.mapstruct.control.DeepClone
295+
* @see org.mapstruct.control.NoComplexMapping
296+
* @see org.mapstruct.control.MappingControl
297+
*/
298+
Class<? extends Annotation> mappingControl() default MappingControl.class;
284299
}

core/src/main/java/org/mapstruct/MapperConfig.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
*/
66
package org.mapstruct;
77

8+
import java.lang.annotation.Annotation;
89
import java.lang.annotation.ElementType;
910
import java.lang.annotation.Retention;
1011
import java.lang.annotation.RetentionPolicy;
1112
import java.lang.annotation.Target;
1213

14+
import org.mapstruct.control.MappingControl;
1315
import org.mapstruct.factory.Mappers;
1416

1517
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
@@ -255,4 +257,19 @@ MappingInheritanceStrategy mappingInheritanceStrategy()
255257
* @since 1.3
256258
*/
257259
Builder builder() default @Builder;
260+
261+
/**
262+
* Allows detailed control over the mapping process.
263+
*
264+
* @return the mapping control
265+
*
266+
* @since 1.4
267+
*
268+
* @see org.mapstruct.control.DeepClone
269+
* @see org.mapstruct.control.NoComplexMapping
270+
* @see org.mapstruct.control.MappingControl
271+
*/
272+
Class<? extends Annotation> mappingControl() default MappingControl.class;
273+
258274
}
275+

core/src/main/java/org/mapstruct/Mapping.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import java.text.SimpleDateFormat;
1616
import java.util.Date;
1717

18+
import org.mapstruct.control.MappingControl;
19+
1820
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
1921

2022
/**
@@ -394,4 +396,19 @@
394396
NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy()
395397
default NullValuePropertyMappingStrategy.SET_TO_NULL;
396398

399+
/**
400+
* Allows detailed control over the mapping process.
401+
*
402+
* @return the mapping control
403+
*
404+
* @since 1.4
405+
*
406+
* @see org.mapstruct.control.DeepClone
407+
* @see org.mapstruct.control.NoComplexMapping
408+
* @see org.mapstruct.control.MappingControl
409+
*/
410+
Class<? extends Annotation> mappingControl() default MappingControl.class;
411+
412+
413+
397414
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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.control;
7+
8+
import java.lang.annotation.Retention;
9+
import java.lang.annotation.RetentionPolicy;
10+
11+
import org.mapstruct.util.Experimental;
12+
13+
/**
14+
* Clones a source type to a target type (assuming source and target are of the same type).
15+
*
16+
* @author Sjaak Derksen
17+
*
18+
* @since 1.4
19+
*/
20+
@Retention(RetentionPolicy.CLASS)
21+
@Experimental
22+
@MappingControl( MappingControl.Use.MAPPING_METHOD )
23+
public @interface DeepClone {
24+
}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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.control;
7+
8+
import java.lang.annotation.ElementType;
9+
import java.lang.annotation.Repeatable;
10+
import java.lang.annotation.Retention;
11+
import java.lang.annotation.RetentionPolicy;
12+
import java.lang.annotation.Target;
13+
14+
15+
/**
16+
* Controls which means of mapping are considered between the source and the target in mappings.
17+
*
18+
* <p>
19+
* There are several applications of <code>MappingControl</code> conceivable. One application, "deep cloning" is
20+
* explained below in the example.
21+
* </p>
22+
*
23+
* <p>
24+
* Another application is controlling so called "complex mappings", which are not always desirable and sometimes lead to
25+
* unexpected behaviour and prolonged compilation time.
26+
* </p>
27+
*
28+
* <p><strong>Example:</strong>Cloning of an object</p>
29+
* <p>
30+
* When all methods are allowed, MapStruct would make a shallow copy. It would take the <code>ShelveDTO</code> in
31+
* the <code>FridgeDTO</code> and directly enter that as target on the target <code>FridgeDTO</code>. By disabling all
32+
* other kinds of mappings apart from {@link MappingControl.Use#MAPPING_METHOD}, see {@link DeepClone} MapStruct is
33+
* forced to generate mapping methods all through the object graph `FridgeDTO` and hence create a deep clone.
34+
* </p>
35+
* <pre><code class='java'>
36+
* public class FridgeDTO {
37+
*
38+
* private ShelveDTO shelve;
39+
*
40+
* public ShelveDTO getShelve() {
41+
* return shelve;
42+
* }
43+
*
44+
* public void setShelve(ShelveDTO shelve) {
45+
* this.shelve = shelve;
46+
* }
47+
* }
48+
* </code></pre>
49+
* <pre><code class='java'>
50+
* public class ShelveDTO {
51+
*
52+
* private CoolBeerDTO coolBeer;
53+
*
54+
* public CoolBeerDTO getCoolBeer() {
55+
* return coolBeer;
56+
* }
57+
*
58+
* public void setCoolBeer(CoolBeerDTO coolBeer) {
59+
* this.coolBeer = coolBeer;
60+
* }
61+
* }
62+
* </code></pre>
63+
* <pre><code class='java'>
64+
* public class CoolBeerDTO {
65+
*
66+
* private String beerCount;
67+
*
68+
* public String getBeerCount() {
69+
* return beerCount;
70+
* }
71+
*
72+
* public void setBeerCount(String beerCount) {
73+
* this.beerCount = beerCount;
74+
* }
75+
* }
76+
* </code></pre>
77+
*
78+
* <pre><code class='java'>
79+
* &#64;Mapper(mappingControl = DeepClone.class)
80+
* public interface CloningMapper {
81+
*
82+
* CloningMapper INSTANCE = Mappers.getMapper( CloningMapper.class );
83+
*
84+
* FridgeDTO clone(FridgeDTO in);
85+
*
86+
* }
87+
* </code></pre>
88+
*
89+
* @author Sjaak Derksen
90+
*/
91+
@Retention(RetentionPolicy.CLASS)
92+
@Repeatable(MappingControls.class)
93+
@Target( ElementType.ANNOTATION_TYPE )
94+
@MappingControl( MappingControl.Use.DIRECT )
95+
@MappingControl( MappingControl.Use.BUILT_IN_CONVERSION )
96+
@MappingControl( MappingControl.Use.MAPPING_METHOD )
97+
@MappingControl( MappingControl.Use.COMPLEX_MAPPING )
98+
public @interface MappingControl {
99+
100+
Use value();
101+
102+
enum Use {
103+
104+
/**
105+
* Controls the mapping, allows for type conversion from source type to target type
106+
* <p>
107+
* Type conversions are typically supported directly in Java. The "toString()" is such an example,
108+
* which allows for mapping for instance a {@link java.lang.Number} type to a {@link java.lang.String}.
109+
* <p>
110+
* Please refer to the MapStruct guide for more info.
111+
*
112+
* @since 1.4
113+
*/
114+
BUILT_IN_CONVERSION,
115+
116+
/**
117+
* Controls the mapping from source to target type, allows mapping by calling:
118+
* <ol>
119+
* <li>A type conversion, passed into a mapping method</li>
120+
* <li>A mapping method, passed into a type conversion</li>
121+
* <li>A mapping method passed into another mapping method</li>
122+
* </ol>
123+
*
124+
* @since 1.4
125+
*/
126+
COMPLEX_MAPPING,
127+
/**
128+
* Controls the mapping, allows for a direct mapping from source type to target type.
129+
* <p>
130+
* This means if source type and target type are of the same type, MapStruct will not perform
131+
* any mappings anymore and assign the target to the source direct.
132+
* <p>
133+
* An exception are types from the package {@link java}, which will be mapped always directly.
134+
*
135+
* @since 1.4
136+
*/
137+
DIRECT,
138+
139+
/**
140+
* Controls the mapping, allows for Direct Mapping from source type to target type.
141+
* <p>
142+
* The mapping method can be either a custom referred mapping method, or a MapStruct built in
143+
* mapping method.
144+
*
145+
* @since 1.4
146+
*/
147+
MAPPING_METHOD
148+
}
149+
150+
}

0 commit comments

Comments
 (0)