0
# Configuration and Inheritance
1
2
Configuration sharing, inheritance patterns, and qualifier systems for managing complex mapping scenarios and reusable mapping configurations.
3
4
## Capabilities
5
6
### Configuration Inheritance
7
8
Methods for inheriting configuration from other mapping methods to reduce duplication and maintain consistency.
9
10
```java { .api }
11
/**
12
* Advises the code generator to apply the configuration from another mapping method to the annotated method as well.
13
*/
14
@Target(ElementType.METHOD)
15
@Retention(RetentionPolicy.CLASS)
16
@interface InheritConfiguration {
17
/** Name of the method to inherit the configuration from */
18
String name() default "";
19
}
20
21
/**
22
* Advises the code generator to apply the inverse configuration of the method specified via name().
23
*/
24
@Target(ElementType.METHOD)
25
@Retention(RetentionPolicy.CLASS)
26
@interface InheritInverseConfiguration {
27
/** Name of the method to inherit the inverse configuration from */
28
String name() default "";
29
}
30
```
31
32
**Usage Examples:**
33
34
```java
35
@Mapper
36
public interface ConfigurationInheritanceMapper {
37
// Base mapping configuration
38
@Mapping(source = "firstName", target = "name")
39
@Mapping(source = "birthDate", target = "dateOfBirth", dateFormat = "yyyy-MM-dd")
40
@Mapping(target = "id", ignore = true)
41
@Mapping(target = "version", constant = "1.0")
42
PersonDto toPersonDto(Person person);
43
44
// Inherit all configuration from toPersonDto
45
@InheritConfiguration(name = "toPersonDto")
46
@Mapping(target = "email", source = "emailAddress") // Additional mapping
47
DetailedPersonDto toDetailedPersonDto(Person person);
48
49
// Inherit inverse configuration (for reverse mapping)
50
@InheritInverseConfiguration(name = "toPersonDto")
51
Person toPerson(PersonDto personDto);
52
53
// Inherit and override specific mappings
54
@InheritConfiguration(name = "toPersonDto")
55
@Mapping(target = "name", source = "fullName") // Override inherited mapping
56
PersonSummaryDto toPersonSummaryDto(Person person);
57
}
58
```
59
60
### Mapping Inheritance Strategies
61
62
Strategies for controlling how configuration inheritance works in complex scenarios.
63
64
```java { .api }
65
/**
66
* Strategy for applying method-level configuration annotations of prototype methods.
67
*/
68
enum MappingInheritanceStrategy {
69
/** Only inherit configuration that is explicitly configured */
70
EXPLICIT,
71
72
/** Auto-inherit configuration from methods in @MapperConfig interface */
73
AUTO_INHERIT_FROM_CONFIG,
74
75
/** Auto-inherit reverse configuration from @MapperConfig interface */
76
AUTO_INHERIT_REVERSE_FROM_CONFIG,
77
78
/** Auto-inherit all configuration from @MapperConfig interface */
79
AUTO_INHERIT_ALL_FROM_CONFIG
80
}
81
```
82
83
**Usage Examples:**
84
85
```java
86
// Configuration interface
87
@MapperConfig(mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG)
88
public interface BaseConfig {
89
@Mapping(source = "createdAt", target = "created", dateFormat = "yyyy-MM-dd HH:mm:ss")
90
@Mapping(source = "updatedAt", target = "modified", dateFormat = "yyyy-MM-dd HH:mm:ss")
91
AuditableDto toAuditableDto(AuditableEntity entity);
92
}
93
94
// Mapper using the configuration
95
@Mapper(config = BaseConfig.class)
96
public interface UserMapper {
97
// Automatically inherits audit field mappings from BaseConfig
98
UserDto toUserDto(User user);
99
100
// Explicit inheritance override
101
@InheritConfiguration(name = "toAuditableDto")
102
@Mapping(source = "email", target = "emailAddress")
103
DetailedUserDto toDetailedUserDto(User user);
104
}
105
```
106
107
### Qualifier System
108
109
Annotation-based and string-based qualifiers for precise mapping method selection.
110
111
```java { .api }
112
/**
113
* Marks an annotation as a qualifier for mapping method selection.
114
*/
115
@Target(ElementType.ANNOTATION_TYPE)
116
@Retention(RetentionPolicy.CLASS)
117
@interface Qualifier {
118
}
119
120
/**
121
* String-based qualifier for mapping method selection.
122
*/
123
@Target({ElementType.TYPE, ElementType.METHOD})
124
@Retention(RetentionPolicy.CLASS)
125
@interface Named {
126
/** Qualifier name */
127
String value();
128
}
129
```
130
131
**Usage Examples:**
132
133
```java
134
// Custom qualifier annotations
135
@Qualifier
136
@Target(ElementType.METHOD)
137
@Retention(RetentionPolicy.CLASS)
138
public @interface ToDto {
139
}
140
141
@Qualifier
142
@Target(ElementType.METHOD)
143
@Retention(RetentionPolicy.CLASS)
144
public @interface ToEntity {
145
}
146
147
@Qualifier
148
@Target(ElementType.METHOD)
149
@Retention(RetentionPolicy.CLASS)
150
public @interface GermanTranslation {
151
}
152
153
@Mapper
154
public abstract class QualifierMapper {
155
// Main mapping methods
156
@Mapping(source = "title", target = "name", qualifiedBy = ToDto.class)
157
public abstract BookDto toBookDto(Book book);
158
159
@Mapping(source = "name", target = "title", qualifiedBy = ToEntity.class)
160
public abstract Book toBook(BookDto bookDto);
161
162
// Qualified helper methods
163
@ToDto
164
protected String formatTitleForDto(String title) {
165
return title != null ? title.toUpperCase() : null;
166
}
167
168
@ToEntity
169
protected String formatTitleForEntity(String name) {
170
return name != null ? name.toLowerCase() : null;
171
}
172
173
// String-based qualifiers
174
@Named("germanTitle")
175
protected String translateToGerman(String title) {
176
// Translation logic
177
return translateService.translate(title, "de");
178
}
179
180
@Named("englishTitle")
181
protected String translateToEnglish(String titel) {
182
return translateService.translate(titel, "en");
183
}
184
185
// Using string qualifiers
186
@Mapping(source = "title", target = "germanTitle", qualifiedByName = "germanTitle")
187
@Mapping(source = "title", target = "englishTitle")
188
MultiLanguageBookDto toMultiLanguageBookDto(Book book);
189
}
190
```
191
192
### Advanced Inheritance Patterns
193
194
Complex inheritance scenarios with multiple configuration sources.
195
196
**Usage Examples:**
197
198
```java
199
// Base configuration with common mappings
200
@MapperConfig
201
public interface CommonConfig {
202
@Mapping(target = "id", ignore = true)
203
@Mapping(target = "version", constant = "1.0")
204
@Mapping(source = "lastModified", target = "updated", dateFormat = "yyyy-MM-dd")
205
BaseDto toBaseDto(BaseEntity entity);
206
}
207
208
// Specific configuration extending base
209
@MapperConfig(uses = CommonConfig.class)
210
public interface AuditConfig {
211
@InheritConfiguration(name = "toBaseDto")
212
@Mapping(source = "createdBy", target = "creator")
213
@Mapping(source = "modifiedBy", target = "modifier")
214
AuditableDto toAuditableDto(AuditableEntity entity);
215
}
216
217
// Mapper with multiple inheritance levels
218
@Mapper(config = AuditConfig.class)
219
public interface DocumentMapper {
220
// Inherits from AuditConfig -> CommonConfig chain
221
@InheritConfiguration(name = "toAuditableDto")
222
@Mapping(source = "content", target = "body")
223
@Mapping(source = "title", target = "heading")
224
DocumentDto toDocumentDto(Document document);
225
226
// Selective inheritance with overrides
227
@InheritConfiguration(name = "toAuditableDto")
228
@Mapping(target = "version", constant = "2.0") // Override inherited constant
229
@Mapping(target = "summary", expression = "java(document.getContent().substring(0, 100))")
230
DocumentSummaryDto toDocumentSummaryDto(Document document);
231
}
232
```
233
234
### Conditional Configuration Inheritance
235
236
Using conditions with inherited configurations.
237
238
**Usage Examples:**
239
240
```java
241
@Mapper
242
public abstract class ConditionalInheritanceMapper {
243
// Base mapping with conditions
244
@Mapping(target = "email", conditionQualifiedByName = "hasValidEmail")
245
@Mapping(target = "phone", conditionQualifiedByName = "hasValidPhone")
246
public abstract ContactDto toContactDto(Person person);
247
248
// Inherit conditions and add new ones
249
@InheritConfiguration(name = "toContactDto")
250
@Mapping(target = "address", conditionExpression = "java(person.getAddress() != null)")
251
public abstract DetailedContactDto toDetailedContactDto(Person person);
252
253
// Condition methods
254
@Condition
255
@Named("hasValidEmail")
256
protected boolean hasValidEmail(String email) {
257
return email != null && email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
258
}
259
260
@Condition
261
@Named("hasValidPhone")
262
protected boolean hasValidPhone(String phone) {
263
return phone != null && phone.matches("\\d{10}");
264
}
265
}
266
```
267
268
### Configuration with Component Models
269
270
Inheritance patterns in dependency injection environments.
271
272
**Usage Examples:**
273
274
```java
275
// Spring configuration
276
@MapperConfig(componentModel = "spring")
277
public interface SpringConfig {
278
@Mapping(source = "createdAt", target = "timestamp", dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
279
TimestampedDto toTimestampedDto(TimestampedEntity entity);
280
}
281
282
// Spring mappers using shared configuration
283
@Mapper(config = SpringConfig.class)
284
public interface SpringUserMapper {
285
@InheritConfiguration
286
UserDto toUserDto(User user);
287
}
288
289
@Mapper(config = SpringConfig.class)
290
public interface SpringOrderMapper {
291
@InheritConfiguration
292
OrderDto toOrderDto(Order order);
293
}
294
295
// CDI configuration
296
@MapperConfig(componentModel = "cdi")
297
public interface CdiConfig {
298
@Mapping(target = "id", ignore = true)
299
@Mapping(source = "status", target = "state")
300
ProcessableDto toProcessableDto(ProcessableEntity entity);
301
}
302
303
@Mapper(config = CdiConfig.class)
304
public interface CdiDocumentMapper {
305
@InheritConfiguration
306
@Mapping(source = "title", target = "documentTitle")
307
DocumentDto toDocumentDto(Document document);
308
}
309
```
310
311
### Cross-Mapper Configuration Sharing
312
313
Sharing configuration across multiple mapper interfaces.
314
315
**Usage Examples:**
316
317
```java
318
// Shared mapping utilities
319
@MapperConfig
320
public interface MappingUtils {
321
@Named("formatCurrency")
322
default String formatCurrency(BigDecimal amount) {
323
return NumberFormat.getCurrencyInstance().format(amount);
324
}
325
326
@Named("parseDate")
327
default LocalDate parseDate(String dateString) {
328
return dateString != null ? LocalDate.parse(dateString) : null;
329
}
330
331
@Named("formatDate")
332
default String formatDate(LocalDate date) {
333
return date != null ? date.format(DateTimeFormatter.ISO_LOCAL_DATE) : null;
334
}
335
}
336
337
// Multiple mappers using shared utilities
338
@Mapper(config = MappingUtils.class)
339
public interface ProductMapper {
340
@Mapping(source = "price", target = "formattedPrice", qualifiedByName = "formatCurrency")
341
@Mapping(source = "releaseDate", target = "releaseDateString", qualifiedByName = "formatDate")
342
ProductDto toProductDto(Product product);
343
}
344
345
@Mapper(config = MappingUtils.class)
346
public interface OrderMapper {
347
@Mapping(source = "total", target = "totalFormatted", qualifiedByName = "formatCurrency")
348
@Mapping(source = "orderDateString", target = "orderDate", qualifiedByName = "parseDate")
349
OrderDto toOrderDto(Order order);
350
}
351
352
// Composite configuration
353
@MapperConfig(uses = {MappingUtils.class})
354
public interface EnhancedConfig {
355
@InheritConfiguration
356
@Mapping(target = "createdBy", expression = "java(getCurrentUser())")
357
AuditableDto toAuditableDto(AuditableEntity entity);
358
359
default String getCurrentUser() {
360
return SecurityContextHolder.getContext().getAuthentication().getName();
361
}
362
}
363
```