diff --git a/README.md b/README.md index 822e00428d92bc30ad235063b17e026207716a79..996cc02d49275dfcbee22029ffcd24e7d3c7e112 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ public class User { ```xml - 1.4.0 + 1.4.1 diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts index f0a6b10911f8ae81942ee0d2888c84dfda45dc10..a1f46d7695e066f36830afeba74f7807a4139c36 100644 --- a/docs/.vuepress/config.ts +++ b/docs/.vuepress/config.ts @@ -2,7 +2,9 @@ import { defineUserConfig } from "vuepress"; import type { DefaultThemeOptions } from "vuepress"; import recoTheme from "vuepress-theme-reco"; import { themeConfig } from './config/index' -import { umamiAnalyticsPlugin } from 'vuepress-plugin-umami-analytics' +import { sitemapPlugin } from '@vuepress/plugin-sitemap' +import { webpackBundler } from '@vuepress/bundler-webpack' +import { viteBundler } from '@vuepress/bundler-vite' export default defineUserConfig({ locales: { @@ -37,9 +39,9 @@ export default defineUserConfig({ } }, plugins: [ - umamiAnalyticsPlugin({ - id: '50be7a94-e1d7-4d49-a8db-67b17acaa0b3', - src: 'https://114.115.147.1/script.js' - }) - ] + sitemapPlugin({ + hostname: 'mapstruct.plus' + }), + ], + bundler: webpackBundler(), }); diff --git a/docs/README.md b/docs/README.md index c8ee02f3ad106cac9b4d1415346ec673792d8498..9334cd1c55ab08a8a4f329e81af2de85f80016f0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,8 +11,8 @@ bannerBrand: description: 可能是最简单最强大的Java Bean转换工具 tagline: Mapstruct Plus 是 Mapstruct 的增强工具,在 Mapstruct 的基础上,实现了自动生成 Mapper 接口的功能,并强化了部分功能,使 Java 类型转换更加便捷、优雅。 buttons: - - { text: 快速开始, link: '/introduction/quick-start' } - - { text: '常见问题', link: '/guide/faq', type: 'plain' } + - { text: 快速开始, link: '/introduction/quick-start.html' } + - { text: '常见问题', link: '/guide/faq.html', type: 'plain' } socialLinks: - { icon: 'LogoGithub', link: 'https://github.com/vuepress-reco/vuepress-theme-reco' } isShowTitleInHome: true @@ -62,18 +62,31 @@ footer: io.github.linpeilie mapstruct-plus-spring-boot-starter - 1.4.0-R1 + 1.4.1 ``` - gradle ```groovy -implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.0-R1' +implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.1' ``` ## 更新日志 +### 1.4.1 + +- feat: `AutoMapper` 注解增加 `mapperNameSuffix` 属性,支持配置生成的转换接口名称增加后缀,默认规则下生成的反向转换接口同时生效; +- feat : 适配 `Mapper` 注解的 `unmappedSourcePolicy`、`unmappedTargetPolicy`、`typeConversionPolicy`、`collectionMappingStrategy`、`nullValueMappingStrategy`、`nullValueIterableMappingStrategy`、`nullValuePropertyMappingStrategy`、`nullValueCheckStrategy`、`mappingControl` 属性; +- feat : 适配 `Mapping` 注解的 `constant`、`qualifiedBy`、`nullValueCheckStrategy`、`nullValuePropertyMappingStrategy`、`mappingControl`; +- feat : 适配 MapStruct 配置的 `typeConversionPolicy`、`collectionMappingStrategy`、`nullValueIterableMappingStrategy`、`nullValueMapMappingStrategy`、`nullValueCheckStrategy`、`mappingControl`、`unexpectedValueMappingException`、`suppressTimestampInGenerated` 属性; +- fix : 适配同一个模块中同类不同包生成类名冲突的问题; +- feat : `AutoMapping` 注解增加 `reverseConvertGenerate`,控制是否生成反向转换逻辑,适配更加复杂的应用场景; +- fix : 修复 `targetClass` 同时配置父类和子类时,转换规则冲突的问题; +- fix : 修复不同模块配置类、代理类类名冲突的问题; +- feat : `AutoMapper` 增加 `useEnums` 属性,支持手动配置转换时需要的枚举,解决跨模块枚举无法自动转换的问题; +- 优化转换接口生成逻辑; + ### 1.4.0 - **优化复杂对象转换逻辑,占用元空间更小!性能更快!** @@ -82,6 +95,12 @@ implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-s - [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63)`AutoMapping`、`ReverseAutoMapping` 支持 `qualifiedByName`、`conditionQualifiedByName` 和 `dependsOn` 属性 - [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z)`AutoMappings` 支持配置在方法上面 +> 升级 1.4.0 注意事项: +> - 1.4.0 及以后的版本,复杂对象比较依赖项目中生成的 `ConvertMapperAdapter`, +> 在多模块下,由于类加载机制只会加载一个的原因,可能会导致 [`NoSuchMethodError`](/guide/faq.html) 的异常, +> 当然,这个问题在之前也会有,几率可能低一些,所以多模块下,务必配置 `adapterPackage` 来避免该问题。 +> - Map 与对象的转换,还是依赖 hutool 中的类转换实现,如果需要该功能,需要额外引入 `hutool-core` 依赖包。 + ### 1.3.6 - 兼容内部类转换 @@ -89,12 +108,6 @@ implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-s - [issue#I8QPRO](https://gitee.com/easii/mapstruct-plus/issues/I8QPRO) : 框架自动生成的 AutoMapperConfig 和 AutoMapMapper 包和类名支持配置 - [issue#I8T7EF](https://gitee.com/easii/mapstruct-plus/issues/I8T7EF) : 支持在父类中配置的 AutoMapping 注解 - -### 1.3.5 - -- AutoMapping、ReverseAutoMapping 支持配置在方法上面; -- AutoMapping、ReverseAutoMapping 支持 defaultExpression 和 conditionExpression 属性 - …… ## 代码仓库 diff --git a/docs/en/README.md b/docs/en/README.md index 403c0b273f3d1c25528b60da3d99b5cbaccfae25..bbe6eaea2539e6318441c23ab57c608240e016ab 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -11,8 +11,8 @@ bannerBrand: description: Probably the simplest and most powerful Java Bean transformation tool tagline: MapStructPlus is an enhancement tool of MapStruct. On the basis of MapStruct, it realizes the function of automatically generating Mapper interface, and strengthens some functions, making Java type conversion more convenient and elegant. buttons: - - { text: Quick Start, link: '/en/introduction/quick-start' } - - { text: 'FAQ', link: '/en/guide/faq', type: 'plain' } + - { text: Quick Start, link: '/en/introduction/quick-start.html' } + - { text: 'FAQ', link: '/en/guide/faq.html', type: 'plain' } socialLinks: - { icon: 'LogoGithub', link: 'https://github.com/vuepress-reco/vuepress-theme-reco' } isShowTitleInHome: true @@ -58,18 +58,37 @@ fotter: io.github.linpeilie mapstruct-plus-spring-boot-starter - 1.4.0-R1 + 1.4.0 ``` - gradle ```groovy -implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.0-R1' +implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.0' ``` ## Change Log +### 1.4.1 + +Sure, here is the translated update document: + +--- + +### Updates + +- **feat**: Added the `mapperNameSuffix` attribute to the `AutoMapper` annotation. This supports adding a suffix to the generated conversion interface name, and the reverse conversion interface will be effective under the default rules. +- **feat**: Adapted the `Mapper` annotation to support the following attributes: `unmappedSourcePolicy`, `unmappedTargetPolicy`, `typeConversionPolicy`, `collectionMappingStrategy`, `nullValueMappingStrategy`, `nullValueIterableMappingStrategy`, `nullValuePropertyMappingStrategy`, `nullValueCheckStrategy`, and `mappingControl`. +- **feat**: Adapted the `Mapping` annotation to support the following attributes: `constant`, `qualifiedBy`, `nullValueCheckStrategy`, `nullValuePropertyMappingStrategy`, and `mappingControl`. +- **feat**: Adapted MapStruct configuration to support the following attributes: `typeConversionPolicy`, `collectionMappingStrategy`, `nullValueIterableMappingStrategy`, `nullValueMapMappingStrategy`, `nullValueCheckStrategy`, `mappingControl`, `unexpectedValueMappingException`, and `suppressTimestampInGenerated`. +- **fix**: Resolved the issue of class name conflicts generated in different packages within the same module. +- **feat**: Added the `reverseConvertGenerate` attribute to the `AutoMapping` annotation to control whether to generate reverse conversion logic, adapting to more complex application scenarios. +- **fix**: Fixed the issue of conversion rule conflicts when both parent and child classes are configured in `targetClass`. +- **fix**: Resolved class name conflicts of configuration classes and proxy classes in different modules. +- **feat**: Added the `useEnums` attribute to `AutoMapper`, supporting manual configuration of required enums for conversion, solving the issue of automatic conversion of enums across modules. +- Optimized the logic for generating conversion interfaces. + ### 1.4.0 - **Optimize complex object conversion logic, take up less meta-space! and faster!** @@ -78,6 +97,14 @@ implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-s - [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63) `AutoMapping`、`ReverseAutoMapping` supports `qualifiedByName`,`conditionQualifiedByName`,and `dependsOn` properties. - [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z) `AutoMappings` supports configuration on methods. +> Points to note for upgrading 1.4.0 +> - 1.4.0 and later versions, complex object comparisons reply on `ConvertMapperAdapter` generated in the project, + which may cause [`NoSuchMethodError`](/guide/faq.html) exceptions under multiple modules because the Class Loading mechanism + will load only one, of course, this problem has been around before, and the odds are probably lower, + so be sure to configure the `adapterPackage` to avoid this problem with multiple modules. +> - Map to object conversions still rely on class conversions in hutool, and additional `hutool-core` dependencies need to be introduced if this + functionality is required. + ### 1.3.6 - Compatible with internal class conversion. @@ -85,11 +112,6 @@ implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-s - AutoMapperConfig and AutoMapMapperConfig package and class name generated automatically by the framework support configuration. - Supports AutoMapping annotations configured in the parent class. -### 1.3.5 - -- `@AutoMapping`、`@ReversedAutoMapping` support is configured on top of methods. -- `@AutoMapping`、`@ReverseAutoMapping` support the defaultExpression and conditionExpression properties - …… ## Code Warehouse diff --git a/docs/en/guide/configuration.md b/docs/en/guide/configuration.md index 0eab1720e63d6aa656e056419572e90a9c03dc3a..6cc797049f68ec0901cf33a5260df96a026cd257 100644 --- a/docs/en/guide/configuration.md +++ b/docs/en/guide/configuration.md @@ -191,3 +191,91 @@ eg: - **Type**:`String` - **Default**:AutoMapMapperConfig - **Compile Parameter**:`-Amapstruct.plus.autoMapMapperConfigClassName` + +### typeConversionPolicy + +> since `1.4.1` + +- **Description**:How lossy (narrowing) conversion, for instance: long to integer should be reported. +- **Type**:`ReportingPolicy` +- **Optional**: + - `IGNORE` + - `WARN` + - `ERROR` +- **Default**:`IGNORE` +- **Compile Parameter**:`-Amapstruct.plus.typeConversionPolicy` + +### collectionMappingStrategy + +> since `1.4.1` + +- **Description**:The strategy to be applied when propagating the value of collection-typed properties. By default, only JavaBeans accessor methods (setters or getters) will be used, but it is also possible to invoke a corresponding adder method for each element of the source collection (e. g. orderDto. +- **Type**:`CollectionMappingStrategy` +- **Optional**: + - `ACCESSOR_ONLY` + - `SETTER_PREFERRED` + - `ADDER_PREFERRED` + - `TARGET_IMMUTABLE` +- **Default**:`ACCESSOR_ONLY` +- **Compile Parameter**:`-Amapstruct.plus.collectionMappingStrategy` + +### nullValueIterableMappingStrategy + +> since `1.4.1` + +- **Description**:The strategy to be applied when null is passed as source argument value to an IterableMapping. If no strategy is configured, the strategy given via `nullValueMappingStrategy()` will be applied, using `NullValueMappingStrategy`.`RETURN_NULL` by default. +- **Type**:`NullValueMappingStrategy` +- **Optional**: + - `RETURN_NULL` + - `RETURN_DEFAULT` +- **Default**:`RETURN_NULL` +- **Compile Parameter**:`-Amapstruct.plus.nullValueIterableMappingStrategy` + +### nullValueMapMappingStrategy + +> since `1.4.1` + +- **Description**:he strategy to be applied when null is passed as source argument value to a MapMapping. If no strategy is configured, the strategy given via `nullValueMappingStrategy()` will be applied, using `NullValueMappingStrategy`.`RETURN_NULL` by default. +- **Type**:`NullValueMappingStrategy` +- **Optional**: + - `RETURN_NULL` + - `RETURN_DEFAULT` +- **Default**:`RETURN_NULL` +- **Compile Parameter**:`-Amapstruct.plus.nullValueMapMappingStrategy` + +### nullValueCheckStrategy + +> since `1.4.1` + +- **Description**:Determines when to include a null check on the source property value of a bean mapping. +- **Type**:`NullValueCheckStrategy` +- **Optional**: + - `ON_IMPLICIT_CONVERSION` + - `ALWAYS` +- **Default**:`ON_IMPLICIT_CONVERSION` +- **Compile Parameter**:`-Amapstruct.plus.nullValueCheckStrategy` + +### mappingControl + +> since `1.4.1` + +- **Description**:Allows detailed control over the mapping process. +- **Type**:`Class` +- **Default**:`MappingControl.class` + +### unexpectedValueMappingException + +> since `1.4.1` + +- **Description**:Exception that should be thrown by the generated code if no mapping matches for enums. If no exception is configured, IllegalArgumentException will be used by default. +- **Type**:`Class` +- **Default**:`IllegalArgumentException.class` + +### suppressTimestampInGenerated + +> since `1.4.1` + +- **Description**:Flag indicating whether the addition of a time stamp in the @Generated annotation should be suppressed. i. e. not be added. The method overrides the flag set through an annotation processor option. +- **Type**:`boolean` +- **Default**:`false` +- **Compile Parameter**:`-Amapstruct.plus.suppressTimestampInGenerated` \ No newline at end of file diff --git a/docs/en/guide/enum-convert.md b/docs/en/guide/enum-convert.md index a1ec42ebbe261d0a51a824f7fb2919e4d8a88edf..eea6aa79c65477d33e6d0b5817fbe29a7cf4d85d 100644 --- a/docs/en/guide/enum-convert.md +++ b/docs/en/guide/enum-convert.md @@ -75,3 +75,13 @@ public void enumMapTest() { } ``` +### Cross-Module Support + +When enums and the types they are used with are not in the same module, they cannot be automatically converted and require specified dependency relationships. + +In the `AutoMapper` annotation, you can specify the enum class list needed for the current conversion relationship through the `useEnums` attribute. These enums need to be annotated with `AutoEnumMapper`. + +> This feature is supported starting from version 1.4.1. + +It is important to note that when two classes are in the same module, specification is not required, and they can be automatically converted. This feature mainly addresses the issue of inability to automatically convert between different modules. + diff --git a/docs/en/release/log.md b/docs/en/release/log.md index 16e2c73c88907306c6d80e7e9d79a0924f81d52d..0a23155ef8cae3309f8a7ea343191fde61b56a97 100644 --- a/docs/en/release/log.md +++ b/docs/en/release/log.md @@ -6,6 +6,19 @@ category: description: MapStructPlus release log --- +### 1.4.1 + +- **feat**: Added the `mapperNameSuffix` attribute to the `AutoMapper` annotation. This supports adding a suffix to the generated conversion interface name, and the reverse conversion interface will be effective under the default rules. +- **feat**: Adapted the `Mapper` annotation to support the following attributes: `unmappedSourcePolicy`, `unmappedTargetPolicy`, `typeConversionPolicy`, `collectionMappingStrategy`, `nullValueMappingStrategy`, `nullValueIterableMappingStrategy`, `nullValuePropertyMappingStrategy`, `nullValueCheckStrategy`, and `mappingControl`. +- **feat**: Adapted the `Mapping` annotation to support the following attributes: `constant`, `qualifiedBy`, `nullValueCheckStrategy`, `nullValuePropertyMappingStrategy`, and `mappingControl`. +- **feat**: Adapted MapStruct configuration to support the following attributes: `typeConversionPolicy`, `collectionMappingStrategy`, `nullValueIterableMappingStrategy`, `nullValueMapMappingStrategy`, `nullValueCheckStrategy`, `mappingControl`, `unexpectedValueMappingException`, and `suppressTimestampInGenerated`. +- **fix**: Resolved the issue of class name conflicts generated in different packages within the same module. +- **feat**: Added the `reverseConvertGenerate` attribute to the `AutoMapping` annotation to control whether to generate reverse conversion logic, adapting to more complex application scenarios. +- **fix**: Fixed the issue of conversion rule conflicts when both parent and child classes are configured in `targetClass`. +- **fix**: Resolved class name conflicts of configuration classes and proxy classes in different modules. +- **feat**: Added the `useEnums` attribute to `AutoMapper`, supporting manual configuration of required enums for conversion, solving the issue of automatic conversion of enums across modules. +- Optimized the logic for generating conversion interfaces. + ### 1.4.0 - **Optimize complex object conversion logic, take up less meta-space! and faster!** @@ -14,6 +27,14 @@ description: MapStructPlus release log - [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63) `AutoMapping`、`ReverseAutoMapping` supports `qualifiedByName`,`conditionQualifiedByName`,and `dependsOn` properties. - [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z) `AutoMappings` supports configuration on methods. +> Points to note for upgrading 1.4.0 +> - 1.4.0 and later versions, complex object comparisons reply on `ConvertMapperAdapter` generated in the project, + which may cause [`NoSuchMethodError`](/guide/faq.html) exceptions under multiple modules because the Class Loading mechanism + will load only one, of course, this problem has been around before, and the odds are probably lower, + so be sure to configure the `adapterPackage` to avoid this problem with multiple modules. +> - Map to object conversions still rely on class conversions in hutool, and additional `hutool-core` dependencies need to be introduced if this + functionality is required. + ### 1.3.6 - Compatible with internal class conversion. diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index e24ee0eb972825787d362912670064cb48e77ba5..78f5080cbf166b9e5f574b366c3335e7c95a2c76 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -188,3 +188,91 @@ public class MapStructPlusConfiguration { - **类型**:`String` - **默认值**:AutoMapMapperConfig - **对应编译参数**:`-Amapstruct.plus.autoMapMapperConfigClassName` + +### typeConversionPolicy + +> since `1.4.1` + +- **说明**:有损转换的处理策略,例如:long 转换为 int +- **类型**:`ReportingPolicy` +- **支持配置项**: + - `IGNORE` + - `WARN` + - `ERROR` +- **默认值**:`IGNORE` +- **对应编译参数**:`-Amapstruct.plus.typeConversionPolicy` + +### collectionMappingStrategy + +> since `1.4.1` + +- **说明**:转换列表集合属性时的策略。 +- **类型**:`CollectionMappingStrategy` +- **支持配置项**: + - `ACCESSOR_ONLY` + - `SETTER_PREFERRED` + - `ADDER_PREFERRED` + - `TARGET_IMMUTABLE` +- **默认值**:`ACCESSOR_ONLY` +- **对应编译参数**:`-Amapstruct.plus.collectionMappingStrategy` + +### nullValueIterableMappingStrategy + +> since `1.4.1` + +- **说明**:当将 `null` 作为源参数值传递给 `IterableMapping` 时要应用的策略。如果未配置策略,则将应用通过 `nullValueMappingStrategy()` 给出的策略。 +- **类型**:`NullValueMappingStrategy` +- **支持配置项**: + - `RETURN_NULL` + - `RETURN_DEFAULT` +- **默认值**:`RETURN_NULL` +- **对应编译参数**:`-Amapstruct.plus.nullValueIterableMappingStrategy` + +### nullValueMapMappingStrategy + +> since `1.4.1` + +- **说明**:当将 `null` 作为源参数值传递给 `MapMapping` 时要应用的策略。如果未配置策略,则将应用通过 `nullValueMappingStrategy()` 给出的策略。 +- **类型**:`NullValueMappingStrategy` +- **支持配置项**: + - `RETURN_NULL` + - `RETURN_DEFAULT` +- **默认值**:`RETURN_NULL` +- **对应编译参数**:`-Amapstruct.plus.nullValueMapMappingStrategy` + +### nullValueCheckStrategy + +> since `1.4.1` + +- **说明**:确定何时对 bean 映射的源属性值进行 null 检查。 +- **类型**:`NullValueCheckStrategy` +- **支持配置项**: + - `ON_IMPLICIT_CONVERSION` + - `ALWAYS` +- **默认值**:`ON_IMPLICIT_CONVERSION` +- **对应编译参数**:`-Amapstruct.plus.nullValueCheckStrategy` + +### mappingControl + +> since `1.4.1` + +- **说明**:允许对映射过程进行详细控制。 +- **类型**:`Class` +- **默认值**:`MappingControl.class` + +### unexpectedValueMappingException + +> since `1.4.1` + +- **说明**:如果枚举没有匹配的映射,则生成的代码应抛出异常。如果没有配置异常,则默认使用 IllegalArgumentException 。 +- **类型**:`Class` +- **默认值**:`IllegalArgumentException.class` + +### suppressTimestampInGenerated + +> since `1.4.1` + +- **说明**:标识是否应在 `@Generated` 注释中添加时间戳 +- **类型**:`boolean` +- **默认值**:`false` +- **对应编译参数**:`-Amapstruct.plus.suppressTimestampInGenerated` \ No newline at end of file diff --git a/docs/guide/enum-convert.md b/docs/guide/enum-convert.md index bfef27a3b3c5383d048de01a2ecbcbd4e9f03d6b..72663881d63652527e67b19dc9bdac607e41898d 100644 --- a/docs/guide/enum-convert.md +++ b/docs/guide/enum-convert.md @@ -6,6 +6,8 @@ category: description: MapStructPlus Map转为对象 map convert to class --- +## 枚举自动转换 + > 当前特性从 1.2.2 开始支持 当需要进行枚举转换时(例如枚举转换为编码值,或者由编码转换为枚举),可以在目标枚举添加 `@AutoEnumMapper` 注解, @@ -73,3 +75,12 @@ public void enumMapTest() { } ``` +## 跨模块支持 + +当枚举与要使用的类型,不在同一个模块(module)中时,并不能自动转换,需要指定依赖关系。 + +在 `AutoMapper` 注解中,可以通过属性 `useEnums` 来指定,当前转换关系,需要依赖的枚举类列表。这些枚举需要被 `AutoEnumMapper`注解。 + +> 该特性从 1.4.1 开始支持 + +需要注意的是,当两个类在同一个模块(module)中,无需指定,可以自动转换。当前特性主要解决跨模块之间不能自动转换的问题。 diff --git a/docs/release/log.md b/docs/release/log.md index cf7dc5d6517be26006af87976682b8f2949f6fe0..9d2f9ad35721f9b1c1b23fbd235e41807b526133 100644 --- a/docs/release/log.md +++ b/docs/release/log.md @@ -6,6 +6,19 @@ category: description: MapStructPlus release log --- +### 1.4.1 + +- feat: `AutoMapper` 注解增加 `mapperNameSuffix` 属性,支持配置生成的转换接口名称增加后缀,默认规则下生成的反向转换接口同时生效; +- feat : 适配 `Mapper` 注解的 `unmappedSourcePolicy`、`unmappedTargetPolicy`、`typeConversionPolicy`、`collectionMappingStrategy`、`nullValueMappingStrategy`、`nullValueIterableMappingStrategy`、`nullValuePropertyMappingStrategy`、`nullValueCheckStrategy`、`mappingControl` 属性; +- feat : 适配 `Mapping` 注解的 `constant`、`qualifiedBy`、`nullValueCheckStrategy`、`nullValuePropertyMappingStrategy`、`mappingControl`; +- feat : 适配 MapStruct 配置的 `typeConversionPolicy`、`collectionMappingStrategy`、`nullValueIterableMappingStrategy`、`nullValueMapMappingStrategy`、`nullValueCheckStrategy`、`mappingControl`、`unexpectedValueMappingException`、`suppressTimestampInGenerated` 属性; +- fix : 适配同一个模块中同类不同包生成类名冲突的问题; +- feat : `AutoMapping` 注解增加 `reverseConvertGenerate`,控制是否生成反向转换逻辑,适配更加复杂的应用场景; +- fix : 修复 `targetClass` 同时配置父类和子类时,转换规则冲突的问题; +- fix : 修复不同模块配置类、代理类类名冲突的问题; +- feat : `AutoMapper` 增加 `useEnums` 属性,支持手动配置转换时需要的枚举,解决跨模块枚举无法自动转换的问题; +- 优化转换接口生成逻辑; + ### 1.4.0 - **优化复杂对象转换逻辑,占用元空间更小!性能更快!** @@ -14,6 +27,14 @@ description: MapStructPlus release log - [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63)`AutoMapping`、`ReverseAutoMapping` 支持 `qualifiedByName`、`conditionQualifiedByName` 和 `dependsOn` 属性 - [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z)`AutoMappings` 支持配置在方法上面 + +> 升级 1.4.0 注意事项: +> - 1.4.0 及以后的版本,复杂对象比较依赖项目中生成的 `ConvertMapperAdapter`, + 在多模块下,由于类加载机制只会加载一个的原因,可能会导致 [`NoSuchMethodError`](/guide/faq.html) 的异常, + 当然,这个问题在之前也会有,几率可能低一些,所以多模块下,务必配置 `adapterPackage` 来避免该问题。 +> - Map 与对象的转换,还是依赖 hutool 中的类转换实现,如果需要该功能,需要额外引入 `hutool-core` 依赖包。 + + ### 1.3.6 - 兼容内部类转换 diff --git a/example/pom.xml b/example/pom.xml index 40528dea800e170f8074f921048ac8c630cd49ed..af6efcbffd25eaa178dc3746fb8602cac7575781 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -18,9 +18,10 @@ UTF-8 1.5.1.Final - 1.4.0 + 1.4.1 1.18.22 5.8.26 + 32.1.3-jre @@ -50,6 +51,11 @@ hutool-all ${hutool.version} + + com.google.guava + guava + ${guava.version} + diff --git a/example/spring-boot-with-lombok/pom.xml b/example/spring-boot-with-lombok/pom.xml index 81a92c8c0435d671e2e185371f4e50fd8a214baf..34776f9035ac196180372e68a48537ea8612868c 100644 --- a/example/spring-boot-with-lombok/pom.xml +++ b/example/spring-boot-with-lombok/pom.xml @@ -50,6 +50,10 @@ cn.hutool hutool-all + + com.google.guava + guava + diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/MapStructPlusConfiguration.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/MapStructPlusConfiguration.java index e9849a7e85bfce13687f9ee37b7e6e07813ab5c7..7e5302aa6d7fc5af639b7b33a808b7e7617b94f7 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/MapStructPlusConfiguration.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/MapStructPlusConfiguration.java @@ -1,12 +1,14 @@ package io.github.linpeilie; import io.github.linpeilie.annotations.MapperConfig; +import org.mapstruct.Builder; @MapperConfig(adapterClassName = "DemoConvertMapperAdapter", adapterPackage = "io.github.linpeilie.adapter", mapAdapterClassName = "DemoMapConvertMapperAdapter", autoConfigPackage = "cn.easii", autoMapperConfigClassName = "EasiiAutoMapperConfig", - autoMapMapperConfigClassName = "EasiiAutoMapMapperConfig") + autoMapMapperConfigClassName = "EasiiAutoMapMapperConfig", + builder = @Builder(disableBuilder = false)) public class MapStructPlusConfiguration { } diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/Titles.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/Titles.java index a30b35d9ad8246414531b49dfa67d822ea3c5908..3374568e256462a2c351c67c28e26107a41236b9 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/Titles.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/mapper/Titles.java @@ -13,6 +13,9 @@ public class Titles { if ("One Hundred Years of Solitude".equals(title)) { return "Cent ans de solitude"; } + if ("Default".equals(title)) { + return null; + } return "Inconnu et inconnu"; } diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/NoProperties.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/NoProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..3a7026001a30bba77fdfb014c3c88a6d611cebae --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/NoProperties.java @@ -0,0 +1,12 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me; + +/** + * @author Filip Hrisafov + */ +public class NoProperties { +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/WithProperties.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/WithProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..e503a504cec55b7f65d5b803f31c513aad517e24 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/WithProperties.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me; + +import io.github.linpeilie.annotations.AutoMapper; + +/** + * @author Filip Hrisafov + */ +@AutoMapper(target = NoProperties.class) +public class WithProperties { + + private String string; + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/array/Scientist.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/array/Scientist.java new file mode 100644 index 0000000000000000000000000000000000000000..cdc07a45c7a651251107bb2193bd8ef3767a9393 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/array/Scientist.java @@ -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 io.github.linpeilie.me.array; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = ScientistDto.class) +public class Scientist { + + //CHECKSTYLE:OFF + public String[] publicPublications; + public String[] publicPublicationYears; + //CHECKSTYLE:ON + private String name; + private String[] publications; + private String[] publicationYears; + + public Scientist(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String[] getPublications() { + return publications; + } + + public void setPublications(String[] publications) { + this.publications = publications; + } + + public String[] getPublicationYears() { + return publicationYears; + } + + public void setPublicationYears(String[] publicationYears) { + this.publicationYears = publicationYears; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/array/ScientistDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/array/ScientistDto.java new file mode 100644 index 0000000000000000000000000000000000000000..175e5daf369234f2e5359ebdac6701b5a7587e98 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/array/ScientistDto.java @@ -0,0 +1,50 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.array; + +public class ScientistDto { + + //CHECKSTYLE:OFF + public String[] publicPublications; + public int[] publicPublicationYears; + //CHECKSTYLE:ON + + private String name; + private String[] publications; + private int[] publicationYears; + + public ScientistDto() { + } + + public ScientistDto(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String[] getPublications() { + return publications; + } + + public void setPublications(String[] publications) { + this.publications = publications; + } + + public int[] getPublicationYears() { + return publicationYears; + } + + public void setPublicationYears(int[] publicationYears) { + this.publicationYears = publicationYears; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/Person.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/Person.java new file mode 100644 index 0000000000000000000000000000000000000000..54948df466ed4d0f9788cd3f504c58a603387b70 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/Person.java @@ -0,0 +1,55 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.bool; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = PersonDto.class, uses = YesNoMapper.class, reverseConvertGenerate = false) +public class Person { + + private Boolean married; + private Boolean engaged; + private YesNo divorced; + private YesNo widowed; + + public Boolean isMarried() { + return married; + } + + public void setMarried(Boolean married) { + this.married = married; + } + + // START: please note: deliberately ordered, first getEngaged, then isEngaged. + public Boolean getEngaged() { + return engaged; + } + + public Boolean isEngaged() { + return engaged != null && !engaged; + } + // END + + public void setEngaged(Boolean engaged) { + this.engaged = engaged; + } + + public YesNo getDivorced() { + return divorced; + } + + public void setDivorced(YesNo divorced) { + this.divorced = divorced; + } + + public YesNo getWidowed() { + return widowed; + } + + public void setWidowed(YesNo widowed) { + this.widowed = widowed; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/PersonDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/PersonDto.java new file mode 100644 index 0000000000000000000000000000000000000000..0768d893f41288b2a77a97d386450a5d4f158d45 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/PersonDto.java @@ -0,0 +1,47 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.bool; + +public class PersonDto { + + private String married; + private String engaged; + private String divorced; + private Boolean widowed; + + public String getMarried() { + return married; + } + + public void setMarried(String married) { + this.married = married; + } + + public String getEngaged() { + return engaged; + } + + public void setEngaged(String engaged) { + this.engaged = engaged; + } + + public String getDivorced() { + return divorced; + } + + public void setDivorced(String divorced) { + this.divorced = divorced; + } + + public Boolean getWidowed() { + return widowed; + } + + public void setWidowed(Boolean widowed) { + this.widowed = widowed; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/YesNo.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/YesNo.java new file mode 100644 index 0000000000000000000000000000000000000000..5389beb7fac76be5705d12ace72eb880e26b8975 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/YesNo.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.bool; + +/** + * @author Andreas Gudian + * + */ +public class YesNo { + private boolean yes; + + public YesNo(boolean yes) { + this.yes = yes; + } + + public boolean isYes() { + return yes; + } + + public void setYes(boolean yes) { + this.yes = yes; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/YesNoMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/YesNoMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..e5f8f2e9ec6752425cb055fd9f80128ec3ab0348 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/bool/YesNoMapper.java @@ -0,0 +1,28 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.bool; + +import org.mapstruct.Mapper; +import org.springframework.stereotype.Component; + +/** + * @author Andreas Gudian + * + */ +@Component +public class YesNoMapper { + public String toString(YesNo yesNo) { + if ( null != yesNo && yesNo.isYes() ) { + return "yes"; + } + + return "no"; + } + + public boolean toBool(YesNo yesNo) { + return ( null != yesNo && yesNo.isYes() ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/AbstractImmutableProduct.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/AbstractImmutableProduct.java new file mode 100644 index 0000000000000000000000000000000000000000..6ed77d1437aa0445f25e72691589324c40c629e5 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/AbstractImmutableProduct.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractBuilder; + +/** + * @author Filip Hrisafov + */ +public abstract class AbstractImmutableProduct { + + private final String name; + + public AbstractImmutableProduct(AbstractProductBuilder builder) { + this.name = builder.name; + } + + public String getName() { + return name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/AbstractProductBuilder.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/AbstractProductBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..8385b8de2ee837c2dabc50c213955458879a749a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/AbstractProductBuilder.java @@ -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 io.github.linpeilie.me.builder.abstractBuilder; + +public abstract class AbstractProductBuilder { + + protected String name; + + public AbstractProductBuilder name(String name) { + this.name = name; + return this; + } + + public abstract T build(); +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/ImmutableProduct.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/ImmutableProduct.java new file mode 100644 index 0000000000000000000000000000000000000000..4d445ef595586088f20030154f692d25b41bf53f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/ImmutableProduct.java @@ -0,0 +1,38 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractBuilder; + +public class ImmutableProduct extends AbstractImmutableProduct { + + private final Integer price; + + public ImmutableProduct(ImmutableProductBuilder builder) { + super( builder ); + this.price = builder.price; + } + + public static ImmutableProductBuilder builder() { + return new ImmutableProductBuilder(); + } + + public Integer getPrice() { + return price; + } + + public static class ImmutableProductBuilder extends AbstractProductBuilder { + private Integer price; + + public ImmutableProductBuilder price(Integer price) { + this.price = price; + return this; + } + + @Override + public ImmutableProduct build() { + return new ImmutableProduct( this ); + } + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/ProductDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/ProductDto.java new file mode 100644 index 0000000000000000000000000000000000000000..b1048d32fe95cf9f503d870534cdc627232279be --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractBuilder/ProductDto.java @@ -0,0 +1,38 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractBuilder; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = ImmutableProduct.class) +public class ProductDto { + private String name; + private Integer price; + + public ProductDto() { + } + + public ProductDto(String name, Integer price) { + this.name = name; + this.price = price; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getPrice() { + return price; + } + + public void setPrice(Integer price) { + this.price = price; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/Child.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/Child.java new file mode 100644 index 0000000000000000000000000000000000000000..43e765068e6611d95eb1eb4cf70252d2ba4f6117 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/Child.java @@ -0,0 +1,10 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractGenericTarget; + +public interface Child { + String getName(); +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ChildSource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ChildSource.java new file mode 100644 index 0000000000000000000000000000000000000000..c76df2e37e50d1c5af548bef06f6f9c718381962 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ChildSource.java @@ -0,0 +1,28 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractGenericTarget; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = ImmutableChild.class) +public class ChildSource { + private String name; + + public ChildSource() { + } + + public ChildSource(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ImmutableChild.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ImmutableChild.java new file mode 100644 index 0000000000000000000000000000000000000000..3f3ff932335473ddcbc550f49159a955012706d5 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ImmutableChild.java @@ -0,0 +1,35 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractGenericTarget; + +public class ImmutableChild implements Child { + private final String name; + + private ImmutableChild(Builder builder) { + this.name = builder.name; + } + + public static Builder builder() { + return new Builder(); + } + + public String getName() { + return name; + } + + public static class Builder { + private String name; + + public Builder name(String name) { + this.name = name; + return this; + } + + public ImmutableChild build() { + return new ImmutableChild( this ); + } + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ImmutableParent.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ImmutableParent.java new file mode 100644 index 0000000000000000000000000000000000000000..3229f0e16c72e7d4da4189f5b7d3f7853f221330 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ImmutableParent.java @@ -0,0 +1,63 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractGenericTarget; + +public class ImmutableParent implements Parent { + private final int count; + private final ImmutableChild child; + private final Child nonGenericChild; + + public ImmutableParent(Builder builder) { + this.count = builder.count; + this.child = builder.child; + this.nonGenericChild = builder.nonGenericChild; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public Child getNonGenericChild() { + return nonGenericChild; + } + + @Override + public int getCount() { + return count; + } + + @Override + public ImmutableChild getChild() { + return child; + } + + public static class Builder { + private int count; + private ImmutableChild child; + private Child nonGenericChild; + + public Builder count(int count) { + this.count = count; + return this; + } + + public Builder nonGenericChild(Child nonGenericChild) { + this.nonGenericChild = nonGenericChild; + return this; + } + + public Builder child(ImmutableChild child) { + this.child = child; + return this; + } + + public ImmutableParent build() { + return new ImmutableParent( this ); + } + + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/MutableChild.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/MutableChild.java new file mode 100644 index 0000000000000000000000000000000000000000..6bf2ebc28378fabaf6dded911ebc68a8eefc1b81 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/MutableChild.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractGenericTarget; + +public class MutableChild implements Child { + private String name; + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/MutableParent.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/MutableParent.java new file mode 100644 index 0000000000000000000000000000000000000000..8c3caeb12f37a0b18ae908f02b4dcf421c61635e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/MutableParent.java @@ -0,0 +1,39 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractGenericTarget; + +public class MutableParent implements Parent { + private int count; + private ImmutableChild child; + private Child nonGenericChild; + + @Override + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + @Override + public ImmutableChild getChild() { + return child; + } + + public void setChild(ImmutableChild child) { + this.child = child; + } + + @Override + public Child getNonGenericChild() { + return nonGenericChild; + } + + public void setNonGenericChild(Child nonGenericChild) { + this.nonGenericChild = nonGenericChild; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/Parent.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/Parent.java new file mode 100644 index 0000000000000000000000000000000000000000..72a0af61640bf1fee1e4b90ff1cf2bca47d82055 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/Parent.java @@ -0,0 +1,14 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.abstractGenericTarget; + +public interface Parent { + int getCount(); + + T getChild(); + + Child getNonGenericChild(); +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ParentSource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ParentSource.java new file mode 100644 index 0000000000000000000000000000000000000000..74271fc8ba359423c0989d09e34f32ac71c2102b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/abstractGenericTarget/ParentSource.java @@ -0,0 +1,44 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.builder.abstractGenericTarget; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; + +@AutoMappers({ + @AutoMapper(target = ImmutableParent.class), + @AutoMapper(target = MutableParent.class) +}) +public class ParentSource { + private int count; + private ChildSource child; + private ChildSource nonGenericChild; + + public ChildSource getNonGenericChild() { + return nonGenericChild; + } + + public void setNonGenericChild(ChildSource nonGenericChild) { + this.nonGenericChild = nonGenericChild; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public ChildSource getChild() { + return child; + } + + public void setChild(ChildSource child) { + this.child = child; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/BuilderFactoryMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/BuilderFactoryMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..088ec3459f6d02237e1a5077459a59ed32148776 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/BuilderFactoryMapper.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.factory; + +import org.mapstruct.Mapper; +import org.mapstruct.ObjectFactory; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +/** + * @author Filip Hrisafov + */ +@Component +public class BuilderFactoryMapper { + + @ObjectFactory + public Person.PersonBuilder personBuilder() { + return new Person.PersonBuilder( "Factory with @ObjectFactory" ); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/BuilderImplicitFactoryMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/BuilderImplicitFactoryMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..2a7ae854836d4150ad7a21b2ccf6aceb6b9e39b7 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/BuilderImplicitFactoryMapper.java @@ -0,0 +1,23 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.builder.factory; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +/** + * @author Filip Hrisafov + */ +@Component +public class BuilderImplicitFactoryMapper { + + public ImplicitPerson.PersonBuilder personBuilder() { + return new ImplicitPerson.PersonBuilder("Implicit Factory"); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/ImplicitPerson.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/ImplicitPerson.java new file mode 100644 index 0000000000000000000000000000000000000000..06853314ffeb6866bbc8c7b39b312ca78d3918f9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/ImplicitPerson.java @@ -0,0 +1,43 @@ +package io.github.linpeilie.me.builder.factory; + +public class ImplicitPerson { + + private final String name; + private final String source; + + protected ImplicitPerson(ImplicitPerson.PersonBuilder builder) { + this.name = builder.name; + this.source = builder.source; + } + + public String getName() { + return name; + } + + public String getSource() { + return source; + } + + public static ImplicitPerson.PersonBuilder builder() { + throw new UnsupportedOperationException( "Factory should be used" ); + } + + public static class PersonBuilder { + private String name; + private final String source; + + public PersonBuilder(String source) { + this.source = source; + } + + public ImplicitPerson.PersonBuilder name(String name) { + this.name = name; + return this; + } + + public ImplicitPerson build() { + return new ImplicitPerson( this ); + } + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/Person.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/Person.java new file mode 100644 index 0000000000000000000000000000000000000000..bfa2a0bcfe43529660a9cf86527ecc498b2b282c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/Person.java @@ -0,0 +1,50 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.factory; + +/** + * @author Filip Hrisafov + */ +public class Person { + + private final String name; + private final String source; + + protected Person(PersonBuilder builder) { + this.name = builder.name; + this.source = builder.source; + } + + public String getName() { + return name; + } + + public String getSource() { + return source; + } + + public static PersonBuilder builder() { + throw new UnsupportedOperationException( "Factory should be used" ); + } + + public static class PersonBuilder { + private String name; + private final String source; + + public PersonBuilder(String source) { + this.source = source; + } + + public PersonBuilder name(String name) { + this.name = name; + return this; + } + + public Person build() { + return new Person( this ); + } + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/PersonDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/PersonDto.java new file mode 100644 index 0000000000000000000000000000000000000000..9da83844b8cd34da3acc4c9f1b3e7c4072496569 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/builder/factory/PersonDto.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.builder.factory; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; + +/** + * @author Filip Hrisafov + */ +@AutoMappers({ + @AutoMapper(target = Person.class, uses = BuilderFactoryMapper.class, reverseConvertGenerate = false), + @AutoMapper(target = ImplicitPerson.class, uses = BuilderImplicitFactoryMapper.class, reverseConvertGenerate = false), +}) +public class PersonDto { + + private String name; + + public PersonDto(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/BaseMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/BaseMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..9e8173eda2e2530b1a9a93b36e0871ae544923e2 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/BaseMapper.java @@ -0,0 +1,244 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.mapstruct.AfterMapping; +import org.mapstruct.BeforeMapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.TargetType; +import org.springframework.stereotype.Component; + +/** + * @author Andreas Gudian + */ +@Component +public class BaseMapper { + + private static final List INVOCATIONS = new ArrayList(); + + @BeforeMapping + public void noArgsBeforeMapping() { + INVOCATIONS.add( new Invocation( "noArgsBeforeMapping" ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(Source source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + @Qualified + public void withSourceBeforeMappingQualified(Source source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(List source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + @Qualified + public void withSourceBeforeMappingQualified(List source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(Map source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + @Qualified + public void withSourceBeforeMappingQualified(Map source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); + } + + @BeforeMapping + public void withSourceAsObjectBeforeMapping(Object source) { + INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(Source source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(SourceEnum source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(List source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(Map source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(Source source, @MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(List source, @MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(Map source, + @MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetAsObjectBeforeMapping(@MappingTarget Object target) { + INVOCATIONS.add( new Invocation( "withTargetAsObjectBeforeMapping", target ) ); + } + + @AfterMapping + public void noArgsAfterMapping() { + INVOCATIONS.add( new Invocation( "noArgsAfterMapping" ) ); + } + + @AfterMapping + public void withSourceAfterMapping(Source source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAfterMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAfterMapping(List source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAfterMapping(Map source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAsObjectAfterMapping(Object source) { + INVOCATIONS.add( new Invocation( "withSourceAsObjectAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(Source source, @MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(List source, @MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(Map source, @MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + @Qualified + public void withTargetAfterMappingQualified(@MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + @Qualified + public void withTargetAfterMappingQualified(@MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + @Qualified + public void withTargetAfterMappingQualified(@MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) ); + } + + @AfterMapping + public void withTargetAsObjectAfterMapping(@MappingTarget Object target) { + INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) ); + } + + @AfterMapping + public void withTargetAndTargetTypeAfterMapping(@MappingTarget T target, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withTargetAndTargetTypeAfterMapping", target, targetClass ) ); + } + + public static List getInvocations() { + return INVOCATIONS; + } + + public static void reset() { + INVOCATIONS.clear(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ClassContainingCallbacks.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ClassContainingCallbacks.java new file mode 100644 index 0000000000000000000000000000000000000000..b441be016e9014f58b64ade59deffb82412f55bd --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ClassContainingCallbacks.java @@ -0,0 +1,243 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.mapstruct.AfterMapping; +import org.mapstruct.BeforeMapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.TargetType; +import org.springframework.stereotype.Component; + +/** + * @author Andreas Gudian + */ +@Component +public class ClassContainingCallbacks { + private static final List INVOCATIONS = new ArrayList(); + + @BeforeMapping + public void noArgsBeforeMapping() { + INVOCATIONS.add( new Invocation( "noArgsBeforeMapping" ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(Source source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + @Qualified + public void withSourceBeforeMappingQualified(Source source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(List source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + @Qualified + public void withSourceBeforeMappingQualified(List source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); + } + + @BeforeMapping + public void withSourceBeforeMapping(Map source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + + @BeforeMapping + @Qualified + public void withSourceBeforeMappingQualified(Map source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); + } + + @BeforeMapping + public void withSourceAsObjectBeforeMapping(Object source) { + INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(Source source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(SourceEnum source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(List source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(Map source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(Source source, @MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(List source, @MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withSourceAndTargetBeforeMapping(Map source, + @MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + + @BeforeMapping + public void withTargetAsObjectBeforeMapping(@MappingTarget Object target) { + INVOCATIONS.add( new Invocation( "withTargetAsObjectBeforeMapping", target ) ); + } + + @AfterMapping + public void noArgsAfterMapping() { + INVOCATIONS.add( new Invocation( "noArgsAfterMapping" ) ); + } + + @AfterMapping + public void withSourceAfterMapping(Source source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAfterMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAfterMapping(List source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAfterMapping(Map source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAsObjectAfterMapping(Object source) { + INVOCATIONS.add( new Invocation( "withSourceAsObjectAfterMapping", source ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(Source source, @MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(List source, @MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withSourceAndTargetAfterMapping(Map source, @MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + @Qualified + public void withTargetAfterMappingQualified(@MappingTarget Target target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + @Qualified + public void withTargetAfterMappingQualified(@MappingTarget List target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) ); + } + + @AfterMapping + public void withTargetAfterMapping(@MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + + @AfterMapping + @Qualified + public void withTargetAfterMappingQualified(@MappingTarget Map target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) ); + } + + @AfterMapping + public void withTargetAsObjectAfterMapping(@MappingTarget Object target) { + INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) ); + } + + @AfterMapping + public void withTargetAndTargetTypeAfterMapping(@MappingTarget T target, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withTargetAndTargetTypeAfterMapping", target, targetClass ) ); + } + + public static List getInvocations() { + return INVOCATIONS; + } + + public static void reset() { + INVOCATIONS.clear(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Invocation.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Invocation.java new file mode 100644 index 0000000000000000000000000000000000000000..9a46e9423e66f1e85d4744f7e68b6d945ce23069 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Invocation.java @@ -0,0 +1,71 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks; + +import java.util.Arrays; + +/** + * @author Andreas Gudian + */ +public class Invocation { + private final String methodName; + private final String arguments; + + public Invocation(String methodName, Object... arguments) { + this.methodName = methodName; + this.arguments = Arrays.toString( arguments ); + } + + public String getMethodName() { + return methodName; + } + + public String getArguments() { + return arguments; + } + + @Override + public String toString() { + return "Invocation [methodName=" + methodName + ", arguments=" + arguments + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ( ( arguments == null ) ? 0 : arguments.hashCode() ); + result = prime * result + ( ( methodName == null ) ? 0 : methodName.hashCode() ); + return result; + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( obj == null ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + Invocation other = (Invocation) obj; + if ( arguments == null ) { + if ( other.arguments != null ) { + return false; + } + } + else if ( !arguments.equals( other.arguments ) ) { + return false; + } + if ( methodName == null ) { + return other.methodName == null; + } + else { + return methodName.equals( other.methodName ); + } + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Qualified.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Qualified.java new file mode 100644 index 0000000000000000000000000000000000000000..e067ca70ae3eb210c947472b7a3f580633381449 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Qualified.java @@ -0,0 +1,17 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks; + +import org.mapstruct.Qualifier; + +/** + * @author Andreas Gudian + * + */ +@Qualifier +public @interface Qualified { + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..a650a39dbf4c58d8da0fe4c9f7e59499afe65c24 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Source.java @@ -0,0 +1,57 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.callbacks; + +import io.github.linpeilie.annotations.AutoMapper; + +/** + * @author Andreas Gudian + */ +@AutoMapper(target = Target.class, uses = {ClassContainingCallbacks.class, BaseMapper.class}) +public class Source { + private String foo; + + public String getFoo() { + return foo; + } + + public void setFoo(String foo) { + this.foo = foo; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((foo == null) ? 0 : foo.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Source other = (Source) obj; + if (foo == null) { + return other.foo == null; + } else { + return foo.equals(other.foo); + } + } + + @Override + public String toString() { + return "Source [foo=" + foo + "]"; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/SourceEnum.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/SourceEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..874605049678b8c2dc62e3ca25533e615f7d6398 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/SourceEnum.java @@ -0,0 +1,14 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks; + +/** + * @author Andreas Gudian + * + */ +public enum SourceEnum { + A, B, C; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..20c10199a20abfba5c40f7006e5640f3a4a93519 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/Target.java @@ -0,0 +1,54 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks; + +/** + * @author Andreas Gudian + */ +public class Target { + private String foo; + + public String getFoo() { + return foo; + } + + public void setFoo(String foo) { + this.foo = foo; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ( ( foo == null ) ? 0 : foo.hashCode() ); + return result; + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( obj == null ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + Target other = (Target) obj; + if ( foo == null ) { + return other.foo == null; + } + else { + return foo.equals( other.foo ); + } + } + + @Override + public String toString() { + return "Target [foo=" + foo + "]"; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/TargetEnum.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/TargetEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..c98141d3f31604fbfcb906567e19cd184b5db6d8 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/TargetEnum.java @@ -0,0 +1,14 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks; + +/** + * @author Andreas Gudian + * + */ +public enum TargetEnum { + A, B, C; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Address.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Address.java new file mode 100644 index 0000000000000000000000000000000000000000..342f1ddb3c06c6c13b70ecfcca897442dcc1859f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Address.java @@ -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 io.github.linpeilie.me.callbacks.ongeneratedmethods; + +import io.github.linpeilie.annotations.AutoMapper; +import org.mapstruct.ReportingPolicy; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = AddressDto.class, unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = CompanyMapperPostProcessing.class) +public class Address { + + private String addressLine; + private String town; + + public String getAddressLine() { + return addressLine; + } + + public void setAddressLine(String addressLine) { + this.addressLine = addressLine; + } + + public String getTown() { + return town; + } + + public void setTown(String town) { + this.town = town; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/AddressDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/AddressDto.java new file mode 100644 index 0000000000000000000000000000000000000000..73533f36591dda2ecec88406ba281b89cb2c7fa5 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/AddressDto.java @@ -0,0 +1,41 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks.ongeneratedmethods; + +/** + * + * @author Sjaak Derksen + */ +public class AddressDto { + + private int houseNumber; + private String street; + private String town; + + public int getHouseNumber() { + return houseNumber; + } + + public void setHouseNumber( int houseNumber ) { + this.houseNumber = houseNumber; + } + + public String getStreet() { + return street; + } + + public void setStreet( String street ) { + this.street = street; + } + + public String getTown() { + return town; + } + + public void setTown( String town ) { + this.town = town; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Company.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Company.java new file mode 100644 index 0000000000000000000000000000000000000000..cc0706e6fa239dbad9b1774368ab22be02fbef7d --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Company.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.callbacks.ongeneratedmethods; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.List; +import org.mapstruct.ReportingPolicy; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = CompanyDto.class, unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = CompanyMapperPostProcessing.class) +public class Company { + + private List employees; + + public List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/CompanyDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/CompanyDto.java new file mode 100644 index 0000000000000000000000000000000000000000..5e94b72353bfd27bc974b1f05515fa5e8ed9896c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/CompanyDto.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks.ongeneratedmethods; + +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class CompanyDto { + + private List employees; + + public List getEmployees() { + return employees; + } + + public void setEmployees( List employees ) { + this.employees = employees; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/CompanyMapperPostProcessing.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/CompanyMapperPostProcessing.java new file mode 100644 index 0000000000000000000000000000000000000000..ededd66b608c0eb63dddc8187273fdd97c2573ad --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/CompanyMapperPostProcessing.java @@ -0,0 +1,28 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks.ongeneratedmethods; + +import org.mapstruct.AfterMapping; +import org.mapstruct.MappingTarget; +import org.springframework.stereotype.Component; + +/** + * + * @author Sjaak Derksen + */ +@Component +public class CompanyMapperPostProcessing { + + @AfterMapping + public void toAddressDto(Address address, @MappingTarget AddressDto addressDto) { + String addressLine = address.getAddressLine(); + int separatorIndex = addressLine.indexOf( ";" ); + addressDto.setStreet( addressLine.substring( 0, separatorIndex ) ); + String houseNumber = addressLine.substring( separatorIndex + 1 ); + addressDto.setHouseNumber( Integer.parseInt( houseNumber ) ); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Employee.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Employee.java new file mode 100644 index 0000000000000000000000000000000000000000..b6011a53c72647e95881923ee42505d350e0511d --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/Employee.java @@ -0,0 +1,27 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.callbacks.ongeneratedmethods; + +import io.github.linpeilie.annotations.AutoMapper; +import org.mapstruct.ReportingPolicy; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = EmployeeDto.class, unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = CompanyMapperPostProcessing.class, mapperNameSuffix = "$1") +public class Employee { + + private Address address; + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/EmployeeDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/EmployeeDto.java new file mode 100644 index 0000000000000000000000000000000000000000..197a6bc4d65e58271599cb67923a763d12ac332c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/ongeneratedmethods/EmployeeDto.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.callbacks.ongeneratedmethods; + +/** + * + * @author Sjaak Derksen + */ +public class EmployeeDto { + + private AddressDto address; + + public AddressDto getAddress() { + return address; + } + + public void setAddress( AddressDto address ) { + this.address = address; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarDto.java new file mode 100644 index 0000000000000000000000000000000000000000..b727fdb37ba21420208ca913f29b878292968344 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarDto.java @@ -0,0 +1,16 @@ +package io.github.linpeilie.me.callbacks.typematching; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = CarEntity.class, uses = CarMapper.class) +public class CarDto extends Identifiable { + private int seatCount; + + public int getSeatCount() { + return seatCount; + } + + public void setSeatCount(int seatCount) { + this.seatCount = seatCount; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarEntity.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..b84e95b207e17ca65dd343db2e8c06572db89e8f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarEntity.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.callbacks.typematching; + +public class CarEntity extends Identifiable { + private int seatCount; + + public int getSeatCount() { + return seatCount; + } + + public void setSeatCount(int seatCount) { + this.seatCount = seatCount; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..e8b8fa2f1669faa809c812d3c1f26e7316622e7a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/CarMapper.java @@ -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 io.github.linpeilie.me.callbacks.typematching; + +import org.mapstruct.AfterMapping; +import org.mapstruct.BeforeMapping; +import org.mapstruct.MappingTarget; +import org.springframework.stereotype.Component; + +/** + * @author Andreas Gudian + */ +@Component +public class CarMapper { + + @AfterMapping + protected void neverMatched(ElectricCarDto electricDto) { + throw new RuntimeException("must not be called"); + } + + @AfterMapping + protected void neverMatched(@MappingTarget ElectricCarEntity electricEntity) { + throw new RuntimeException("must not be called"); + } + + @AfterMapping + protected void isCalled(@MappingTarget Object any) { + if (any instanceof CarEntity) { + CarEntity car = (CarEntity) any; + if (car.getSeatCount() == 0) { + car.setSeatCount(5); + } + } + } + + @AfterMapping + protected void incrementsTargetId(@MappingTarget Identifiable identifiable) { + identifiable.setId(identifiable.getId() + 1); + } + + @BeforeMapping + protected void incrementsSourceId(Identifiable identifiable) { + identifiable.setId(identifiable.getId() + 1); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/ElectricCarDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/ElectricCarDto.java new file mode 100644 index 0000000000000000000000000000000000000000..988d99f26732bafb9c01eb963c2703eca6ba8ef1 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/ElectricCarDto.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.callbacks.typematching; + +public class ElectricCarDto extends CarDto { + private long batteryCapacity; + + public long getBatteryCapacity() { + return batteryCapacity; + } + + public void setBatteryCapacity(long batteryCapacity) { + this.batteryCapacity = batteryCapacity; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/ElectricCarEntity.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/ElectricCarEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..d597152241d9ab40a099ee1295267582b9e273fb --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/ElectricCarEntity.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.callbacks.typematching; + +public class ElectricCarEntity extends Identifiable { + private long batteryCapacity; + + public long getBatteryCapacity() { + return batteryCapacity; + } + + public void setBatteryCapacity(long batteryCapacity) { + this.batteryCapacity = batteryCapacity; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/Identifiable.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/Identifiable.java new file mode 100644 index 0000000000000000000000000000000000000000..98dcb4aa10089c76add4454c5e673848c88342c1 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/callbacks/typematching/Identifiable.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.callbacks.typematching; + +public abstract class Identifiable { + private long id; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Colour.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Colour.java new file mode 100644 index 0000000000000000000000000000000000000000..1e71dfffa998d024b1404a53730e5ad7486b98c8 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Colour.java @@ -0,0 +1,10 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +public enum Colour { + RED, GREEN, BLUE; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..54bba0bf9c973c001fbbee6145ca78242968c848 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Source.java @@ -0,0 +1,204 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@AutoMapper(target = Target.class, uses = SourceTargetMapper.class) +public class Source { + + private List publicStringList; + + private List stringList; + private List otherStringList; + private ArrayList stringArrayList; + + private Set stringSet; + private HashSet stringHashSet; + + private Collection stringCollection; + + @AutoMapping(target = "integerCollection") + private List integerList; + + @AutoMapping(target = "set") + private Set integerSet; + + @AutoMapping(target = "anotherStringSet") + private Set anotherIntegerSet; + + private Set colours; + + private Map stringLongMap; + + private Map otherStringLongMap; + + @AutoMapping(target = "nonGenericMapStringtoLong") + private Map stringLongMapForNonGeneric; + + @AutoMapping(target = "stringListNoSetter") + private List stringList2; + + @AutoMapping(target = "stringListNoSetter2") + private Set stringSet2; + + private EnumSet enumSet; + + @AutoMapping(target = "nonGenericStringList") + private List stringList3; + + public List getPublicStringList() { + return publicStringList; + } + + public void setPublicStringList(List publicStringList) { + this.publicStringList = publicStringList; + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + public ArrayList getStringArrayList() { + return stringArrayList; + } + + public void setStringArrayList(ArrayList stringArrayList) { + this.stringArrayList = stringArrayList; + } + + public Set getStringSet() { + return stringSet; + } + + public void setStringSet(Set stringSet) { + this.stringSet = stringSet; + } + + public HashSet getStringHashSet() { + return stringHashSet; + } + + public void setStringHashSet(HashSet stringHashSet) { + this.stringHashSet = stringHashSet; + } + + public Collection getStringCollection() { + return stringCollection; + } + + public void setStringCollection(Collection stringCollection) { + this.stringCollection = stringCollection; + } + + public List getIntegerList() { + return integerList; + } + + public void setIntegerList(List integerList) { + this.integerList = integerList; + } + + public Set getIntegerSet() { + return integerSet; + } + + public void setIntegerSet(Set integerSet) { + this.integerSet = integerSet; + } + + public Set getAnotherIntegerSet() { + return anotherIntegerSet; + } + + public void setAnotherIntegerSet(Set anotherIntegerSet) { + this.anotherIntegerSet = anotherIntegerSet; + } + + public Set getColours() { + return colours; + } + + public void setColours(Set colours) { + this.colours = colours; + } + + public Map getStringLongMap() { + return stringLongMap; + } + + public void setStringLongMap(Map stringLongMap) { + this.stringLongMap = stringLongMap; + } + + public List getStringList2() { + return stringList2; + } + + public void setStringList2(List stringList2) { + this.stringList2 = stringList2; + } + + public List getOtherStringList() { + return otherStringList; + } + + public void setOtherStringList(List otherStringList) { + this.otherStringList = otherStringList; + } + + public Map getOtherStringLongMap() { + return otherStringLongMap; + } + + public void setOtherStringLongMap(Map otherStringLongMap) { + this.otherStringLongMap = otherStringLongMap; + } + + public Set getStringSet2() { + return stringSet2; + } + + public void setStringSet2(Set stringSet2) { + this.stringSet2 = stringSet2; + } + + public EnumSet getEnumSet() { + return enumSet; + } + + public void setEnumSet(EnumSet enumSet) { + this.enumSet = enumSet; + } + + public List getStringList3() { + return stringList3; + } + + public void setStringList3(List stringList3) { + this.stringList3 = stringList3; + } + + public Map getStringLongMapForNonGeneric() { + return stringLongMapForNonGeneric; + } + + public void setStringLongMapForNonGeneric(Map stringLongMapForNonGeneric) { + this.stringLongMapForNonGeneric = stringLongMapForNonGeneric; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/SourceTargetMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/SourceTargetMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..5137f3a41c14086b072c07f20aede443057ad997 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/SourceTargetMapper.java @@ -0,0 +1,20 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +import org.springframework.stereotype.Component; + +@Component +public class SourceTargetMapper { + + protected StringHolder toStringHolder(String string) { + return new StringHolder( string ); + } + + protected String toString(StringHolder string) { + return string.getString(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolder.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..88860e17e1735b032dd577937e9051bc9a9a7e3d --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolder.java @@ -0,0 +1,50 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +/** + * @author Andreas Gudian + * + */ +public class StringHolder { + private final String string; + + public StringHolder(String string) { + this.string = string; + } + + public String getString() { + return string; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ( ( string == null ) ? 0 : string.hashCode() ); + return result; + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( obj == null ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + StringHolder other = (StringHolder) obj; + if ( string == null ) { + return other.string == null; + } + else { + return string.equals( other.string ); + } + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolderArrayList.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolderArrayList.java new file mode 100644 index 0000000000000000000000000000000000000000..c19ebe04bbd4fadc4c51b2c015507eab6bb84b1b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolderArrayList.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +import java.util.ArrayList; + +/** + * @author Stefan May + */ +public class StringHolderArrayList extends ArrayList { + + private static final long serialVersionUID = 1L; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolderToLongMap.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolderToLongMap.java new file mode 100644 index 0000000000000000000000000000000000000000..4a0e9418693567d7de0278a3f2060a2f9468b59e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/StringHolderToLongMap.java @@ -0,0 +1,17 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +import java.util.HashMap; + +/** + * @author Stefan May + */ +public class StringHolderToLongMap extends HashMap { + + private static final long serialVersionUID = 1L; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..96e41584f5dc42bde02a724b985e6ed93d97a5bc --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/Target.java @@ -0,0 +1,197 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class Target { + + //CHECKSTYLE:OFF + public List publicStringList; + //CHECKSTYLE:On + + private List stringList; + private List otherStringList; + private ArrayList stringArrayList; + + private Set stringSet; + private HashSet stringHashSet; + + private Collection stringCollection; + + private Collection integerCollection; + + private Set anotherStringSet; + + private Set colours; + + private Map stringLongMap; + private Map otherStringLongMap; + + private List stringListNoSetter; + + private List stringListNoSetter2; + + @SuppressWarnings( "rawtypes" ) + private Set set; + + private EnumSet enumSet; + + private StringHolderArrayList nonGenericStringList; + + private StringHolderToLongMap nonGenericMapStringtoLong; + + public Target() { + otherStringLongMap = new HashMap<>(); + otherStringLongMap.put( "not-present-after-mapping", 42L ); + + otherStringList = new ArrayList<>(); + otherStringList.add( "not-present-after-mapping" ); + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + public ArrayList getStringArrayList() { + return stringArrayList; + } + + public void setStringArrayList(ArrayList stringArrayList) { + this.stringArrayList = stringArrayList; + } + + public Set getStringSet() { + return stringSet; + } + + public void setStringSet(Set stringSet) { + this.stringSet = stringSet; + } + + public HashSet getStringHashSet() { + return stringHashSet; + } + + public void setStringHashSet(HashSet stringHashSet) { + this.stringHashSet = stringHashSet; + } + + public Collection getStringCollection() { + return stringCollection; + } + + public void setStringCollection(Collection stringCollection) { + this.stringCollection = stringCollection; + } + + public Collection getIntegerCollection() { + return integerCollection; + } + + public void setIntegerCollection(Collection integerCollection) { + this.integerCollection = integerCollection; + } + + @SuppressWarnings("rawtypes") + public Set getSet() { + return set; + } + + @SuppressWarnings("rawtypes") + public void setSet(Set set) { + this.set = set; + } + + public Set getAnotherStringSet() { + return anotherStringSet; + } + + public void setAnotherStringSet(Set anotherStringSet) { + this.anotherStringSet = anotherStringSet; + } + + public void setColours(Set colours) { + this.colours = colours; + } + + public Set getColours() { + return colours; + } + + public Map getStringLongMap() { + return stringLongMap; + } + + public void setStringLongMap(Map stringLongMap) { + this.stringLongMap = stringLongMap; + } + + public List getStringListNoSetter() { + if ( stringListNoSetter == null ) { + stringListNoSetter = new ArrayList<>(); + } + return stringListNoSetter; + } + + public List getStringListNoSetter2() { + if ( stringListNoSetter2 == null ) { + stringListNoSetter2 = new ArrayList<>(); + } + return stringListNoSetter2; + } + + public Map getOtherStringLongMap() { + return otherStringLongMap; + } + + public void setOtherStringLongMap(Map otherStringLongMap) { + this.otherStringLongMap = otherStringLongMap; + } + + public List getOtherStringList() { + return otherStringList; + } + + public void setOtherStringList(List otherStringList) { + this.otherStringList = otherStringList; + } + + public EnumSet getEnumSet() { + return enumSet; + } + + public void setEnumSet(EnumSet enumSet) { + this.enumSet = enumSet; + } + + public StringHolderArrayList getNonGenericStringList() { + return nonGenericStringList; + } + + public void setNonGenericStringList(StringHolderArrayList nonGenericStringList) { + this.nonGenericStringList = nonGenericStringList; + } + + public StringHolderToLongMap getNonGenericMapStringtoLong() { + return nonGenericMapStringtoLong; + } + + public void setNonGenericMapStringtoLong(StringHolderToLongMap nonGenericMapStringtoLong) { + this.nonGenericMapStringtoLong = nonGenericMapStringtoLong; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/TestList.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/TestList.java new file mode 100644 index 0000000000000000000000000000000000000000..663627e3ed9343d6b50f68d60f6f8181dca819cb --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/TestList.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Sjaak Derksen + */ +public class TestList extends ArrayList { + + private static final long serialVersionUID = 1L; + + private static boolean addAllCalled = false; + + public static boolean isAddAllCalled() { + return addAllCalled; + } + + public static void setAddAllCalled(boolean addAllCalled) { + TestList.addAllCalled = addAllCalled; + } + + @Override + public boolean addAll(Collection c) { + addAllCalled = true; + return super.addAll( c ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/TestMap.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/TestMap.java new file mode 100644 index 0000000000000000000000000000000000000000..341a4e526165b44c0a025b14ff2840bfabb5756f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/TestMap.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Sjaak Derksen + */ +public class TestMap extends HashMap { + + private static final long serialVersionUID = 1L; + + private static boolean puttAllCalled = false; + + public static boolean isPuttAllCalled() { + return puttAllCalled; + } + + public static void setPuttAllCalled(boolean puttAllCalled) { + TestMap.puttAllCalled = puttAllCalled; + } + + @Override + public void putAll(Map m) { + puttAllCalled = true; + super.putAll( m ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/CatException.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/CatException.java new file mode 100644 index 0000000000000000000000000000000000000000..54f35229546af5df0c11edc38b125cb972de8478 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/CatException.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder; + +/** + * @author Sjaak Derksen + */ +public class CatException extends Exception { + + private static final long serialVersionUID = 1L; + + public CatException() { + } + + public CatException(String msg) { + super( msg ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/DogException.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/DogException.java new file mode 100644 index 0000000000000000000000000000000000000000..391892ca2abb73bf1bfd05e8aa193355b0f6ae58 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/DogException.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder; + +/** + * @author Sjaak Derksen + */ +public class DogException extends Exception { + + private static final long serialVersionUID = 1L; + + public DogException() { + } + + public DogException(String msg) { + super( msg ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/PetMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/PetMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..4935452cbb8e621c59439f5b17654de5feecd176 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/PetMapper.java @@ -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 io.github.linpeilie.me.collection.adder; + +import com.google.common.collect.ImmutableMap; +import io.github.linpeilie.me.collection.adder._target.IndoorPet; +import io.github.linpeilie.me.collection.adder._target.OutdoorPet; +import io.github.linpeilie.me.collection.adder._target.Pet; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.mapstruct.TargetType; +import org.springframework.stereotype.Component; + +/** + * @author Sjaak Derksen + */ +@Component +public class PetMapper { + + private static final Map PETS_TO_TARGET = ImmutableMap.builder() + .put( "rabbit", 1L ) + .put( "mouse", 2L ).build(); + + private static final Map PETS_TO_SOURCE = ImmutableMap.builder() + .put( 1L, "rabbit" ) + .put( 2L, "mouse" ) + .put( 3L, "cat" ) + .put( 4L, "dog" ).build(); + + /** + * method to be used when using an adder + * + * @param pet + * + * @return + * + * @throws CatException + * @throws DogException + */ + public Long toPet(String pet) throws CatException, DogException { + if ( "cat".equals( pet ) ) { + throw new CatException(); + } + else if ( "dog".equals( pet ) ) { + throw new DogException(); + } + return PETS_TO_TARGET.get( pet ); + } + + /** + * Method to be used when not using an adder + * + * @param pets + * + * @return + * + * @throws CatException + * @throws DogException + */ + public List toPets(List pets) throws CatException, DogException { + List result = new ArrayList<>(); + for ( String pet : pets ) { + result.add( toPet( pet ) ); + } + return result; + } + + @SuppressWarnings("unchecked") + public T toPet(String pet, @TargetType Class clazz) throws CatException, DogException { + if ( clazz == IndoorPet.class ) { + return (T) new IndoorPet( toPet( pet ) ); + } + if ( clazz == OutdoorPet.class ) { + return (T) new OutdoorPet( toPet( pet ) ); + } + return null; + } + + public List toSourcePets(List pets) throws CatException, DogException { + List result = new ArrayList<>(); + for ( Long pet : pets ) { + result.add( PETS_TO_SOURCE.get( pet ) ); + } + return result; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/TeethMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/TeethMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..94f0d3bc30a589d8696edd12af557019245a6ad0 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/TeethMapper.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.springframework.stereotype.Component; + +/** + * @author Sjaak Derksen + */ +@Component +public class TeethMapper { + + private static final Map TEETH = ImmutableMap.builder() + .put( "incisor", 1 ) + .put( "canine", 2 ) + .put( "moler", 3 ).build(); + + public Integer toTooth(String tooth) { + return TEETH.get( tooth ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/AdderUsageObserver.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/AdderUsageObserver.java new file mode 100644 index 0000000000000000000000000000000000000000..59992e4e2fb711afdabdeff20e733c70a24a4a6b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/AdderUsageObserver.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +/** + * @author Sjaak Derksen + */ +public class AdderUsageObserver { + + private AdderUsageObserver() { + } + + private static boolean used = false; + + public static boolean isUsed() { + return used; + } + + public static void setUsed(boolean used) { + AdderUsageObserver.used = used; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/IndoorPet.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/IndoorPet.java new file mode 100644 index 0000000000000000000000000000000000000000..55ee799bd97d18684a2a89f15745428ed0312513 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/IndoorPet.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +/** + * @author Sjaak Derksen + */ +public class IndoorPet extends Pet { + + private Long value; + + public IndoorPet(Long value) { + this.value = value; + } + + public Long getValue() { + return value; + } + + public void setValue(Long value) { + this.value = value; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/OutdoorPet.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/OutdoorPet.java new file mode 100644 index 0000000000000000000000000000000000000000..908948d3c27e6b5e14d396594e64b1a11bf78941 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/OutdoorPet.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +/** + * @author Sjaak Derksen + */ +public class OutdoorPet extends Pet { + + private Long value; + + public OutdoorPet(Long value) { + this.value = value; + } + + public Long getValue() { + return value; + } + + public void setValue(Long value) { + this.value = value; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Pet.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Pet.java new file mode 100644 index 0000000000000000000000000000000000000000..eeb456790ed10356352d511d1c423696cd8aabe3 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Pet.java @@ -0,0 +1,13 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +/** + * @author Sjaak Derksen + */ +public class Pet { + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..aea270ce82913c02b5ed8b963035db69308ac2aa --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target.java @@ -0,0 +1,46 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Sjaak Derksen + */ +public class Target { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets(List pets) { + this.pets = pets; + } + + public void addCat(Long cat) { + // dummy method to test selection mechanism + } + + public void addDog(Long cat) { + // dummy method to test selection mechanism + } + + public void addPets(Long cat) { + // dummy method to test selection mechanism + } + + public Long addPet(Long pet) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList<>(); + } + pets.add( pet ); + return pet; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target2.java new file mode 100644 index 0000000000000000000000000000000000000000..c78eaadb080b4522b559364e62d5e5cf5576c1a4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target2.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import io.github.linpeilie.me.collection.adder.source.Foo; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class Target2 { + + private List attributes = new ArrayList(); + + public Foo addAttribute( Foo foo ) { + attributes.add( foo ); + return foo; + } + + public List getAttributes() { + return attributes; + } + + public void setAttributes( List attributes ) { + this.attributes = attributes; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target3.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target3.java new file mode 100644 index 0000000000000000000000000000000000000000..78b1007f949b2533dbd524cf4589dcba53576cc3 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/Target3.java @@ -0,0 +1,38 @@ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +public class Target3 { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets(List pets) { + this.pets = pets; + } + + public void addCat(Long cat) { + // dummy method to test selection mechanism + } + + public void addDog(Long cat) { + // dummy method to test selection mechanism + } + + public void addPets(Long cat) { + // dummy method to test selection mechanism + } + + public Long addPet(Long pet) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList<>(); + } + pets.add( pet ); + return pet; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetDali.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetDali.java new file mode 100644 index 0000000000000000000000000000000000000000..2ce60814b80e2490421fa8d4cc2e9a9dadb3a70c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetDali.java @@ -0,0 +1,34 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Sjaak Derksen + */ +public class TargetDali { + + private List teeth; + + public List getTeeth() { + return teeth; + } + + public void setTeeth(List teeth) { + this.teeth = teeth; + } + + public void addTeeth(Integer tooth) { + AdderUsageObserver.setUsed( true ); + if ( teeth == null ) { + teeth = new ArrayList<>(); + } + teeth.add( tooth ); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetHuman.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetHuman.java new file mode 100644 index 0000000000000000000000000000000000000000..1050c13acbdbf1a4f6f05e535ab52521cc8f431c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetHuman.java @@ -0,0 +1,40 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Sjaak Derksen + */ +public class TargetHuman { + + private List teeth; + + public List getTeeth() { + return teeth; + } + + public void setTeeth(List teeth) { + this.teeth = teeth; + } + + public void addTooth(Integer pet) { + AdderUsageObserver.setUsed( true ); + if ( teeth == null ) { + teeth = new ArrayList<>(); + } + teeth.add( pet ); + } + + public void addTeeth(Integer tooth) { + if ( teeth == null ) { + teeth = new ArrayList<>(); + } + teeth.add( tooth ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetOnlyGetter.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetOnlyGetter.java new file mode 100644 index 0000000000000000000000000000000000000000..f8858235e974c6a69ea09bc620bad4f90a2de73c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetOnlyGetter.java @@ -0,0 +1,41 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Sjaak Derksen + */ +public class TargetOnlyGetter { + + private List pets; + + public List getPets() { + return pets; + } + + public void addCat(Long cat) { + // dummy method to test selection mechanism + } + + public void addDog(Long cat) { + // dummy method to test selection mechanism + } + + public void addPets(Long cat) { + // dummy method to test selection mechanism + } + + public void addPet(Long pet) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList<>(); + } + pets.add( pet ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetViaTargetType.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetViaTargetType.java new file mode 100644 index 0000000000000000000000000000000000000000..b7e83e3df646e9005ba8e9c6080c4be7e88cc575 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetViaTargetType.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Sjaak Derksen + */ +public class TargetViaTargetType { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets(List pets) { + this.pets = pets; + } + + public void addPet(IndoorPet pet) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList<>(); + } + pets.add( pet ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetWithAnimals.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetWithAnimals.java new file mode 100644 index 0000000000000000000000000000000000000000..f1c6e5a347b113963f580be356aeb6aadd991bba --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetWithAnimals.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Filip Hrisafov + */ +public class TargetWithAnimals { + + private List animals = new ArrayList<>(); + + public List getAnimals() { + return animals; + } + + public void setAnimals(List animals) { + this.animals = animals; + } + + public void addAnimal(String animal) { + animals.add( animal ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetWithoutSetter.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetWithoutSetter.java new file mode 100644 index 0000000000000000000000000000000000000000..432e9a7c6de152fff58327318dec90ad12dcd275 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/_target/TargetWithoutSetter.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder._target; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Sjaak Derksen + */ +public class TargetWithoutSetter { + + private List pets; + + public List getPets() { + return pets; + } + + public void addPet(Long pet) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList<>(); + } + pets.add( pet ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Foo.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Foo.java new file mode 100644 index 0000000000000000000000000000000000000000..b32bcc5962dc0bc232d27120a2dd7f7e1fdd2e63 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Foo.java @@ -0,0 +1,14 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.adder.source; + +/** + * + * @author Sjaak Derksen + */ +public class Foo { + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SingleElementSource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SingleElementSource.java new file mode 100644 index 0000000000000000000000000000000000000000..2c8ecf2c3bdac77f88e4085830843bf018dc1c24 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SingleElementSource.java @@ -0,0 +1,34 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.collection.adder.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.me.collection.adder.PetMapper; +import io.github.linpeilie.me.collection.adder.TeethMapper; +import io.github.linpeilie.me.collection.adder._target.Target; +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapping; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = Target.class, reverseConvertGenerate = false, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = { + PetMapper.class, TeethMapper.class}) +public class SingleElementSource { + + @AutoMapping(target = "pets") + private String pet; + + public String getPet() { + return pet; + } + + public void setPet(String pet) { + this.pet = pet; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..e229a4fe6eec461481af6cf2083c12d7dca09676 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source.java @@ -0,0 +1,46 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.collection.adder.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.me.collection.adder.PetMapper; +import io.github.linpeilie.me.collection.adder.TeethMapper; +import io.github.linpeilie.me.collection.adder._target.Target; +import io.github.linpeilie.me.collection.adder._target.TargetOnlyGetter; +import io.github.linpeilie.me.collection.adder._target.TargetViaTargetType; +import io.github.linpeilie.me.collection.adder._target.TargetWithoutSetter; +import java.util.List; +import org.mapstruct.CollectionMappingStrategy; + +/** + * @author Sjaak Derksen + */ +@AutoMappers({ + @AutoMapper(target = Target.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = { + PetMapper.class, TeethMapper.class}), + @AutoMapper(target = TargetOnlyGetter.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = { + PetMapper.class, TeethMapper.class}), + @AutoMapper(target = TargetViaTargetType.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = { + PetMapper.class, TeethMapper.class}, reverseConvertGenerate = false), + @AutoMapper(target = TargetWithoutSetter.class, + collectionMappingStrategy = CollectionMappingStrategy.SETTER_PREFERRED, + uses = {PetMapper.class} + ) +}) +public class Source { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets(List pets) { + this.pets = pets; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source2.java new file mode 100644 index 0000000000000000000000000000000000000000..aa980042e4bb4f21a940c7c6ecd648a6600fde57 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source2.java @@ -0,0 +1,32 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.collection.adder.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.me.collection.adder._target.Target2; +import java.util.List; +import org.mapstruct.CollectionMappingStrategy; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = Target2.class, + reverseConvertGenerate = false, + collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) +public class Source2 { + + private List attributes; + + public List getAttributes() { + return attributes; + } + + public void setAttributes(List attributes) { + this.attributes = attributes; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source3.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source3.java new file mode 100644 index 0000000000000000000000000000000000000000..d9d6068f3a0ca7674fba4b5740c75193366e59a6 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/Source3.java @@ -0,0 +1,20 @@ +package io.github.linpeilie.me.collection.adder.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.me.collection.adder.PetMapper; +import io.github.linpeilie.me.collection.adder._target.Target3; +import java.util.List; + +@AutoMapper(target = Target3.class, uses = PetMapper.class) +public class Source3 { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets(List pets) { + this.pets = pets; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SourceTeeth.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SourceTeeth.java new file mode 100644 index 0000000000000000000000000000000000000000..40af0a9dc8e32fce87fefa0a7db2eef18895359a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SourceTeeth.java @@ -0,0 +1,38 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.collection.adder.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.me.collection.adder.PetMapper; +import io.github.linpeilie.me.collection.adder.TeethMapper; +import io.github.linpeilie.me.collection.adder._target.TargetDali; +import io.github.linpeilie.me.collection.adder._target.TargetHuman; +import java.util.List; +import org.mapstruct.CollectionMappingStrategy; + +/** + * @author Sjaak Derksen + */ +@AutoMappers({ + @AutoMapper(target = TargetDali.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, + uses = {PetMapper.class, TeethMapper.class}), + @AutoMapper(target = TargetHuman.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, + uses = {PetMapper.class, TeethMapper.class}) +}) +public class SourceTeeth { + + private List teeth; + + public List getTeeth() { + return teeth; + } + + public void setTeeth(List teeth) { + this.teeth = teeth; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SourceWithPets.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SourceWithPets.java new file mode 100644 index 0000000000000000000000000000000000000000..4a7e6842d5f8fb12f3389c4ee83aa2ca6deb01f5 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/adder/source/SourceWithPets.java @@ -0,0 +1,32 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.collection.adder.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.me.collection.adder._target.TargetWithAnimals; +import java.util.List; +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapping; + +/** + * @author Filip Hrisafov + */ +@AutoMapper(target = TargetWithAnimals.class, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) +public class SourceWithPets { + + @AutoMapping(target = "animals") + private List pets; + + public List getPets() { + return pets; + } + + public void setPets(List pets) { + this.pets = pets; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/NoSetterSource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/NoSetterSource.java new file mode 100644 index 0000000000000000000000000000000000000000..6a77b9b5bc125b819b7db53e1b724af11852f73c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/NoSetterSource.java @@ -0,0 +1,39 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.defaultimplementation; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import java.util.List; +import java.util.Map; + +/** + * @author Andreas Gudian + * + */ +@AutoMappers({ + @AutoMapper(target = NoSetterTarget.class) +}) +public class NoSetterSource { + private List listValues; + private Map mapValues; + + public List getListValues() { + return listValues; + } + + public void setListValues(List listValues) { + this.listValues = listValues; + } + + public Map getMapValues() { + return mapValues; + } + + public void setMapValues(Map mapValues) { + this.mapValues = mapValues; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/NoSetterTarget.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/NoSetterTarget.java new file mode 100644 index 0000000000000000000000000000000000000000..ff301c8b4e39f289ba174a059a05686086d16069 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/NoSetterTarget.java @@ -0,0 +1,28 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.defaultimplementation; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Andreas Gudian + * + */ +public class NoSetterTarget { + private List listValues = new ArrayList(); + private Map mapValues = new HashMap(); + + public List getListValues() { + return listValues; + } + + public Map getMapValues() { + return mapValues; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..59bf3334e1aa29a8896653a7886c0050e3c20801 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/Source.java @@ -0,0 +1,30 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.defaultimplementation; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import java.util.List; +import org.mapstruct.Mapping; + +@AutoMappers({ + @AutoMapper(target = Target.class) +}) +public class Source { + + @AutoMapping(target = "fooListNoSetter") + private List fooList; + + public List getFooList() { + return fooList; + } + + public void setFooList(List fooList) { + this.fooList = fooList; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/SourceFoo.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/SourceFoo.java new file mode 100644 index 0000000000000000000000000000000000000000..9976ebcd1dfef25ae36acd519834a1ca8c6fcb3c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/SourceFoo.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.defaultimplementation; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = TargetFoo.class) +public class SourceFoo { + + private String name; + + public SourceFoo() { + } + + public SourceFoo(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..c5d0442a1da7d1c68639ae5b8741c9981be123d7 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/Target.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.defaultimplementation; + +import java.util.ArrayList; +import java.util.List; + +public class Target { + + private List fooListNoSetter; + + public List getFooListNoSetter() { + if ( fooListNoSetter == null ) { + fooListNoSetter = new ArrayList<>(); + } + return fooListNoSetter; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/TargetFoo.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/TargetFoo.java new file mode 100644 index 0000000000000000000000000000000000000000..cf033f11542a35597d6604cc03f6c5906eca8121 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/defaultimplementation/TargetFoo.java @@ -0,0 +1,59 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.defaultimplementation; + +public class TargetFoo implements Comparable { + + private String name; + + public TargetFoo() { + } + + public TargetFoo(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ( ( name == null ) ? 0 : name.hashCode() ); + return result; + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( obj == null ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + TargetFoo other = (TargetFoo) obj; + if ( name == null ) { + return other.name == null; + } + else { + return name.equals( other.name ); + } + } + + @Override + public int compareTo(TargetFoo o) { + return getName().compareTo( o.getName() ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Bar.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Bar.java new file mode 100644 index 0000000000000000000000000000000000000000..5031bf510fda16e6cb9cc8f470edd714af349aae --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Bar.java @@ -0,0 +1,14 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.forged; + +/** + * + * @author Sjaak Derksen + */ +public class Bar { + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Foo.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Foo.java new file mode 100644 index 0000000000000000000000000000000000000000..51f646736c5023ab065856ad2f4e331153a8c669 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Foo.java @@ -0,0 +1,14 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.forged; + +/** + * + * @author Sjaak Derksen + */ +public class Foo { + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..f5bec01aaed2e88b6835ade2468f92bd10689967 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Source.java @@ -0,0 +1,58 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.forged; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.Map; +import java.util.Set; + +@AutoMapper(target = Target.class) +public class Source { + + //CHECKSTYLE:OFF + public Set publicFooSet; + //CHECKSTYLE:ON + private Set fooSet; + private Set fooSet2; + + //CHECKSTYLE:OFF + public Map publicBarMap; + //CHECKSTYLE:ON + private Map barMap; + private Map barMap2; + + public Set getFooSet() { + return fooSet; + } + + public void setFooSet(Set fooSet) { + this.fooSet = fooSet; + } + + public Map getBarMap() { + return barMap; + } + + public void setBarMap(Map barMap) { + this.barMap = barMap; + } + + public Set getFooSet2() { + return fooSet2; + } + + public void setFooSet2( Set fooSet2 ) { + this.fooSet2 = fooSet2; + } + + public Map getBarMap2() { + return barMap2; + } + + public void setBarMap2( Map barMap2 ) { + this.barMap2 = barMap2; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Source1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Source1.java new file mode 100644 index 0000000000000000000000000000000000000000..f0f5fb7d2b7f11afb40659ab2a49ce7846f30687 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Source1.java @@ -0,0 +1,54 @@ +package io.github.linpeilie.me.collection.forged; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.Map; +import java.util.Set; +import org.mapstruct.NullValueMappingStrategy; + +@AutoMapper(target = Target1.class, nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT) +public class Source1 { + + //CHECKSTYLE:OFF + public Set publicFooSet; + //CHECKSTYLE:ON + private Set fooSet; + private Set fooSet2; + + //CHECKSTYLE:OFF + public Map publicBarMap; + //CHECKSTYLE:ON + private Map barMap; + private Map barMap2; + + public Set getFooSet() { + return fooSet; + } + + public void setFooSet(Set fooSet) { + this.fooSet = fooSet; + } + + public Map getBarMap() { + return barMap; + } + + public void setBarMap(Map barMap) { + this.barMap = barMap; + } + + public Set getFooSet2() { + return fooSet2; + } + + public void setFooSet2( Set fooSet2 ) { + this.fooSet2 = fooSet2; + } + + public Map getBarMap2() { + return barMap2; + } + + public void setBarMap2( Map barMap2 ) { + this.barMap2 = barMap2; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..f9f35e379eb38c335caf180b19bb000a3a7676bf --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Target.java @@ -0,0 +1,68 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.forged; + +import java.util.Map; +import java.util.Set; + +public class Target { + + private Set fooSet; + private Set fooSet2; + private Map barMap; + private Map barMap2; + + private Set publicFooSet; + private Map publicBarMap; + + public Set getFooSet() { + return fooSet; + } + + public void setFooSet(Set fooSet) { + this.fooSet = fooSet; + } + + public Map getBarMap() { + return barMap; + } + + public void setBarMap(Map barMap) { + this.barMap = barMap; + } + + public Set getFooSet2() { + return fooSet2; + } + + public void setFooSet2( Set fooSet2 ) { + this.fooSet2 = fooSet2; + } + + public Map getBarMap2() { + return barMap2; + } + + public void setBarMap2( Map barMap2 ) { + this.barMap2 = barMap2; + } + + public Set getPublicFooSet() { + return publicFooSet; + } + + public void setPublicFooSet(Set publicFooSet) { + this.publicFooSet = publicFooSet; + } + + public Map getPublicBarMap() { + return publicBarMap; + } + + public void setPublicBarMap(Map publicBarMap) { + this.publicBarMap = publicBarMap; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Target1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Target1.java new file mode 100644 index 0000000000000000000000000000000000000000..d098c922a88b14e4c26dada179f166dc9a7122fd --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/forged/Target1.java @@ -0,0 +1,66 @@ +package io.github.linpeilie.me.collection.forged; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.Map; +import java.util.Set; +import org.mapstruct.NullValueMappingStrategy; + +@AutoMapper(target = Source1.class, nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT) +public class Target1 { + + private Set fooSet; + private Set fooSet2; + private Map barMap; + private Map barMap2; + + private Set publicFooSet; + private Map publicBarMap; + + public Set getFooSet() { + return fooSet; + } + + public void setFooSet(Set fooSet) { + this.fooSet = fooSet; + } + + public Map getBarMap() { + return barMap; + } + + public void setBarMap(Map barMap) { + this.barMap = barMap; + } + + public Set getFooSet2() { + return fooSet2; + } + + public void setFooSet2( Set fooSet2 ) { + this.fooSet2 = fooSet2; + } + + public Map getBarMap2() { + return barMap2; + } + + public void setBarMap2( Map barMap2 ) { + this.barMap2 = barMap2; + } + + public Set getPublicFooSet() { + return publicFooSet; + } + + public void setPublicFooSet(Set publicFooSet) { + this.publicFooSet = publicFooSet; + } + + public Map getPublicBarMap() { + return publicBarMap; + } + + public void setPublicBarMap(Map publicBarMap) { + this.publicBarMap = publicBarMap; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/immutabletarget/CupboardDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/immutabletarget/CupboardDto.java new file mode 100644 index 0000000000000000000000000000000000000000..628ce938272e244a4554000cf96914b773eaa465 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/immutabletarget/CupboardDto.java @@ -0,0 +1,31 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.collection.immutabletarget; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import java.util.List; +import org.mapstruct.CollectionMappingStrategy; + +/** + * @author Sjaak Derksen + */ +@AutoMappers({ + @AutoMapper(target = CupboardEntity.class, collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE), +}) +public class CupboardDto { + + private List content; + + public List getContent() { + return content; + } + + public void setContent(List content) { + this.content = content; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/immutabletarget/CupboardEntity.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/immutabletarget/CupboardEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..7aec2a5e9556ff3f0651ff501a8eca431ecfe43e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/immutabletarget/CupboardEntity.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.immutabletarget; + +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class CupboardEntity { + + private List content; + + public List getContent() { + return content; + } + + public void setContent(List content) { + this.content = content; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Fruit.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Fruit.java new file mode 100644 index 0000000000000000000000000000000000000000..5a0eeba945830c3bf4e529b6ef398f1c8e353250 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Fruit.java @@ -0,0 +1,27 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.iterabletononiterable; + +/** + * + * @author Saheb Preet Singh + */ +public class Fruit { + + private String type; + + public Fruit(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/FruitSalad.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/FruitSalad.java new file mode 100644 index 0000000000000000000000000000000000000000..8fc679aed359ff0e0d5ef5193cc1fb5ef84a6102 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/FruitSalad.java @@ -0,0 +1,31 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.iterabletononiterable; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.List; + +/** + * + * @author Saheb Preet Singh + */ +@AutoMapper(target = FruitsMenu.class) +public class FruitSalad { + + private List fruits; + + public FruitSalad(List fruits) { + this.fruits = fruits; + } + + public List getFruits() { + return fruits; + } + + public void setFruits(List fruits) { + this.fruits = fruits; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/FruitsMenu.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/FruitsMenu.java new file mode 100644 index 0000000000000000000000000000000000000000..c769bdc971bb035b47b6677013f2d9ed1bd57d15 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/FruitsMenu.java @@ -0,0 +1,35 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.iterabletononiterable; + +import java.util.Iterator; +import java.util.List; + +/** + * + * @author Saheb Preet Singh + */ +public class FruitsMenu implements Iterable { + + private List fruits; + + public FruitsMenu(List fruits) { + this.fruits = fruits; + } + + public List getFruits() { + return fruits; + } + + public void setFruits(List fruits) { + this.fruits = fruits; + } + + @Override + public Iterator iterator() { + return this.fruits.iterator(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..15d37d35bfa4ff4d38eda066a32a4dd81b8898e1 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Source.java @@ -0,0 +1,27 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.iterabletononiterable; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.List; + +@AutoMapper(target = Target.class, uses = StringListMapper.class) +public class Source { + + //CHECKSTYLE:OFF + public List publicNames; + //CHECKSTYLE:ON + + private List names; + + public List getNames() { + return names; + } + + public void setNames(List names) { + this.names = names; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/StringListMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/StringListMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..2ac01130f29dcf915ad6ef07c456fe23bd376d02 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/StringListMapper.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.iterabletononiterable; + +import java.util.Arrays; +import java.util.List; +import org.springframework.stereotype.Component; + +@Component +public class StringListMapper { + + public String stringListToString(List strings) { + return strings == null ? null : String.join( "-", strings ); + } + + public List stringToStringList(String string) { + return string == null ? null : Arrays.asList( string.split( "-" ) ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..a1a6a2f4cbd7756b737886517b4704bfbc88ce90 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/collection/iterabletononiterable/Target.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.collection.iterabletononiterable; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = Source.class, uses = StringListMapper.class) +public class Target { + + //CHECKSTYLE:OFF + public String publicNames; + //CHECKSTYLE:ON + + private String names; + + public String getNames() { + return names; + } + + public void setNames(String names) { + this.names = names; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/_target/CarDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/_target/CarDto.java new file mode 100644 index 0000000000000000000000000000000000000000..ae57e8af080c150044a47c377fe2067317246717 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/_target/CarDto.java @@ -0,0 +1,86 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.complex._target; + +import java.util.List; + +public class CarDto { + + private String make; + private int seatCount; + private String manufacturingYear; + private PersonDto driver; + private List passengers; + private Long price; + private String category; + + public CarDto() { + } + + public CarDto(String make, int seatCount, String manufacturingYear, PersonDto driver, List passengers) { + this.make = make; + this.seatCount = seatCount; + this.manufacturingYear = manufacturingYear; + this.driver = driver; + this.passengers = passengers; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public int getSeatCount() { + return seatCount; + } + + public void setSeatCount(int seatCount) { + this.seatCount = seatCount; + } + + public String getManufacturingYear() { + return manufacturingYear; + } + + public void setManufacturingYear(String manufacturingYear) { + this.manufacturingYear = manufacturingYear; + } + + public PersonDto getDriver() { + return driver; + } + + public void setDriver(PersonDto driver) { + this.driver = driver; + } + + public List getPassengers() { + return passengers; + } + + public void setPassengers(List passengers) { + this.passengers = passengers; + } + + public Long getPrice() { + return price; + } + + public void setPrice(Long price) { + this.price = price; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/_target/PersonDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/_target/PersonDto.java new file mode 100644 index 0000000000000000000000000000000000000000..e9a2a09e9bf82895ba86b1f01602bcc318ff7e37 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/_target/PersonDto.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.complex._target; + +public class PersonDto { + + private String name; + + public PersonDto() { + } + + public PersonDto(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/other/DateMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/other/DateMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..67c7faa6f2d49f49218fa0ad1fbfa22124450a2e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/other/DateMapper.java @@ -0,0 +1,28 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.complex.other; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.springframework.stereotype.Component; + +@Component +public class DateMapper { + + public String asString(Date date) { + return date != null ? new SimpleDateFormat( "yyyy" ).format( date ) : null; + } + + public Date asDate(String date) { + try { + return date != null ? new SimpleDateFormat( "yyyy" ).parse( date ) : null; + } + catch ( ParseException e ) { + throw new RuntimeException( e ); + } + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Car.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Car.java new file mode 100644 index 0000000000000000000000000000000000000000..399871755b299084e6521205e4ff6148c7731bcc --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Car.java @@ -0,0 +1,96 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.complex.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.me.complex._target.CarDto; +import io.github.linpeilie.me.complex.other.DateMapper; +import java.util.Date; +import java.util.List; + +@AutoMapper(target = CarDto.class, uses = DateMapper.class) +public class Car { + + private String make; + + @AutoMapping(target = "seatCount") + private int numberOfSeats; + + @AutoMapping(target = "manufacturingYear") + private Date manufacturingDate; + private Person driver; + private List passengers; + private int price; + private Category category; + + public Car() { + } + + public Car(String make, int numberOfSeats, Date manufacturingDate, Person driver, List passengers) { + this.make = make; + this.numberOfSeats = numberOfSeats; + this.manufacturingDate = manufacturingDate; + this.driver = driver; + this.passengers = passengers; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + + public void setNumberOfSeats(int numberOfSeats) { + this.numberOfSeats = numberOfSeats; + } + + public Date getManufacturingDate() { + return manufacturingDate; + } + + public void setManufacturingDate(Date manufacturingDate) { + this.manufacturingDate = manufacturingDate; + } + + public Person getDriver() { + return driver; + } + + public void setDriver(Person driver) { + this.driver = driver; + } + + public List getPassengers() { + return passengers; + } + + public void setPassengers(List passengers) { + this.passengers = passengers; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Category.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Category.java new file mode 100644 index 0000000000000000000000000000000000000000..c9ce310e410cca5d174640368d4a2228ff06bd0e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Category.java @@ -0,0 +1,10 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.complex.source; + +public enum Category { + SEDAN, CONVERTIBLE, TRUCK; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Person.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Person.java new file mode 100644 index 0000000000000000000000000000000000000000..207357cd24f919669e42704d1c1aa4e47489afc8 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/complex/source/Person.java @@ -0,0 +1,31 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.complex.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.me.complex._target.PersonDto; +import io.github.linpeilie.me.complex.other.DateMapper; + +@AutoMapper(target = PersonDto.class, uses = DateMapper.class) +public class Person { + + private String name; + + public Person() { + } + + public Person(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/Author.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/Author.java new file mode 100644 index 0000000000000000000000000000000000000000..14de4c51cf9bcd2d83ab4bf8583ed06739b1bcaf --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/Author.java @@ -0,0 +1,24 @@ +package io.github.linpeilie.me.conditional.basic; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.List; + +@AutoMapper(target = AuthorDto.class, reverseConvertGenerate = false, + uses = ConditionalMethodForCollectionMapper.class) +public class Author { + + private List books; + + public List getBooks() { + return books; + } + + public boolean hasBooks() { + return false; + } + + public void setBooks(List books) { + this.books = books; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/AuthorDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/AuthorDto.java new file mode 100644 index 0000000000000000000000000000000000000000..a38d5089e7939e3aca3696977006e1b7dcdaeade --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/AuthorDto.java @@ -0,0 +1,17 @@ +package io.github.linpeilie.me.conditional.basic; + +import java.util.List; + +public class AuthorDto { + + private List books; + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee.java new file mode 100644 index 0000000000000000000000000000000000000000..f2d822af82b7a9b2eef98de988d5f60ad7905d25 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +/** + * @author Filip Hrisafov + */ +public class BasicEmployee { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee1.java new file mode 100644 index 0000000000000000000000000000000000000000..2e5995eedeffa4f7a28465054dc3f314deeed490 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee1.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +/** + * @author Filip Hrisafov + */ +public class BasicEmployee1 { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee2.java new file mode 100644 index 0000000000000000000000000000000000000000..1bfd4b7a733e393653af7ca160ef162b0d74df82 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee2.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +/** + * @author Filip Hrisafov + */ +public class BasicEmployee2 { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee3.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee3.java new file mode 100644 index 0000000000000000000000000000000000000000..25827a0668b698dad1cd1dcad6962d56a37aa9f5 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee3.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +/** + * @author Filip Hrisafov + */ +public class BasicEmployee3 { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee4.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee4.java new file mode 100644 index 0000000000000000000000000000000000000000..5f9d5c7150eb3f75ee59731ea3a0eebf4235ee59 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployee4.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +/** + * @author Filip Hrisafov + */ +public class BasicEmployee4 { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployeeDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployeeDto.java new file mode 100644 index 0000000000000000000000000000000000000000..c7432bd9a486575646dbef01f7b64cdcf0a0247f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BasicEmployeeDto.java @@ -0,0 +1,44 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conditional.basic; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import org.mapstruct.NullValuePropertyMappingStrategy; + +/** + * @author Filip Hrisafov + */ +@AutoMappers({ + @AutoMapper(target = BasicEmployee.class, reverseConvertGenerate = false, uses = ConditionalMethodInMapper.class), + @AutoMapper(target = BasicEmployee1.class, reverseConvertGenerate = false, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, uses = ConditionalMethodWithMappingTargetInUpdateMapper.class), + @AutoMapper(target = BasicEmployee2.class, reverseConvertGenerate = false, uses = ConditionalMethodWithSourceParameterAndValueMapper.class), + @AutoMapper(target = BasicEmployee3.class, reverseConvertGenerate = false, uses = ConditionalMethodWithSourceParameterMapper.class), + @AutoMapper(target = BasicEmployee4.class, reverseConvertGenerate = false, uses = ConditionalMethodWithTargetType.class), +}) +public class BasicEmployeeDto { + + private final String name; + private final String strategy; + + public BasicEmployeeDto(String name) { + this(name, "default"); + } + + public BasicEmployeeDto(String name, String strategy) { + this.name = name; + this.strategy = strategy; + } + + public String getName() { + return name; + } + + public String getStrategy() { + return strategy; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/Book.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/Book.java new file mode 100644 index 0000000000000000000000000000000000000000..0d99f615cf58419a46278c2aee0167d2b6a4bf5e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/Book.java @@ -0,0 +1,18 @@ +package io.github.linpeilie.me.conditional.basic; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = BookDto.class, reverseConvertGenerate = false) +public class Book { + + private final String name; + + public Book(String name) { + this.name = name; + } + + public String getName() { + return name; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BookDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BookDto.java new file mode 100644 index 0000000000000000000000000000000000000000..3573d26ad8623f496c2f49c8de1ab23d1d79cbba --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/BookDto.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.conditional.basic; + +public class BookDto { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodAndBeanPresenceCheckMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodAndBeanPresenceCheckMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..fdad1335900daca0c612d74839548c52a089cabc --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodAndBeanPresenceCheckMapper.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Component +public class ConditionalMethodAndBeanPresenceCheckMapper { + + @Condition + public boolean isNotBlank(String value) { + return value != null && !value.trim().isEmpty(); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodForCollectionMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodForCollectionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..e55f70b7a52dea5c953b5001d0aafe592d059575 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodForCollectionMapper.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conditional.basic; + +import java.util.Collection; +import java.util.List; +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Component +public class ConditionalMethodForCollectionMapper { + + @Condition + public boolean isNotEmpty(Collection collection) { + return collection != null && !collection.isEmpty(); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodInMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodInMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..c82049f4022c0c3f6378bb044c52d3c5ea992c5a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodInMapper.java @@ -0,0 +1,20 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Component +public class ConditionalMethodInMapper { + + @Condition + public boolean isNotBlank(String value) { + return value != null && !value.trim().isEmpty(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithMappingTargetInUpdateMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithMappingTargetInUpdateMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..b089f8bf64435f19fcd3b87672b6463da52f6dad --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithMappingTargetInUpdateMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conditional.basic; + +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +/** + * @author Ben Zegveld + */ +@Component +public class ConditionalMethodWithMappingTargetInUpdateMapper { + @Condition + public boolean isNotBlankAndNotPresent(String value, @MappingTarget BasicEmployee1 targetEmployee) { + return value != null && !value.trim().isEmpty() && targetEmployee.getName() == null; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithSourceParameterAndValueMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithSourceParameterAndValueMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..8450be51437dd56409d16dd95202b889a5447357 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithSourceParameterAndValueMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Component +public class ConditionalMethodWithSourceParameterAndValueMapper { + + @Condition + public boolean isPresent(BasicEmployeeDto source, String value) { + if ( value == null ) { + return false; + } + switch ( source.getStrategy() ) { + case "blank": + return !value.trim().isEmpty(); + case "empty": + return !value.isEmpty(); + default: + return true; + } + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithSourceParameterMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithSourceParameterMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..f23d35f12524e1f3c5aeef3cf248e1e2df454018 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithSourceParameterMapper.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conditional.basic; + +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Component +public class ConditionalMethodWithSourceParameterMapper { + + @Condition + public boolean shouldMap(BasicEmployeeDto source) { + return "map".equals(source.getStrategy()); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithTargetType.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithTargetType.java new file mode 100644 index 0000000000000000000000000000000000000000..f934acbc4e1565182800718b7369d934b16cc82c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/ConditionalMethodWithTargetType.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.basic; + +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.TargetType; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Component +public class ConditionalMethodWithTargetType { + + @Condition + public boolean isNotBlank(String value, @TargetType Class targetType) { + return value != null && !value.trim().isEmpty(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/EmployeeDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/EmployeeDto.java new file mode 100644 index 0000000000000000000000000000000000000000..d12a9d1bb9036f16a5cd909a4bfc6d12124ddabf --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/basic/EmployeeDto.java @@ -0,0 +1,21 @@ +package io.github.linpeilie.me.conditional.basic; + +import io.github.linpeilie.annotations.AutoMapper; + +@AutoMapper(target = BasicEmployee.class, reverseConvertGenerate = false, uses = ConditionalMethodAndBeanPresenceCheckMapper.class) +public class EmployeeDto { + private final String name; + + public EmployeeDto(String name) { + this.name = name; + } + + public boolean hasName() { + return false; + } + + public String getName() { + return name; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Address.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Address.java new file mode 100644 index 0000000000000000000000000000000000000000..9849ba9431b86dd52b991af593edb476b601a692 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Address.java @@ -0,0 +1,22 @@ +package io.github.linpeilie.me.conditional.expression; + +public class Address { + private String line1; + private String line2; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Customer.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Customer.java new file mode 100644 index 0000000000000000000000000000000000000000..ecbc3e84a5c209f7cb09592069c6889c9d9a31cd --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Customer.java @@ -0,0 +1,22 @@ +package io.github.linpeilie.me.conditional.expression; + +public class Customer { + private String name; + private Address address; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Employee.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Employee.java new file mode 100644 index 0000000000000000000000000000000000000000..4ab467cf215977f501756a6c85bc530e09ae8098 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Employee.java @@ -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 io.github.linpeilie.me.conditional.expression; + +public class Employee { + private String name; + private String ssid; + private String nin; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSsid() { + return ssid; + } + + public void setSsid(String ssid) { + this.ssid = ssid; + } + + public String getNin() { + return nin; + } + + public void setNin(String nin) { + this.nin = nin; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/EmployeeDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/EmployeeDto.java new file mode 100644 index 0000000000000000000000000000000000000000..56a9bb65fc1a17bac0e7c5eb17f88a0d2cb000b9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/EmployeeDto.java @@ -0,0 +1,45 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conditional.expression; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; + +@AutoMapper(target = Employee.class, reverseConvertGenerate = false, imports = StaticUtil.class) +public class EmployeeDto { + private String name; + private String country; + @AutoMappings({ + @AutoMapping(target = "ssid", conditionExpression = "java(StaticUtil.isAmericanCitizen( source ))"), + @AutoMapping(target = "nin", conditionExpression = "java(StaticUtil.isBritishCitizen( source ))")}) + private String uniqueIdNumber; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getUniqueIdNumber() { + return uniqueIdNumber; + } + + public void setUniqueIdNumber(String uniqueIdNumber) { + this.uniqueIdNumber = uniqueIdNumber; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Order.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Order.java new file mode 100644 index 0000000000000000000000000000000000000000..47e2b76aa3a86e3bac8ee1a8f1be48b425c1a70a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Order.java @@ -0,0 +1,15 @@ +package io.github.linpeilie.me.conditional.expression; + +public class Order { + + private Customer customer; + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/OrderDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/OrderDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..a13146b2de6baf2eb8e13de757fbc482148b453e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/OrderDTO.java @@ -0,0 +1,45 @@ +package io.github.linpeilie.me.conditional.expression; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; + +@AutoMappers({@AutoMapper(target = Order.class, reverseConvertGenerate = false, imports = Util.class), + @AutoMapper(target = Customer.class, reverseConvertGenerate = false, imports = Util.class), + @AutoMapper(target = Address.class, reverseConvertGenerate = false, imports = Util.class),}) +public class OrderDTO { + + @AutoMappings({ + @AutoMapping(targetClass = Order.class, target = "customer", source = "source", conditionExpression = "java(Util.mapCustomerFromOrder( source ))"), + @AutoMapping(targetClass = Customer.class, target = "name"), + @AutoMapping(targetClass = Customer.class, target = "address", source = "source", conditionExpression = "java(Util.mapAddressFromOrder( source ))"),}) + private String customerName; + private String line1; + private String line2; + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..b5f19e69a2ce6eb7947ab66bfffdf82b77455c10 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Source.java @@ -0,0 +1,19 @@ +package io.github.linpeilie.me.conditional.expression; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; + +@AutoMapper(target = Target.class, reverseConvertGenerate = false) +public class Source { + + @AutoMapping(conditionExpression = "java(source.getValue() < 100)") + private final int value; + + public Source(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/StaticUtil.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/StaticUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..7e515c81105b68adacc65f3ba343d3e4bdcd1822 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/StaticUtil.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.conditional.expression; + +public class StaticUtil { + + static boolean isAmericanCitizen(EmployeeDto employeeDto) { + return "US".equals(employeeDto.getCountry()); + } + + static boolean isBritishCitizen(EmployeeDto employeeDto) { + return "UK".equals(employeeDto.getCountry()); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..7b22379c79b28db3fd50597cdc1bf4976b2ca663 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Target.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.conditional.expression; + +public class Target { + private int value; + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Util.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Util.java new file mode 100644 index 0000000000000000000000000000000000000000..9e4d408f9a20386f735e70d65313afe2ebd77f34 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/expression/Util.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.conditional.expression; + +public class Util { + + static boolean mapCustomerFromOrder(OrderDTO orderDTO) { + return orderDTO != null && (orderDTO.getCustomerName() != null || mapAddressFromOrder(orderDTO)); + } + + static boolean mapAddressFromOrder(OrderDTO orderDTO) { + return orderDTO != null && (orderDTO.getLine1() != null || orderDTO.getLine2() != null); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Address.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Address.java new file mode 100644 index 0000000000000000000000000000000000000000..47c2a22f3376bc485057fdfb6c1fdbe9330fd91b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Address.java @@ -0,0 +1,22 @@ +package io.github.linpeilie.me.conditional.qualifier; + +public class Address { + private String line1; + private String line2; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/ConditionalMethodWithClassQualifiersMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/ConditionalMethodWithClassQualifiersMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..8958b18486f6ac9908aceccecd8aba7296c39e89 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/ConditionalMethodWithClassQualifiersMapper.java @@ -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 io.github.linpeilie.me.conditional.qualifier; + +import org.mapstruct.Condition; +import org.mapstruct.Named; +import org.springframework.stereotype.Component; + +/** + * @author Filip Hrisafov + */ +@Component +public class ConditionalMethodWithClassQualifiersMapper { + + @Condition + public boolean isNotBlank(String value) { + return value != null && !value.trim().isEmpty(); + } + + @Condition + @Named("american") + public boolean isAmericanCitizen(EmployeeDto employerDto) { + return "US".equals(employerDto.getCountry()); + } + + @Condition + @Named("british") + public boolean isBritishCitizen(EmployeeDto employeeDto) { + return "UK".equals(employeeDto.getCountry()); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/ConditionalMethodWithSourceToTargetMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/ConditionalMethodWithSourceToTargetMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..d2a32aff8334ac0bb4278de0dc2a02d1f5bff045 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/ConditionalMethodWithSourceToTargetMapper.java @@ -0,0 +1,34 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conditional.qualifier; + +import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +/** + * @author Filip Hrisafov + */ +@Component +public class ConditionalMethodWithSourceToTargetMapper { + + @Condition + @Named("mapCustomerFromOrder") + public boolean mapCustomerFromOrder(OrderDTO orderDTO) { + return orderDTO != null && (orderDTO.getCustomerName() != null || mapAddressFromOrder(orderDTO)); + } + + @Condition + @Named("mapAddressFromOrder") + public boolean mapAddressFromOrder(OrderDTO orderDTO) { + return orderDTO != null && (orderDTO.getLine1() != null || orderDTO.getLine2() != null); + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Customer.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Customer.java new file mode 100644 index 0000000000000000000000000000000000000000..d3b0ab27531af4d9832af704caba12378c2329f1 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Customer.java @@ -0,0 +1,22 @@ +package io.github.linpeilie.me.conditional.qualifier; + +public class Customer { + private String name; + private Address address; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Employee.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Employee.java new file mode 100644 index 0000000000000000000000000000000000000000..ce033b5e47f5cb649d85791f21194963cae50bb9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Employee.java @@ -0,0 +1,37 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conditional.qualifier; + +public class Employee { + + private String name; + private String ssid; + private String nin; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSsid() { + return ssid; + } + + public void setSsid(String ssid) { + this.ssid = ssid; + } + + public String getNin() { + return nin; + } + + public void setNin(String nin) { + this.nin = nin; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/EmployeeDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/EmployeeDto.java new file mode 100644 index 0000000000000000000000000000000000000000..a528668f59b0ec39b4769782fe7363f28ba5ccf0 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/EmployeeDto.java @@ -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 io.github.linpeilie.me.conditional.qualifier; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; + +@AutoMapper(target = Employee.class, + reverseConvertGenerate = false, + uses = ConditionalMethodWithClassQualifiersMapper.class) +public class EmployeeDto { + + private String name; + private String country; + + @AutoMappings({ + @AutoMapping(target = "ssid", conditionQualifiedByName = "american"), + @AutoMapping(target = "nin", conditionQualifiedByName = "british") + }) + private String uniqueIdNumber; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getUniqueIdNumber() { + return uniqueIdNumber; + } + + public void setUniqueIdNumber(String uniqueIdNumber) { + this.uniqueIdNumber = uniqueIdNumber; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Order.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Order.java new file mode 100644 index 0000000000000000000000000000000000000000..199763dbd0f56bf6fb0bc36f90b088d9ce8b5b02 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/Order.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.conditional.qualifier; + +public class Order { + private Customer customer; + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/OrderDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/OrderDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..82c3f15ad06e7315b0d5b7ce55b17377ed35432d --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conditional/qualifier/OrderDTO.java @@ -0,0 +1,45 @@ +package io.github.linpeilie.me.conditional.qualifier; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; + +@AutoMappers({ + @AutoMapper(target = Order.class, reverseConvertGenerate = false, uses = ConditionalMethodWithSourceToTargetMapper.class), + @AutoMapper(target = Customer.class, reverseConvertGenerate = false, uses = ConditionalMethodWithSourceToTargetMapper.class), + @AutoMapper(target = Address.class, reverseConvertGenerate = false, uses = ConditionalMethodWithSourceToTargetMapper.class)}) +public class OrderDTO { + @AutoMappings({ + @AutoMapping(targetClass = Order.class, target = "customer", source = "source", conditionQualifiedByName = "mapCustomerFromOrder"), + @AutoMapping(targetClass = Customer.class, target = "name"), + @AutoMapping(targetClass = Customer.class, target = "address", source = "source", conditionQualifiedByName = "mapAddressFromOrder"), + }) + private String customerName; + private String line1; + private String line2; + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigDecimalSource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigDecimalSource.java new file mode 100644 index 0000000000000000000000000000000000000000..65f5cdd67ab1cfa514f37811ad22e36ffb10faa4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigDecimalSource.java @@ -0,0 +1,140 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.bignumbers; + +import io.github.linpeilie.annotations.AutoMapper; +import java.math.BigDecimal; + +@AutoMapper(target = BigDecimalTarget.class) +public class BigDecimalSource { + + private BigDecimal b; + private BigDecimal bb; + private BigDecimal s; + private BigDecimal ss; + private BigDecimal i; + private BigDecimal ii; + private BigDecimal l; + private BigDecimal ll; + private BigDecimal f; + private BigDecimal ff; + private BigDecimal d; + private BigDecimal dd; + private BigDecimal string; + private BigDecimal bigInteger; + + public BigDecimal getB() { + return b; + } + + public void setB(BigDecimal b) { + this.b = b; + } + + public BigDecimal getBb() { + return bb; + } + + public void setBb(BigDecimal bb) { + this.bb = bb; + } + + public BigDecimal getS() { + return s; + } + + public void setS(BigDecimal s) { + this.s = s; + } + + public BigDecimal getSs() { + return ss; + } + + public void setSs(BigDecimal ss) { + this.ss = ss; + } + + public BigDecimal getI() { + return i; + } + + public void setI(BigDecimal i) { + this.i = i; + } + + public BigDecimal getIi() { + return ii; + } + + public void setIi(BigDecimal ii) { + this.ii = ii; + } + + public BigDecimal getL() { + return l; + } + + public void setL(BigDecimal l) { + this.l = l; + } + + public BigDecimal getLl() { + return ll; + } + + public void setLl(BigDecimal ll) { + this.ll = ll; + } + + public BigDecimal getF() { + return f; + } + + public void setF(BigDecimal f) { + this.f = f; + } + + public BigDecimal getFf() { + return ff; + } + + public void setFf(BigDecimal ff) { + this.ff = ff; + } + + public BigDecimal getD() { + return d; + } + + public void setD(BigDecimal d) { + this.d = d; + } + + public BigDecimal getDd() { + return dd; + } + + public void setDd(BigDecimal dd) { + this.dd = dd; + } + + public BigDecimal getString() { + return string; + } + + public void setString(BigDecimal string) { + this.string = string; + } + + public BigDecimal getBigInteger() { + return bigInteger; + } + + public void setBigInteger(BigDecimal bigInteger) { + this.bigInteger = bigInteger; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigDecimalTarget.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigDecimalTarget.java new file mode 100644 index 0000000000000000000000000000000000000000..7c15e9cc7542854fa13f7d1ab49a1ce8b4658901 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigDecimalTarget.java @@ -0,0 +1,138 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.bignumbers; + +import java.math.BigInteger; + +public class BigDecimalTarget { + + private byte b; + private Byte bb; + private short s; + private Short ss; + private int i; + private Integer ii; + private long l; + private Long ll; + private float f; + private Float ff; + private double d; + private Double dd; + private String string; + private BigInteger bigInteger; + + public byte getB() { + return b; + } + + public void setB(byte b) { + this.b = b; + } + + public Byte getBb() { + return bb; + } + + public void setBb(Byte bb) { + this.bb = bb; + } + + public short getS() { + return s; + } + + public void setS(short s) { + this.s = s; + } + + public Short getSs() { + return ss; + } + + public void setSs(Short ss) { + this.ss = ss; + } + + public int getI() { + return i; + } + + public void setI(int i) { + this.i = i; + } + + public Integer getIi() { + return ii; + } + + public void setIi(Integer ii) { + this.ii = ii; + } + + public long getL() { + return l; + } + + public void setL(long l) { + this.l = l; + } + + public Long getLl() { + return ll; + } + + public void setLl(Long ll) { + this.ll = ll; + } + + public float getF() { + return f; + } + + public void setF(float f) { + this.f = f; + } + + public Float getFf() { + return ff; + } + + public void setFf(Float ff) { + this.ff = ff; + } + + public double getD() { + return d; + } + + public void setD(double d) { + this.d = d; + } + + public Double getDd() { + return dd; + } + + public void setDd(Double dd) { + this.dd = dd; + } + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + + public BigInteger getBigInteger() { + return bigInteger; + } + + public void setBigInteger(BigInteger bigInteger) { + this.bigInteger = bigInteger; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigIntegerSource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigIntegerSource.java new file mode 100644 index 0000000000000000000000000000000000000000..20802021515c0ab4d5df8371e82af3fea471796b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigIntegerSource.java @@ -0,0 +1,131 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.bignumbers; + +import io.github.linpeilie.annotations.AutoMapper; +import java.math.BigInteger; + +@AutoMapper(target = BigIntegerTarget.class) +public class BigIntegerSource { + + private BigInteger b; + private BigInteger bb; + private BigInteger s; + private BigInteger ss; + private BigInteger i; + private BigInteger ii; + private BigInteger l; + private BigInteger ll; + private BigInteger f; + private BigInteger ff; + private BigInteger d; + private BigInteger dd; + private BigInteger string; + + public BigInteger getB() { + return b; + } + + public void setB(BigInteger b) { + this.b = b; + } + + public BigInteger getBb() { + return bb; + } + + public void setBb(BigInteger bb) { + this.bb = bb; + } + + public BigInteger getS() { + return s; + } + + public void setS(BigInteger s) { + this.s = s; + } + + public BigInteger getSs() { + return ss; + } + + public void setSs(BigInteger ss) { + this.ss = ss; + } + + public BigInteger getI() { + return i; + } + + public void setI(BigInteger i) { + this.i = i; + } + + public BigInteger getIi() { + return ii; + } + + public void setIi(BigInteger ii) { + this.ii = ii; + } + + public BigInteger getL() { + return l; + } + + public void setL(BigInteger l) { + this.l = l; + } + + public BigInteger getLl() { + return ll; + } + + public void setLl(BigInteger ll) { + this.ll = ll; + } + + public BigInteger getF() { + return f; + } + + public void setF(BigInteger f) { + this.f = f; + } + + public BigInteger getFf() { + return ff; + } + + public void setFf(BigInteger ff) { + this.ff = ff; + } + + public BigInteger getD() { + return d; + } + + public void setD(BigInteger d) { + this.d = d; + } + + public BigInteger getDd() { + return dd; + } + + public void setDd(BigInteger dd) { + this.dd = dd; + } + + public BigInteger getString() { + return string; + } + + public void setString(BigInteger string) { + this.string = string; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigIntegerTarget.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigIntegerTarget.java new file mode 100644 index 0000000000000000000000000000000000000000..0591ebd8cf679128272247a5b1dc3eecefccede9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/bignumbers/BigIntegerTarget.java @@ -0,0 +1,127 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.bignumbers; + +public class BigIntegerTarget { + + private byte b; + private Byte bb; + private short s; + private Short ss; + private int i; + private Integer ii; + private long l; + private Long ll; + private float f; + private Float ff; + private double d; + private Double dd; + private String string; + + public byte getB() { + return b; + } + + public void setB(byte b) { + this.b = b; + } + + public Byte getBb() { + return bb; + } + + public void setBb(Byte bb) { + this.bb = bb; + } + + public short getS() { + return s; + } + + public void setS(short s) { + this.s = s; + } + + public Short getSs() { + return ss; + } + + public void setSs(Short ss) { + this.ss = ss; + } + + public int getI() { + return i; + } + + public void setI(int i) { + this.i = i; + } + + public Integer getIi() { + return ii; + } + + public void setIi(Integer ii) { + this.ii = ii; + } + + public long getL() { + return l; + } + + public void setL(long l) { + this.l = l; + } + + public Long getLl() { + return ll; + } + + public void setLl(Long ll) { + this.ll = ll; + } + + public float getF() { + return f; + } + + public void setF(float f) { + this.f = f; + } + + public Float getFf() { + return ff; + } + + public void setFf(Float ff) { + this.ff = ff; + } + + public double getD() { + return d; + } + + public void setD(double d) { + this.d = d; + } + + public Double getDd() { + return dd; + } + + public void setDd(Double dd) { + this.dd = dd; + } + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/currency/CurrencySource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/currency/CurrencySource.java new file mode 100644 index 0000000000000000000000000000000000000000..8efd6af36760739a7284f32572569f68058bbc23 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/currency/CurrencySource.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.currency; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.Currency; +import java.util.Set; + +@AutoMapper(target = CurrencyTarget.class) +public class CurrencySource { + + private Currency currencyA; + private Set uniqueCurrencies; + + public Currency getCurrencyA() { + return this.currencyA; + } + + public void setCurrencyA(final Currency currencyA) { + this.currencyA = currencyA; + } + + public Set getUniqueCurrencies() { + return this.uniqueCurrencies; + } + + public void setUniqueCurrencies(final Set uniqueCurrencies) { + this.uniqueCurrencies = uniqueCurrencies; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/currency/CurrencyTarget.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/currency/CurrencyTarget.java new file mode 100644 index 0000000000000000000000000000000000000000..e7e1506f2aa0cbeb039a206985026639a65778bc --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/currency/CurrencyTarget.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.currency; + +import java.util.Set; + +/** + * @author Darren Rambaud + */ +public class CurrencyTarget { + + private String currencyA; + private Set uniqueCurrencies; + + public String getCurrencyA() { + return this.currencyA; + } + + public void setCurrencyA(final String currencyA) { + this.currencyA = currencyA; + } + + public Set getUniqueCurrencies() { + return this.uniqueCurrencies; + } + + public void setUniqueCurrencies(final Set uniqueCurrencies) { + this.uniqueCurrencies = uniqueCurrencies; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/DataStringMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/DataStringMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..1adaf9a497bc177a3b1b5653ebe5b0879b429930 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/DataStringMapper.java @@ -0,0 +1,37 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conversion.date; + +import java.util.Date; +import java.util.List; + +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.IterableMapping; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface DataStringMapper { + + @IterableMapping(dateFormat = "dd.MM.yyyy") + List stringListToDateList(List dates); + + @IterableMapping(dateFormat = "dd.MM.yyyy") + String[] stringListToDateArray(List dates); + + @InheritInverseConfiguration + List dateListToStringList(List strings); + + @InheritInverseConfiguration + List stringArrayToDateList(String[] dates); + + @IterableMapping(dateFormat = "dd.MM.yyyy") + String[] dateArrayToStringArray(Date[] dates); + + @InheritInverseConfiguration + Date[] stringArrayToDateArray(String[] dates); +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..53b03cd96b90f7f3b0755d11e74901a2b54f7892 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/Source.java @@ -0,0 +1,63 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.date; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import java.util.Date; +import org.mapstruct.Mapping; + +@AutoMapper(target = Target.class, uses = DataStringMapper.class) +public class Source { + + @AutoMapping(target = "date", dateFormat = "dd.MM.yyyy") + private Date date; + private Date anotherDate; + private Date time; + private Date sqlDate; + private Date timestamp; + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Date getAnotherDate() { + return anotherDate; + } + + public void setAnotherDate(Date anotherDate) { + this.anotherDate = anotherDate; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + public Date getSqlDate() { + return sqlDate; + } + + public void setSqlDate(Date sqlDate) { + this.sqlDate = sqlDate; + } + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..d4572eeffdb69535505b77c08604377f5d4297af --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/date/Target.java @@ -0,0 +1,64 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.date; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; + +@AutoMapper(target = Source.class, uses = DataStringMapper.class) +public class Target { + + @AutoMapping(target = "date", dateFormat = "dd.MM.yyyy") + private String date; + private String anotherDate; + private Time time; + private Date sqlDate; + private Timestamp timestamp; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + + public String getAnotherDate() { + return anotherDate; + } + + public void setAnotherDate(String anotherDate) { + this.anotherDate = anotherDate; + } + + public Time getTime() { + return time; + } + + public void setTime(Time time) { + this.time = time; + } + + public Date getSqlDate() { + return sqlDate; + } + + public void setSqlDate(Date sqlDate) { + this.sqlDate = sqlDate; + } + + public Timestamp getTimestamp() { + return timestamp; + } + + public void setTimestamp(Timestamp timestamp) { + this.timestamp = timestamp; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/lossy/CutleryInventoryDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/lossy/CutleryInventoryDto.java new file mode 100644 index 0000000000000000000000000000000000000000..fa3c5eaea791cb45896d2c50f32ed39be6c8a6d8 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/lossy/CutleryInventoryDto.java @@ -0,0 +1,56 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.conversion.lossy; + +import io.github.linpeilie.annotations.AutoMapper; +import org.mapstruct.ReportingPolicy; + +@AutoMapper( + target = CutleryInventoryEntity.class, + typeConversionPolicy = ReportingPolicy.ERROR, + reverseConvertGenerate = false +) +public class CutleryInventoryDto { + + private short numberOfKnifes; + private int numberOfForks; + private byte numberOfSpoons; + + private float approximateKnifeLength; + + public short getNumberOfKnifes() { + return numberOfKnifes; + } + + public void setNumberOfKnifes(short numberOfKnifes) { + this.numberOfKnifes = numberOfKnifes; + } + + public int getNumberOfForks() { + return numberOfForks; + } + + public void setNumberOfForks(int numberOfForks) { + this.numberOfForks = numberOfForks; + } + + public byte getNumberOfSpoons() { + return numberOfSpoons; + } + + public void setNumberOfSpoons(byte numberOfSpoons) { + this.numberOfSpoons = numberOfSpoons; + } + + public float getApproximateKnifeLength() { + return approximateKnifeLength; + } + + public void setApproximateKnifeLength(float approximateKnifeLength) { + this.approximateKnifeLength = approximateKnifeLength; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/lossy/CutleryInventoryEntity.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/lossy/CutleryInventoryEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..891320f4701fdc8ed80faaefdf450e9646204ab2 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/lossy/CutleryInventoryEntity.java @@ -0,0 +1,47 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.lossy; + +public class CutleryInventoryEntity { + + private int numberOfKnifes; + private Long numberOfForks; + private short numberOfSpoons; + + private double approximateKnifeLength; + + public int getNumberOfKnifes() { + return numberOfKnifes; + } + + public void setNumberOfKnifes(int numberOfKnifes) { + this.numberOfKnifes = numberOfKnifes; + } + + public Long getNumberOfForks() { + return numberOfForks; + } + + public void setNumberOfForks(Long numberOfForks) { + this.numberOfForks = numberOfForks; + } + + public short getNumberOfSpoons() { + return numberOfSpoons; + } + + public void setNumberOfSpoons(short numberOfSpoons) { + this.numberOfSpoons = numberOfSpoons; + } + + public double getApproximateKnifeLength() { + return approximateKnifeLength; + } + + public void setApproximateKnifeLength(double approximateKnifeLength) { + this.approximateKnifeLength = approximateKnifeLength; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/numbers/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/numbers/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..b1eafc468bb2d17a34cb007f48e6aa05eb28261c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/numbers/Source.java @@ -0,0 +1,172 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.numbers; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import java.math.BigDecimal; +import java.math.BigInteger; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +@AutoMapper(target = Target.class) +public class Source { + + @AutoMapping( target = "i", numberFormat = "##.00" ) + private int i; + + @AutoMapping( target = "ii", numberFormat = "##.00" ) + private Integer ii; + + @AutoMapping( target = "d", numberFormat = "##.00" ) + private double d; + + @AutoMapping( target = "dd", numberFormat = "##.00" ) + private Double dd; + + @AutoMapping( target = "f", numberFormat = "##.00" ) + private float f; + + @AutoMapping( target = "ff", numberFormat = "##.00" ) + private Float ff; + + @AutoMapping( target = "l", numberFormat = "##.00" ) + private long l; + + @AutoMapping( target = "ll", numberFormat = "##.00" ) + private Long ll; + + @AutoMapping( target = "b", numberFormat = "##.00" ) + private byte b; + + @AutoMapping( target = "bb", numberFormat = "##.00" ) + private Byte bb; + + @AutoMapping( target = "complex1", numberFormat = "##0.##E0" ) + private double complex1; + + @AutoMapping( target = "complex2", numberFormat = "$#.00" ) + private double complex2; + + @AutoMapping( target = "bigDecimal1", numberFormat = "#0.#E0" ) + private BigDecimal bigDecimal1; + + @AutoMapping( target = "bigInteger1", numberFormat = "0.#############E0" ) + private BigInteger bigInteger1; + + public int getI() { + return i; + } + + public void setI(int i) { + this.i = i; + } + + public Integer getIi() { + return ii; + } + + public void setIi(Integer ii) { + this.ii = ii; + } + + public double getD() { + return d; + } + + public void setD(double d) { + this.d = d; + } + + public Double getDd() { + return dd; + } + + public void setDd(Double dd) { + this.dd = dd; + } + + public float getF() { + return f; + } + + public void setF(float f) { + this.f = f; + } + + public Float getFf() { + return ff; + } + + public void setFf(Float ff) { + this.ff = ff; + } + + public long getL() { + return l; + } + + public void setL(long l) { + this.l = l; + } + + public Long getLl() { + return ll; + } + + public void setLl(Long ll) { + this.ll = ll; + } + + public byte getB() { + return b; + } + + public void setB(byte b) { + this.b = b; + } + + public Byte getBb() { + return bb; + } + + public void setBb(Byte bb) { + this.bb = bb; + } + + public double getComplex1() { + return complex1; + } + + public void setComplex1(double complex1) { + this.complex1 = complex1; + } + + public double getComplex2() { + return complex2; + } + + public void setComplex2(double complex2) { + this.complex2 = complex2; + } + + public BigDecimal getBigDecimal1() { + return bigDecimal1; + } + + public void setBigDecimal1(BigDecimal bigDecimal1) { + this.bigDecimal1 = bigDecimal1; + } + + public BigInteger getBigInteger1() { + return bigInteger1; + } + + public void setBigInteger1(BigInteger bigInteger1) { + this.bigInteger1 = bigInteger1; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/numbers/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/numbers/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..ac89f92e321cc852fd3ce709586854cd59a0355a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/numbers/Target.java @@ -0,0 +1,169 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.numbers; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import java.math.BigDecimal; +import java.math.BigInteger; + +@AutoMapper(target = Source.class) +public class Target { + + @AutoMapping( target = "i", numberFormat = "##.00" ) + private String i; + + @AutoMapping( target = "ii", numberFormat = "##.00" ) + private String ii; + + @AutoMapping( target = "d", numberFormat = "##.00" ) + private String d; + + @AutoMapping( target = "dd", numberFormat = "##.00" ) + private String dd; + + @AutoMapping( target = "f", numberFormat = "##.00" ) + private String f; + + @AutoMapping( target = "ff", numberFormat = "##.00" ) + private String ff; + + @AutoMapping( target = "l", numberFormat = "##.00" ) + private String l; + + @AutoMapping( target = "ll", numberFormat = "##.00" ) + private String ll; + + @AutoMapping( target = "b", numberFormat = "##.00" ) + private String b; + + @AutoMapping( target = "bb", numberFormat = "##.00" ) + private String bb; + + @AutoMapping( target = "complex1", numberFormat = "##0.##E0" ) + private String complex1; + + @AutoMapping( target = "complex2", numberFormat = "$#.00" ) + private String complex2; + + @AutoMapping( target = "bigDecimal1", numberFormat = "#0.#E0" ) + private String bigDecimal1; + + @AutoMapping( target = "bigInteger1", numberFormat = "0.#############E0" ) + private String bigInteger1; + + public String getI() { + return i; + } + + public void setI(String i) { + this.i = i; + } + + public String getIi() { + return ii; + } + + public void setIi(String ii) { + this.ii = ii; + } + + public String getD() { + return d; + } + + public void setD(String d) { + this.d = d; + } + + public String getDd() { + return dd; + } + + public void setDd(String dd) { + this.dd = dd; + } + + public String getF() { + return f; + } + + public void setF(String f) { + this.f = f; + } + + public String getFf() { + return ff; + } + + public void setFf(String ff) { + this.ff = ff; + } + + public String getL() { + return l; + } + + public void setL(String l) { + this.l = l; + } + + public String getLl() { + return ll; + } + + public void setLl(String ll) { + this.ll = ll; + } + + public String getB() { + return b; + } + + public void setB(String b) { + this.b = b; + } + + public String getBb() { + return bb; + } + + public void setBb(String bb) { + this.bb = bb; + } + + public String getComplex1() { + return complex1; + } + + public void setComplex1(String complex1) { + this.complex1 = complex1; + } + + public String getComplex2() { + return complex2; + } + + public void setComplex2(String complex2) { + this.complex2 = complex2; + } + + public String getBigDecimal1() { + return bigDecimal1; + } + + public void setBigDecimal1(String bigDecimal1) { + this.bigDecimal1 = bigDecimal1; + } + + public String getBigInteger1() { + return bigInteger1; + } + + public void setBigInteger1(String bigInteger1) { + this.bigInteger1 = bigInteger1; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/string/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/string/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..2d76d324d666ef48f8e691fec322319346e1eae0 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/string/Source.java @@ -0,0 +1,178 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.string; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; + +@AutoMapper(target = Target.class) +public class Source { + + private byte b; + private Byte bb; + private short s; + private Short ss; + private int i; + private Integer ii; + private long l; + private Long ll; + private float f; + private Float ff; + private double d; + private Double dd; + private boolean bool; + private Boolean boolBool; + private char c; + private Character cc; + private StringBuilder sb; + + @AutoMapping(target = "object", ignore = true) + private Object object; + + public byte getB() { + return b; + } + + public void setB(byte b) { + this.b = b; + } + + public Byte getBb() { + return bb; + } + + public void setBb(Byte bb) { + this.bb = bb; + } + + public short getS() { + return s; + } + + public void setS(short s) { + this.s = s; + } + + public Short getSs() { + return ss; + } + + public void setSs(Short ss) { + this.ss = ss; + } + + public int getI() { + return i; + } + + public void setI(int i) { + this.i = i; + } + + public Integer getIi() { + return ii; + } + + public void setIi(Integer ii) { + this.ii = ii; + } + + public long getL() { + return l; + } + + public void setL(long l) { + this.l = l; + } + + public Long getLl() { + return ll; + } + + public void setLl(Long ll) { + this.ll = ll; + } + + public float getF() { + return f; + } + + public void setF(float f) { + this.f = f; + } + + public Float getFf() { + return ff; + } + + public void setFf(Float ff) { + this.ff = ff; + } + + public double getD() { + return d; + } + + public void setD(double d) { + this.d = d; + } + + public Double getDd() { + return dd; + } + + public void setDd(Double dd) { + this.dd = dd; + } + + public boolean getBool() { + return bool; + } + + public void setBool(boolean bool) { + this.bool = bool; + } + + public Boolean getBoolBool() { + return boolBool; + } + + public void setBoolBool(Boolean boolBool) { + this.boolBool = boolBool; + } + + public char getC() { + return c; + } + + public void setC(char c) { + this.c = c; + } + + public Character getCc() { + return cc; + } + + public void setCc(Character cc) { + this.cc = cc; + } + + public Object getObject() { + return object; + } + + public void setObject(Object object) { + this.object = object; + } + + public StringBuilder getSb() { + return sb; + } + + public void setSb(StringBuilder sb) { + this.sb = sb; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/string/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/string/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..08e92ab21482c0a8eeca799d64d61194a1ed88e0 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/conversion/string/Target.java @@ -0,0 +1,178 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.conversion.string; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; + +@AutoMapper(target = Source.class) +public class Target { + + private String b; + private String bb; + private String s; + private String ss; + private String i; + private String ii; + private String l; + private String ll; + private String f; + private String ff; + private String d; + private String dd; + private String bool; + private String boolBool; + private String c; + private String cc; + private String sb; + + @AutoMapping(target = "object", ignore = true) + private String object; + + public String getB() { + return b; + } + + public void setB(String b) { + this.b = b; + } + + public String getBb() { + return bb; + } + + public void setBb(String bb) { + this.bb = bb; + } + + public String getS() { + return s; + } + + public void setS(String s) { + this.s = s; + } + + public String getSs() { + return ss; + } + + public void setSs(String ss) { + this.ss = ss; + } + + public String getI() { + return i; + } + + public void setI(String i) { + this.i = i; + } + + public String getIi() { + return ii; + } + + public void setIi(String ii) { + this.ii = ii; + } + + public String getL() { + return l; + } + + public void setL(String l) { + this.l = l; + } + + public String getLl() { + return ll; + } + + public void setLl(String ll) { + this.ll = ll; + } + + public String getF() { + return f; + } + + public void setF(String f) { + this.f = f; + } + + public String getFf() { + return ff; + } + + public void setFf(String ff) { + this.ff = ff; + } + + public String getD() { + return d; + } + + public void setD(String d) { + this.d = d; + } + + public String getDd() { + return dd; + } + + public void setDd(String dd) { + this.dd = dd; + } + + public String getBool() { + return bool; + } + + public void setBool(String bool) { + this.bool = bool; + } + + public String getBoolBool() { + return boolBool; + } + + public void setBoolBool(String boolBool) { + this.boolBool = boolBool; + } + + public String getC() { + return c; + } + + public void setC(String c) { + this.c = c; + } + + public String getCc() { + return cc; + } + + public void setCc(String cc) { + this.cc = cc; + } + + public String getObject() { + return object; + } + + public void setObject(String object) { + this.object = object; + } + + public String getSb() { + return sb; + } + + public void setSb(String sb) { + this.sb = sb; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryDts.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryDts.java new file mode 100644 index 0000000000000000000000000000000000000000..25c1f500edc424734af89402dac4ccda971d287a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryDts.java @@ -0,0 +1,71 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.defaultvalue; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.me.defaultvalue.other.Continent; +import org.mapstruct.Mapping; + +@AutoMapper(target = CountryEntity.class) +public class CountryDts { + + @AutoMapping(target = "code", defaultValue = "DE") + private String code; + + @AutoMapping(target = "id", defaultValue = "42") + private int id; + + @AutoMapping(target = "zipcode", defaultValue = "1337") + private long zipcode; + + @AutoMapping(target = "region", ignore = true) + private String region; + + @AutoMapping(target = "continent", defaultValue = "EUROPE") + private Continent continent; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public long getZipcode() { + return zipcode; + } + + public void setZipcode(long zipcode) { + this.zipcode = zipcode; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public Continent getContinent() { + return continent; + } + + public void setContinent(Continent continent) { + this.continent = continent; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryEntity.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..076fea1dea22fbcf0ff1e63b8660c8f24ef9fa19 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryEntity.java @@ -0,0 +1,70 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.defaultvalue; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.me.defaultvalue.other.Continent; + +@AutoMapper(target = CountryDts.class) +public class CountryEntity { + + @AutoMapping(target = "code", defaultValue = "DE") + private String code; + + @AutoMapping(target = "id", defaultValue = "42") + private Integer id; + + @AutoMapping(target = "zipcode", defaultValue = "1337") + private long zipcode; + + @AutoMapping(target = "region", defaultValue = "someRegion") + private Region region; + + @AutoMapping(target = "continent", defaultValue = "EUROPE") + private Continent continent; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public long getZipcode() { + return zipcode; + } + + public void setZipcode(long zipcode) { + this.zipcode = zipcode; + } + + public Region getRegion() { + return region; + } + + public void setRegion(Region region) { + this.region = region; + } + + public Continent getContinent() { + return continent; + } + + public void setContinent(Continent continent) { + this.continent = continent; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..643df0d1b1848754b69e8b8c0d60d5c279489f1a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/CountryMapper.java @@ -0,0 +1,23 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.defaultvalue; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingConstants; +import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public abstract class CountryMapper { + + protected String mapToString(Region region) { + return ( region != null ) ? region.getCode() : null; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/Region.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/Region.java new file mode 100644 index 0000000000000000000000000000000000000000..48b70e26c17bc3df0bb19745de55f142f5d714c9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/Region.java @@ -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 io.github.linpeilie.me.defaultvalue; + +public class Region { + private String code; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/other/Continent.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/other/Continent.java new file mode 100644 index 0000000000000000000000000000000000000000..cb49c839b03a56a18f50e007e8b1c6a0cb6840d5 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/defaultvalue/other/Continent.java @@ -0,0 +1,20 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.defaultvalue.other; + +/** + * @author Andreas Gudian + * + */ +public enum Continent { + AFRICA, + ANTARCTICA, + ASIA, + EUROPE, + NORTH_AMERICA, + OCEANIA, + SOUTH_AMERICA +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/Address.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/Address.java new file mode 100644 index 0000000000000000000000000000000000000000..d50cd340a697bfea3278e023b18659aa36ddd2f3 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/Address.java @@ -0,0 +1,47 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.dependency; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import org.mapstruct.Mapping; + +@AutoMapper(target = AddressDto.class, reverseConvertGenerate = false) +public class Address { + + @AutoMapping(target = "givenName") + private String firstName; + + @AutoMapping(target = "middleName", dependsOn = "givenName") + private String middleName; + + @AutoMapping(target = "surName", dependsOn = "middleName") + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/AddressDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/AddressDto.java new file mode 100644 index 0000000000000000000000000000000000000000..943e9869df680534e289539e6c08a260e6697dcd --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/AddressDto.java @@ -0,0 +1,45 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.dependency; + +public class AddressDto { + + private String givenName; + private String middleName; + private String surName; + private String fullName; + + public String getGivenName() { + return givenName; + } + + public void setGivenName(String givenName) { + this.givenName = givenName; + this.fullName = givenName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + this.fullName += " " + middleName; + } + + public String getSurName() { + return surName; + } + + public void setSurName(String surName) { + this.surName = surName; + this.fullName += " " + surName; + } + + public String getFullName() { + return fullName; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/Person.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/Person.java new file mode 100644 index 0000000000000000000000000000000000000000..3a430412854218a8ed703602c6273f9a1d6b94bc --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/Person.java @@ -0,0 +1,44 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.dependency; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import org.mapstruct.Mapping; + +@AutoMapper(target = PersonDto.class, reverseConvertGenerate = false) +public class Person { + + private String firstName; + private String middleName; + + @AutoMapping(target = "lastName", dependsOn = {"firstName", "middleName" }) + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/PersonDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/PersonDto.java new file mode 100644 index 0000000000000000000000000000000000000000..cff9de7cc5ffbb0ddd143d01552d896a4a421eeb --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/dependency/PersonDto.java @@ -0,0 +1,43 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.dependency; + +public class PersonDto { + + private String firstName; + private String middleName; + private String lastName; + private String fullName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + this.fullName = firstName + " " + middleName + " " + lastName; + } + + public String getFullName() { + return fullName; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/Customer.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/Customer.java new file mode 100644 index 0000000000000000000000000000000000000000..597f0bc0b22fcaef6c9078e09f817e54c33bf7d4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/Customer.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.field_mapping; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import java.util.Collection; +import lombok.Data; + +@Data +@AutoMapper(target = CustomerDto.class) +public class Customer { + + private Long id; + + @AutoMapping(target = "customerName") + private String name; + + @AutoMapping(target = "orders") + private Collection orderItems; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/CustomerDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/CustomerDto.java new file mode 100644 index 0000000000000000000000000000000000000000..41366bf4103e10d38608266617950e441c52b13f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/CustomerDto.java @@ -0,0 +1,17 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.field_mapping; + +import java.util.List; +import lombok.Data; + +@Data +public class CustomerDto { + + public Long id; + public String customerName; + public List orders; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/OrderItem.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/OrderItem.java new file mode 100644 index 0000000000000000000000000000000000000000..1fdedcee229a976135abe85b4e46cade5664d7ac --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/OrderItem.java @@ -0,0 +1,11 @@ +package io.github.linpeilie.me.field_mapping; + +import lombok.Data; + +@Data +public class OrderItem { + + private String name; + private Long quantity; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/OrderItemDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/OrderItemDto.java new file mode 100644 index 0000000000000000000000000000000000000000..0466d80d5f4bd4374dc4183fbd33e132cb9f4f3b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/field_mapping/OrderItemDto.java @@ -0,0 +1,10 @@ +package io.github.linpeilie.me.field_mapping; + +import lombok.Data; + +@Data +public class OrderItemDto { + + public String name; + public Long quantity; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..03273ed23e24cd5138c00e0e1501afb412171a58 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/Source.java @@ -0,0 +1,27 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.iterable_to_non_iterable; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.me.iterable_to_non_iterable.util.FirstElement; +import io.github.linpeilie.me.iterable_to_non_iterable.util.IterableNonIterableUtil; +import io.github.linpeilie.me.iterable_to_non_iterable.util.LastElement; +import java.util.List; +import lombok.Data; + +@Data +@AutoMapper(target = Target.class, reverseConvertGenerate = false, uses = IterableNonIterableUtil.class, mapperNameSuffix = "$4") +public class Source { + + @AutoMapping(target = "myInteger", qualifiedBy = FirstElement.class) + private List myIntegers; + + @AutoMapping(target = "myString", qualifiedBy = LastElement.class) + private List myStrings; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..33f13816945f5ccf38ecb2e1ce71f02cd49ff17b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/Target.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.iterable_to_non_iterable; + +import lombok.Data; + +@Data +public class Target { + + private Integer myInteger; + private String myString; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/FirstElement.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/FirstElement.java new file mode 100644 index 0000000000000000000000000000000000000000..a87ddf5ceb52e9ce0d292fc25c1e722add8226e6 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/FirstElement.java @@ -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 io.github.linpeilie.me.iterable_to_non_iterable.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.mapstruct.Qualifier; + +@Qualifier +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.CLASS) +public @interface FirstElement { +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/IterableNonIterableUtil.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/IterableNonIterableUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..c060a0bd090ac57054b4757f64e3a7497656fdaf --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/IterableNonIterableUtil.java @@ -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 io.github.linpeilie.me.iterable_to_non_iterable.util; + +import java.util.List; +import org.springframework.stereotype.Component; +//import org.mapstruct.ap.test.selection.qualifier.annotation.TitleTranslator; + +@Component +public class IterableNonIterableUtil { + + @FirstElement + public T first( List in ) { + if ( in != null && !in.isEmpty() ) { + return in.get( 0 ); + } + else { + return null; + } + } + + @LastElement + public T last( List in ) { + if ( in != null && !in.isEmpty() ) { + return in.get( in.size() - 1 ); + } + else { + return null; + } + } + + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/LastElement.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/LastElement.java new file mode 100644 index 0000000000000000000000000000000000000000..7fbe0cb229e18457dfec8d3eedd6b0b6370d65d9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/iterable_to_non_iterable/util/LastElement.java @@ -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 io.github.linpeilie.me.iterable_to_non_iterable.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.mapstruct.Qualifier; + +@Qualifier +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.CLASS) +public @interface LastElement { +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningBeanMappingMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningBeanMappingMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..787a7b27b3adedfd7d97f26b14a8e1895ccc648c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningBeanMappingMapper.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +import org.mapstruct.BeanMapping; +import org.mapstruct.Mapper; +import org.mapstruct.control.DeepClone; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface CloningBeanMappingMapper { + + CloningBeanMappingMapper INSTANCE = Mappers.getMapper( CloningBeanMappingMapper.class ); + + @BeanMapping(mappingControl = DeepClone.class) + FridgeDTO clone(FridgeDTO in); + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningListMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningListMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..1cfc3595fdc5ea4eef607e0a9d59584d847cb426 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningListMapper.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +import org.mapstruct.Mapper; +import org.mapstruct.control.DeepClone; +import org.mapstruct.factory.Mappers; + +@Mapper(mappingControl = DeepClone.class) +public interface CloningListMapper { + + CloningListMapper INSTANCE = Mappers.getMapper( CloningListMapper.class ); + + CustomerDto clone(CustomerDto in); + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..ae64974a7c0a6a288611e74682207168d85ddc86 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CloningMapper.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +import org.mapstruct.Mapper; +import org.mapstruct.control.DeepClone; +import org.mapstruct.factory.Mappers; + +@Mapper(mappingControl = DeepClone.class) +public interface CloningMapper { + + CloningMapper INSTANCE = Mappers.getMapper( CloningMapper.class ); + + FridgeDTO clone(FridgeDTO in); + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ComplexMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ComplexMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..5f79693dfaffb1085d517dcbb95494c4f4f5bf91 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ComplexMapper.java @@ -0,0 +1,20 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.mappingcontrol; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; +import org.springframework.stereotype.Component; + +@Component +public class ComplexMapper { + + public String toBeerCount(ShelveDTO in) { + return in.getCoolBeer().getBeerCount(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ConversionMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ConversionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..0a9c400e7c40698a77822fa41c40a1304ff218fa --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ConversionMapper.java @@ -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 io.github.linpeilie.me.mappingcontrol; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface ConversionMapper { + + ConversionMapper INSTANCE = Mappers.getMapper( ConversionMapper.class ); + + Fridge map(CoolBeerDTO in); + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CoolBeerDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CoolBeerDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..14398707298277cca831dfe7835f6ac06fd60988 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CoolBeerDTO.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +public class CoolBeerDTO { + + private String beerCount; + + public String getBeerCount() { + return beerCount; + } + + public void setBeerCount(String beerCount) { + this.beerCount = beerCount; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CustomerDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CustomerDto.java new file mode 100644 index 0000000000000000000000000000000000000000..e1a97583ab78184aeddf53ec36c4522692b819f6 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/CustomerDto.java @@ -0,0 +1,56 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.mappingcontrol; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.List; +import java.util.Map; +import org.mapstruct.control.DeepClone; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = CustomerDto.class, mappingControl = DeepClone.class, reverseConvertGenerate = false) +public class CustomerDto { + + private Long id; + private String customerName; + private List orders; + private Map stock; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public List getOrders() { + return orders; + } + + public void setOrders(List orders) { + this.orders = orders; + } + + public Map getStock() { + return stock; + } + + public void setStock(Map stock) { + this.stock = stock; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/Fridge.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/Fridge.java new file mode 100644 index 0000000000000000000000000000000000000000..4b58628d4ed46f76df5dc2649570452a11303266 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/Fridge.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +public class Fridge { + + private int beerCount; + + public int getBeerCount() { + return beerCount; + } + + public void setBeerCount(int beerCount) { + this.beerCount = beerCount; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/FridgeDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/FridgeDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..22e65d173307e8c9e7de0efa6abb43dd34a00039 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/FridgeDTO.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.mappingcontrol; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import org.mapstruct.control.DeepClone; +import org.mapstruct.control.MappingControl; + +@AutoMappers({ + @AutoMapper(target = FridgeDTO.class, mappingControl = DeepClone.class, reverseConvertGenerate = false), + @AutoMapper(target = Fridge.class, reverseConvertGenerate = false, uses = ComplexMapper.class) +}) +public class FridgeDTO { + + private ShelveDTO shelve; + + public ShelveDTO getShelve() { + return shelve; + } + + public void setShelve(ShelveDTO shelve) { + this.shelve = shelve; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/OrderItemDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/OrderItemDto.java new file mode 100644 index 0000000000000000000000000000000000000000..378080c9563f12408836558e73d7593fbf3e6644 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/OrderItemDto.java @@ -0,0 +1,31 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +/** + * @author Sjaak Derksen + */ +public class OrderItemDto { + + private String name; + private Long quantity; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getQuantity() { + return quantity; + } + + public void setQuantity(Long quantity) { + this.quantity = quantity; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/OrderItemKeyDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/OrderItemKeyDto.java new file mode 100644 index 0000000000000000000000000000000000000000..ca544e7c7c5f255e42d25328697aa29a7ee9129c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/OrderItemKeyDto.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +/** + * @author Sjaak Derksen + */ +public class OrderItemKeyDto { + + private long stockNumber; + + public long getStockNumber() { + return stockNumber; + } + + public void setStockNumber(long stockNumber) { + this.stockNumber = stockNumber; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ShelveDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ShelveDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..1fb93d425b324164c5d27d291f37d3dda775ce2a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/mappingcontrol/ShelveDTO.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.mappingcontrol; + +public class ShelveDTO { + + private CoolBeerDTO coolBeer; + + public CoolBeerDTO getCoolBeer() { + return coolBeer; + } + + public void setCoolBeer(CoolBeerDTO coolBeer) { + this.coolBeer = coolBeer; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishDto.java new file mode 100644 index 0000000000000000000000000000000000000000..826da42ef180e069cbea30b7fafd6d8f33b66b09 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishDto.java @@ -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 io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class FishDto { + + private String kind; + + // make sure that mapping on name does not happen based on name mapping + private String name; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto.java new file mode 100644 index 0000000000000000000000000000000000000000..59f476e10d03c917c2b742f8ccf03001a3292dc4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto.java @@ -0,0 +1,34 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import io.github.linpeilie.me.nested_bean_mappings.model.FishTank; +import lombok.Data; + +@Data +@AutoMapper(target = FishTank.class) +public class FishTankDto { + + @AutoMappings({ + @AutoMapping(target = "fish.type", source = "fish.kind"), + }) + private FishDto fish; + private WaterPlantDto plant; + private String name; + + @AutoMapping(target = "material", source = "material.materialType") + private MaterialDto material; + + @AutoMapping(target = "interior.ornament", source = "ornament") + private OrnamentDto ornament; + + @AutoMapping(target = "quality.report.organisationName", source = "quality.report.organisation.name") + private WaterQualityDto quality; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto1.java new file mode 100644 index 0000000000000000000000000000000000000000..557bf762dbb0a8ad0aa3dee915b07e56b46b9c08 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto1.java @@ -0,0 +1,15 @@ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class FishTankDto1 { + + private FishDto fish; + private WaterPlantDto plant; + private String name; + private MaterialDto material; + private OrnamentDto ornament; + private WaterQualityDto quality; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto2.java new file mode 100644 index 0000000000000000000000000000000000000000..86c87dd50baaed2032cc4c8ea18ff705bc729bb9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankDto2.java @@ -0,0 +1,15 @@ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class FishTankDto2 { + + private FishDto fish; + private WaterPlantDto plant; + private String name; + private MaterialDto material; + private OrnamentDto ornament; + private WaterQualityDto quality; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankWithNestedDocumentDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankWithNestedDocumentDto.java new file mode 100644 index 0000000000000000000000000000000000000000..2ba155af0440adb8001a520cc9bd214a17aa0a74 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/FishTankWithNestedDocumentDto.java @@ -0,0 +1,15 @@ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class FishTankWithNestedDocumentDto { + + private FishDto fish; + private WaterPlantDto plant; + private String name; + private MaterialDto material; + private OrnamentDto ornament; + private WaterQualityWithDocumentDto quality; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/MaterialDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/MaterialDto.java new file mode 100644 index 0000000000000000000000000000000000000000..08daf55ccf07ce248c002a735a734f5edf06f43b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/MaterialDto.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class MaterialDto { + + private String manufacturer; + private MaterialTypeDto materialType; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/MaterialTypeDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/MaterialTypeDto.java new file mode 100644 index 0000000000000000000000000000000000000000..d18c95a91daad5c34e9d6687612628bdfc4a3295 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/MaterialTypeDto.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class MaterialTypeDto { + + private String type; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/OrnamentDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/OrnamentDto.java new file mode 100644 index 0000000000000000000000000000000000000000..7145e9b0857a42ac394c36bf486e34b29d34b7fa --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/OrnamentDto.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class OrnamentDto { + + private String type; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterPlantDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterPlantDto.java new file mode 100644 index 0000000000000000000000000000000000000000..f2a64288d365c10f53a0ff2f993d3703755d3f58 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterPlantDto.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class WaterPlantDto { + + private String kind; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityDto.java new file mode 100644 index 0000000000000000000000000000000000000000..bdf256e1729357005cc96a2fd602b935dc09cee5 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityDto.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class WaterQualityDto { + + private WaterQualityReportDto report; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityOrganisationDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityOrganisationDto.java new file mode 100644 index 0000000000000000000000000000000000000000..823ac6d5446335569f86774e342e99f587a0bd03 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityOrganisationDto.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class WaterQualityOrganisationDto { + + private String name; + private String approval; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityReportDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityReportDto.java new file mode 100644 index 0000000000000000000000000000000000000000..102970d713e8558676cb720ddde32a4ef63bf6f4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityReportDto.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class WaterQualityReportDto { + + private WaterQualityOrganisationDto organisation; + private String verdict; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityWithDocumentDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityWithDocumentDto.java new file mode 100644 index 0000000000000000000000000000000000000000..f48d49d2b032d49a46d3fe31866cfbe719c050d9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/dto/WaterQualityWithDocumentDto.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.dto; + +import lombok.Data; + +@Data +public class WaterQualityWithDocumentDto { + + private WaterQualityReportDto document; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Fish.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Fish.java new file mode 100644 index 0000000000000000000000000000000000000000..c3c1642c59466689af22a2735b01a7bf05d28c57 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Fish.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.model; + +import lombok.Data; + +@Data +public class Fish { + + private String type; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/FishTank.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/FishTank.java new file mode 100644 index 0000000000000000000000000000000000000000..b7cc550bfcb0e2a8baeeb1c16216c0767d42eaa7 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/FishTank.java @@ -0,0 +1,73 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.nested_bean_mappings.model; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankDto; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankDto1; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankDto2; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankWithNestedDocumentDto; +import lombok.Data; + +@Data +@AutoMappers({ + @AutoMapper(target = FishTankDto.class), + @AutoMapper(target = FishTankDto1.class, reverseConvertGenerate = false), + @AutoMapper(target = FishTankDto2.class, reverseConvertGenerate = false), + @AutoMapper(target = FishTankWithNestedDocumentDto.class, reverseConvertGenerate = false), +}) +public class FishTank { + + @AutoMappings({ + @AutoMapping(targetClass = FishTankDto.class, target = "fish.kind", source = "fish.type"), + @AutoMapping(targetClass = FishTankDto.class, target = "fish.name", ignore = true), + @AutoMapping(targetClass = FishTankDto1.class, target = "fish.kind", source = "fish.type"), + @AutoMapping(targetClass = FishTankDto1.class, target = "fish.name", constant = "Nemo"), + @AutoMapping(targetClass = FishTankDto2.class, target = "fish.kind", source = "fish.type"), + @AutoMapping(targetClass = FishTankDto2.class, target = "fish.name", expression = "java(\"Jaws\")"), + @AutoMapping(targetClass = FishTankWithNestedDocumentDto.class, target = "fish.kind", source = "fish.type"), + @AutoMapping(targetClass = FishTankWithNestedDocumentDto.class, target = "fish.name", expression = "java(\"Jaws\")"), + }) + private Fish fish; + + @AutoMappings({ + @AutoMapping(targetClass = FishTankDto2.class, target = "plant", ignore = true), + @AutoMapping(targetClass = FishTankWithNestedDocumentDto.class, target = "plant", ignore = true) + }) + private WaterPlant plant; + private String name; + + @AutoMappings({ + @AutoMapping(targetClass = FishTankDto.class, target = "material.materialType"), + @AutoMapping(targetClass = FishTankDto1.class, target = "material.materialType"), + @AutoMapping(targetClass = FishTankDto1.class, target = "material.manufacturer", constant = "MMM"), + @AutoMapping(targetClass = FishTankDto2.class, target = "material", ignore = true), + @AutoMapping(targetClass = FishTankWithNestedDocumentDto.class, target = "material", ignore = true), + }) + private MaterialType material; + + @AutoMappings({ + @AutoMapping(targetClass = FishTankDto.class, target = "ornament", source = "interior.ornament"), + @AutoMapping(targetClass = FishTankDto1.class, target = "ornament", ignore = true), + @AutoMapping(targetClass = FishTankDto2.class, target = "ornament", ignore = true), + @AutoMapping(targetClass = FishTankWithNestedDocumentDto.class, target = "ornament", ignore = true), + }) + private Interior interior; + + @AutoMappings({ + @AutoMapping(targetClass = FishTankDto.class, target = "quality.report.organisation.name", source = "quality.report.organisationName"), + @AutoMapping(targetClass = FishTankDto1.class, target = "quality", ignore = true), + @AutoMapping(targetClass = FishTankDto2.class, target = "quality.report.organisation.name", expression = "java(\"Dunno\")"), + @AutoMapping(targetClass = FishTankWithNestedDocumentDto.class, target = "quality.document", source = "quality.report"), + @AutoMapping(targetClass = FishTankWithNestedDocumentDto.class, target = "quality.document.organisation.name", constant = "NoIdeaInc"), + }) + private WaterQuality quality; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Interior.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Interior.java new file mode 100644 index 0000000000000000000000000000000000000000..e77a7d84073aab542301b122f265964398683889 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Interior.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.model; + +import lombok.Data; + +@Data +public class Interior { + + private String designer; + private Ornament ornament; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/MaterialType.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/MaterialType.java new file mode 100644 index 0000000000000000000000000000000000000000..2d6e152349c776bd1a62240d00b3cb713c8aebf1 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/MaterialType.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.model; + +import lombok.Data; + +@Data +public class MaterialType { + + private String type; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Ornament.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Ornament.java new file mode 100644 index 0000000000000000000000000000000000000000..5f4949e02a6cb9c94d0aee5841fa26ced59b324e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/Ornament.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.model; + +import lombok.Data; + +@Data +public class Ornament { + + private String type; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterPlant.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterPlant.java new file mode 100644 index 0000000000000000000000000000000000000000..8e6052fe21ad47afd8fd468f78a2e6ad47ee5b56 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterPlant.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.model; + +import lombok.Data; + +@Data +public class WaterPlant { + + private String kind; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterQuality.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterQuality.java new file mode 100644 index 0000000000000000000000000000000000000000..6910b6b6ad5a46a38198f245b66290b95ee047f4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterQuality.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.model; + +import lombok.Data; + +@Data +public class WaterQuality { + + private WaterQualityReport report; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterQualityReport.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterQualityReport.java new file mode 100644 index 0000000000000000000000000000000000000000..ac499ff2554322339047ab1b2bc5c4f7c1b7280e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nested_bean_mappings/model/WaterQualityReport.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nested_bean_mappings.model; + +import lombok.Data; + +@Data +public class WaterQualityReport { + + private String organisationName; + private String verdict; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/CustomMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/CustomMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..f0007e4777db1bba823c47a29adbeae06d1c725e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/CustomMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck; + +import java.math.BigInteger; +import org.springframework.stereotype.Component; + +@Component +public class CustomMapper { + + public MyBigIntWrapper toMyBigIntWrapper(BigInteger bigInteger) { + MyBigIntWrapper wrapper = new MyBigIntWrapper(); + wrapper.setMyBigInt( bigInteger ); + return wrapper; + } + + public MyLongWrapper toMyBigIntWrapperViaPrimitive(long primitive) { + MyLongWrapper wrapper = new MyLongWrapper(); + wrapper.setMyLong( primitive ); + return wrapper; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/MyBigIntWrapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/MyBigIntWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3e07088fa14fd4205ac65082da21a835ef592cff --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/MyBigIntWrapper.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck; + +import java.math.BigInteger; + +/** + * @author Sjaak Derksen + */ +public class MyBigIntWrapper { + + private BigInteger myBigInt; + + public BigInteger getMyBigInt() { + return myBigInt; + } + + public void setMyBigInt(BigInteger myBigInt) { + this.myBigInt = myBigInt; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/MyLongWrapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/MyLongWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..5212690d55a38f59578251f2331ae6adc502aa03 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/MyLongWrapper.java @@ -0,0 +1,23 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck; + +/** + * @author Sjaak Derksen + */ +public class MyLongWrapper { + + private Long myLong; + + public Long getMyLong() { + return myLong; + } + + public void setMyLong(Long myLong) { + this.myLong = myLong; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/NullObject.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/NullObject.java new file mode 100644 index 0000000000000000000000000000000000000000..37c89d48a8b87abe5ae09e77c903333bc758454c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/NullObject.java @@ -0,0 +1,13 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck; + +/** + * @author Sjaak Derksen + */ +public class NullObject { + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/NullObjectMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/NullObjectMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..a2bc3125d2b3a8a1906f5e83a2ccb6fdbbbbe59c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/NullObjectMapper.java @@ -0,0 +1,16 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck; + +import org.springframework.stereotype.Component; + +@Component +public class NullObjectMapper { + + public String toNullString(NullObject in) { + return in.toString(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..4c5444f90e0af9bf436436557b2fd580c48075ce --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/Source.java @@ -0,0 +1,63 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.nullcheck; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.List; + +@AutoMapper(target = Target.class, + uses = {NullObjectMapper.class, CustomMapper.class}, + reverseConvertGenerate = false) +public class Source { + + private NullObject someObject; + private String number; + private List someList; + private Integer someInteger; + private Long someLong; + + public NullObject getSomeObject() { + return someObject; + } + + public void setSomeObject(NullObject someObject) { + this.someObject = someObject; + } + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public List getSomeList() { + return someList; + } + + public void setSomeList(List someList) { + this.someList = someList; + } + + public Integer getSomeInteger() { + return someInteger; + } + + public void setSomeInteger(Integer someInteger) { + this.someInteger = someInteger; + } + + public Long getSomeLong() { + return someLong; + } + + public void setSomeLong(Long someLong) { + this.someLong = someLong; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..ab832c070960c91b7b13aee04d43acc61049d5f8 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/Target.java @@ -0,0 +1,60 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck; + +import java.util.List; + +/** + * @author Sjaak Derksen + */ +public class Target { + + private String someObject; + private Integer number; + private List someList; + private MyBigIntWrapper someInteger; + private MyLongWrapper someLong; + + public String getSomeObject() { + return someObject; + } + + public void setSomeObject(String someObject) { + this.someObject = someObject; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } + + public List getSomeList() { + return someList; + } + + public void setSomeList(List someList) { + this.someList = someList; + } + + public MyBigIntWrapper getSomeInteger() { + return someInteger; + } + + public void setSomeInteger(MyBigIntWrapper someInteger) { + this.someInteger = someInteger; + } + + public MyLongWrapper getSomeLong() { + return someLong; + } + + public void setSomeLong(MyLongWrapper someLong) { + this.someLong = someLong; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseDto.java new file mode 100644 index 0000000000000000000000000000000000000000..b89991b618c98694a511f922a489880129913fd4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseDto.java @@ -0,0 +1,42 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.nullcheck.strategy; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; + +@AutoMappers({ + @AutoMapper(target = HouseEntity.class, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS), + @AutoMapper(target = HouseEntity1.class, nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION), + @AutoMapper(target = HouseEntity2.class, nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION), +}) +public class HouseDto { + + private String owner; + + @AutoMapping(targetClass = HouseEntity2.class, target = "number", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) + private Integer number; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..79892b7c171e49ad41fbd475cd14857a28a85e59 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity.java @@ -0,0 +1,41 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck.strategy; + +public class HouseEntity { + + private String owner; + private boolean ownerSet = false; + + private Integer number; + private boolean numberSet = false; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + ownerSet = true; + this.owner = owner; + } + + public boolean ownerSet() { + return ownerSet; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + numberSet = true; + this.number = number; + } + + public boolean numberSet() { + return numberSet; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity1.java new file mode 100644 index 0000000000000000000000000000000000000000..ee362fc6ab952235eb3a2e1b8c2c7b1bead7f189 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity1.java @@ -0,0 +1,41 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck.strategy; + +public class HouseEntity1 { + + private String owner; + private boolean ownerSet = false; + + private Integer number; + private boolean numberSet = false; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + ownerSet = true; + this.owner = owner; + } + + public boolean ownerSet() { + return ownerSet; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + numberSet = true; + this.number = number; + } + + public boolean numberSet() { + return numberSet; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity2.java new file mode 100644 index 0000000000000000000000000000000000000000..2071821c313e20d05dfc267f69cb0bf90052b569 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseEntity2.java @@ -0,0 +1,41 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck.strategy; + +public class HouseEntity2 { + + private String owner; + private boolean ownerSet = false; + + private Integer number; + private boolean numberSet = false; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + ownerSet = true; + this.owner = owner; + } + + public boolean ownerSet() { + return ownerSet; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + numberSet = true; + this.number = number; + } + + public boolean numberSet() { + return numberSet; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..973d32355ea4882b6441c2557f9c756c1e9aa5c4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullcheck/strategy/HouseMapper.java @@ -0,0 +1,28 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullcheck.strategy; + +import org.mapstruct.BeanMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.factory.Mappers; + +@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +public interface HouseMapper { + + HouseMapper INSTANCE = Mappers.getMapper( HouseMapper.class ); + + HouseEntity mapWithNvcsOnMapper(HouseDto in); + + @BeanMapping(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION) + HouseEntity mapWithNvcsOnBean(HouseDto in); + + @BeanMapping(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION) + @Mapping(target = "number", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) + HouseEntity mapWithNvcsOnMapping(HouseDto in); + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/CarMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/CarMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..ca7249157de2ac98276541fe3985ae464bd28863 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/CarMapper.java @@ -0,0 +1,34 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluemapping; + +import io.github.linpeilie.me.nullvaluemapping._target.CarDto; +import io.github.linpeilie.me.nullvaluemapping.source.Car; +import java.util.List; +import java.util.UUID; +import org.mapstruct.BeanMapping; +import org.mapstruct.IterableMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import static org.mapstruct.NullValueMappingStrategy.RETURN_DEFAULT; + +@Mapper(imports = UUID.class) +public interface CarMapper { + + CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); + + @BeanMapping(nullValueMappingStrategy = RETURN_DEFAULT) + @Mapping(target = "seatCount", source = "numberOfSeats") + @Mapping(target = "model", constant = "ModelT") + @Mapping(target = "catalogId", expression = "java( UUID.randomUUID().toString() )") + CarDto carToCarDto(Car car); + + @IterableMapping(nullValueMappingStrategy = RETURN_DEFAULT) + List carsToCarDtos(List cars); + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/CarDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/CarDto.java new file mode 100644 index 0000000000000000000000000000000000000000..99fd1b3c38f937a32d93f7ea4c3784c2d4eab672 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/CarDto.java @@ -0,0 +1,55 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluemapping._target; + +public class CarDto { + + private String make; + private int seatCount; + private String model; + private String catalogId; + + public CarDto() { + } + + public CarDto(String make, int seatCount) { + this.make = make; + this.seatCount = seatCount; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public int getSeatCount() { + return seatCount; + } + + public void setSeatCount(int seatCount) { + this.seatCount = seatCount; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getCatalogId() { + return catalogId; + } + + public void setCatalogId(String catalogId) { + this.catalogId = catalogId; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/CarDto1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/CarDto1.java new file mode 100644 index 0000000000000000000000000000000000000000..b0b8402a234a7dc237b47ed45a45bb97a5d29003 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/CarDto1.java @@ -0,0 +1,55 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluemapping._target; + +public class CarDto1 { + + private String make; + private int seatCount; + private String model; + private String catalogId; + + public CarDto1() { + } + + public CarDto1(String make, int seatCount) { + this.make = make; + this.seatCount = seatCount; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public int getSeatCount() { + return seatCount; + } + + public void setSeatCount(int seatCount) { + this.seatCount = seatCount; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getCatalogId() { + return catalogId; + } + + public void setCatalogId(String catalogId) { + this.catalogId = catalogId; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/DriverAndCarDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/DriverAndCarDto.java new file mode 100644 index 0000000000000000000000000000000000000000..b00b0e4e7d30c0c4d78c654b8908450c11c3003c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/_target/DriverAndCarDto.java @@ -0,0 +1,28 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluemapping._target; + +public class DriverAndCarDto { + + private String name; + private String make; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Car.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Car.java new file mode 100644 index 0000000000000000000000000000000000000000..b5e77a2cffcebf34ef62534a309cce59add74408 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Car.java @@ -0,0 +1,57 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.nullvaluemapping.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import io.github.linpeilie.me.nullvaluemapping._target.CarDto; +import java.util.UUID; + +import static org.mapstruct.NullValueMappingStrategy.RETURN_DEFAULT; + +@AutoMapper(target = CarDto.class, + imports = UUID.class, + nullValueMappingStrategy = RETURN_DEFAULT, + reverseConvertGenerate = false) +public class Car { + + private String make; + + @AutoMappings({ + @AutoMapping(target = "seatCount", source = "numberOfSeats"), + @AutoMapping(target = "catalogId", expression = "java( UUID.randomUUID().toString() )"), + @AutoMapping(target = "model", constant = "ModelT") + }) + private int numberOfSeats; + + public Car() { + } + + public Car(String make, int numberOfSeats) { + this.make = make; + this.numberOfSeats = numberOfSeats; + + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + + public void setNumberOfSeats(int numberOfSeats) { + this.numberOfSeats = numberOfSeats; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Car1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Car1.java new file mode 100644 index 0000000000000000000000000000000000000000..de5764fe25ce4ed8a8b27fbd789f885fde6104f1 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Car1.java @@ -0,0 +1,59 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.nullvaluemapping.source; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import io.github.linpeilie.me.nullvaluemapping._target.CarDto1; +import java.util.UUID; +import org.mapstruct.NullValueMappingStrategy; + +import static org.mapstruct.NullValueMappingStrategy.RETURN_DEFAULT; + +@AutoMapper(target = CarDto1.class, + imports = UUID.class, + nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValueIterableMappingStrategy = NullValueMappingStrategy.RETURN_NULL, + reverseConvertGenerate = false) +public class Car1 { + + private String make; + + @AutoMappings({ + @AutoMapping(target = "seatCount", source = "numberOfSeats"), + @AutoMapping(target = "catalogId", expression = "java( UUID.randomUUID().toString() )"), + @AutoMapping(target = "model", constant = "ModelT") + }) + private int numberOfSeats; + + public Car1() { + } + + public Car1(String make, int numberOfSeats) { + this.make = make; + this.numberOfSeats = numberOfSeats; + + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + + public void setNumberOfSeats(int numberOfSeats) { + this.numberOfSeats = numberOfSeats; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Driver.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Driver.java new file mode 100644 index 0000000000000000000000000000000000000000..3f92d13b49d7c9aeda2370ee2b863ed4013710dc --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluemapping/source/Driver.java @@ -0,0 +1,23 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluemapping.source; + +public class Driver { + + private String name; + + public Driver(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/Address.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/Address.java new file mode 100644 index 0000000000000000000000000000000000000000..23f014080d632637bdc0e03fdab45a4b1f1e0367 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/Address.java @@ -0,0 +1,38 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.nullvaluepropertymapping; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import org.mapstruct.NullValuePropertyMappingStrategy; + +@AutoMappers({ + @AutoMapper(target = AddressDTO.class, + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT), + @AutoMapper(target = AddressDTO1.class, + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE), + @AutoMapper(target = AddressDTO2.class) +}) +public class Address { + + @AutoMappings({ + @AutoMapping(targetClass = AddressDTO.class, target = "houseNo", defaultValue = "0"), + @AutoMapping(targetClass = AddressDTO1.class, target = "houseNo"), + @AutoMapping(targetClass = AddressDTO2.class, target = "houseNo") + }) + private Integer houseNumber; + + public Integer getHouseNumber() { + return houseNumber; + } + + public void setHouseNumber(Integer houseNumber) { + this.houseNumber = houseNumber; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..8cc051a1ba0a93e7faa4a79fc993322c4fb1ff9f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +public class AddressDTO { + + private Integer houseNo; + + public Integer getHouseNo() { + return houseNo; + } + + public void setHouseNo(Integer houseNo) { + this.houseNo = houseNo; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO1.java new file mode 100644 index 0000000000000000000000000000000000000000..aae9fdb25df21266b7336bc8469fe8a6b74683fc --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO1.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +public class AddressDTO1 { + + private Integer houseNo; + + public Integer getHouseNo() { + return houseNo; + } + + public void setHouseNo(Integer houseNo) { + this.houseNo = houseNo; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO2.java new file mode 100644 index 0000000000000000000000000000000000000000..0e3ae3ad0ec61e3e5107fd88d420f853041a3cae --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/AddressDTO2.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +public class AddressDTO2 { + + private Integer houseNo; + + public Integer getHouseNo() { + return houseNo; + } + + public void setHouseNo(Integer houseNo) { + this.houseNo = houseNo; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/Customer.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/Customer.java new file mode 100644 index 0000000000000000000000000000000000000000..4706a907b2c1582cce7ed8db8715707139ebdff2 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/Customer.java @@ -0,0 +1,59 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.nullvaluepropertymapping; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import java.util.List; +import org.mapstruct.Mapping; +import org.mapstruct.NullValuePropertyMappingStrategy; + +import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE; + +@AutoMappers({ + @AutoMapper(target = UserDTO.class, + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT, + reverseConvertGenerate = false), + @AutoMapper(target = UserDTO1.class, + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, + reverseConvertGenerate = false), + @AutoMapper(target = CustomerDTO.class, + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, + reverseConvertGenerate = false), + @AutoMapper(target = CustomerDTO1.class, + reverseConvertGenerate = false) +}) +public class Customer { + + @AutoMappings({ + @AutoMapping(targetClass = UserDTO.class, target = "homeDTO.addressDTO"), + @AutoMapping(targetClass = UserDTO1.class, target = "homeDTO.addressDTO"), + @AutoMapping(targetClass = CustomerDTO1.class, target = "address", nullValuePropertyMappingStrategy = IGNORE), + }) + private Address address; + + @AutoMapping(targetClass = CustomerDTO1.class, target = "details", nullValuePropertyMappingStrategy = IGNORE) + private List details; + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public List getDetails() { + return details; + } + + public void setDetails(List details) { + this.details = details; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/CustomerDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/CustomerDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..4f1824a4a9f07b403c663ec0bc30def377268750 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/CustomerDTO.java @@ -0,0 +1,30 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +import java.util.List; + +public class CustomerDTO { + + private AddressDTO1 address; + private List details; + + public AddressDTO1 getAddress() { + return address; + } + + public void setAddress(AddressDTO1 address) { + this.address = address; + } + + public List getDetails() { + return details; + } + + public void setDetails(List details) { + this.details = details; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/CustomerDTO1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/CustomerDTO1.java new file mode 100644 index 0000000000000000000000000000000000000000..9d13f01449b10b9b04aa289a51663c7c6ce9ddaf --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/CustomerDTO1.java @@ -0,0 +1,30 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +import java.util.List; + +public class CustomerDTO1 { + + private AddressDTO2 address; + private List details; + + public AddressDTO2 getAddress() { + return address; + } + + public void setAddress(AddressDTO2 address) { + this.address = address; + } + + public List getDetails() { + return details; + } + + public void setDetails(List details) { + this.details = details; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/HomeDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/HomeDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..037237775f1a756905788bc0ed5782d44e5f227f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/HomeDTO.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +public class HomeDTO { + + private AddressDTO addressDTO; + + public AddressDTO getAddressDTO() { + return addressDTO; + } + + public void setAddressDTO(AddressDTO addressDTO) { + this.addressDTO = addressDTO; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/HomeDTO1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/HomeDTO1.java new file mode 100644 index 0000000000000000000000000000000000000000..07c88c3762b873b505dec1a0c0b2df429906c0c8 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/HomeDTO1.java @@ -0,0 +1,19 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +public class HomeDTO1 { + + private AddressDTO1 addressDTO; + + public AddressDTO1 getAddressDTO() { + return addressDTO; + } + + public void setAddressDTO(AddressDTO1 addressDTO) { + this.addressDTO = addressDTO; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/NvpmsConfig.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/NvpmsConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..ee45d6bd77e55c23af81e308bedc47997fa83dda --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/NvpmsConfig.java @@ -0,0 +1,13 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +import org.mapstruct.MapperConfig; +import org.mapstruct.NullValuePropertyMappingStrategy; + +@MapperConfig( nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE ) +public interface NvpmsConfig { +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/UserDTO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/UserDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..be904fa79e650b2595749c8fe0292693c10fe02f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/UserDTO.java @@ -0,0 +1,30 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +import java.util.List; + +public class UserDTO { + + private HomeDTO homeDTO; + private List details; + + public HomeDTO getHomeDTO() { + return homeDTO; + } + + public void setHomeDTO(HomeDTO homeDTO) { + this.homeDTO = homeDTO; + } + + public List getDetails() { + return details; + } + + public void setDetails(List details) { + this.details = details; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/UserDTO1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/UserDTO1.java new file mode 100644 index 0000000000000000000000000000000000000000..6c6f4a3d6869ca25256f22a2b18074fba619a30d --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/nullvaluepropertymapping/UserDTO1.java @@ -0,0 +1,30 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.nullvaluepropertymapping; + +import java.util.List; + +public class UserDTO1 { + + private HomeDTO1 homeDTO; + private List details; + + public HomeDTO1 getHomeDTO() { + return homeDTO; + } + + public void setHomeDTO(HomeDTO1 homeDTO) { + this.homeDTO = homeDTO; + } + + public List getDetails() { + return details; + } + + public void setDetails(List details) { + this.details = details; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/CountryEnum.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/CountryEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..5d0543ed4486fc335b82846385b874259c155157 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/CountryEnum.java @@ -0,0 +1,15 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.constants; + +/** + * + * @author Sjaak Derksen + */ +public enum CountryEnum { + + GERMANY, THE_NETHERLANDS, BELGIUM; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..53c7d4d62baf780b32b1c7011af4f826d57f9865 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source.java @@ -0,0 +1,35 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.constants; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = Target.class, uses = StringList1Mapper.class) +public class Source { + + @AutoMappings({ + @AutoMapping(target = "stringConstant", constant = "stringConstant"), + @AutoMapping(target = "integerConstant", constant = "14"), + @AutoMapping(target = "longWrapperConstant", constant = "3001L"), + @AutoMapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"), + @AutoMapping(target = "nameConstants", constant = "jack-jill-tom"), + @AutoMapping(target = "country", constant = "THE_NETHERLANDS") + }) + private String propertyThatShouldBeMapped; + + public String getPropertyThatShouldBeMapped() { + return propertyThatShouldBeMapped; + } + + public void setPropertyThatShouldBeMapped(String propertyThatShouldBeMapped) { + this.propertyThatShouldBeMapped = propertyThatShouldBeMapped; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source1.java new file mode 100644 index 0000000000000000000000000000000000000000..0dccc2a18332c5aeefcdf04e44707491d2c3643a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source1.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.constants; + +/** + * + * @author Sjaak Derksen + */ +public class Source1 { + + private String someProp; + + public String getSomeProp() { + return someProp; + } + + public void setSomeProp( String someProp ) { + this.someProp = someProp; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source2.java new file mode 100644 index 0000000000000000000000000000000000000000..3553765d4a6d2874ac19115f1f0570ac55c57f5b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Source2.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.constants; + +/** + * + * @author Sjaak Derksen + */ +public class Source2 { + + private String anotherProp; + + public String getAnotherProp() { + return anotherProp; + } + + public void setAnotherProp( String anotherProp ) { + this.anotherProp = anotherProp; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/StringList1Mapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/StringList1Mapper.java new file mode 100644 index 0000000000000000000000000000000000000000..0cb4f14d62a6bcc7ce0a6efb5ec1dd9095fbb87e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/StringList1Mapper.java @@ -0,0 +1,13 @@ +package io.github.linpeilie.me.source.constants; + +import java.util.Arrays; +import java.util.List; +import org.springframework.stereotype.Component; + +@Component +public class StringList1Mapper { + + public List stringToStringList(String string) { + return string == null ? null : Arrays.asList( string.split( "-" ) ); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..868e8ed040a7f6e2f1b85930b2654fda997e8e98 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Target.java @@ -0,0 +1,89 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.source.constants; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author Sjaak Derksen + */ +@AutoMapper(target = Source.class, uses = StringList1Mapper.class) +public class Target { + + private String propertyThatShouldBeMapped; + private String stringConstant; + private String emptyStringConstant; + private int integerConstant; + private Long longWrapperConstant; + private Date dateConstant; + private List nameConstants = new ArrayList(); + private CountryEnum country; + + public String getPropertyThatShouldBeMapped() { + return propertyThatShouldBeMapped; + } + + public void setPropertyThatShouldBeMapped(String propertyThatShouldBeMapped) { + this.propertyThatShouldBeMapped = propertyThatShouldBeMapped; + } + + public String getStringConstant() { + return stringConstant; + } + + public void setStringConstant(String stringConstant) { + this.stringConstant = stringConstant; + } + + public int getIntegerConstant() { + return integerConstant; + } + + public void setIntegerConstant(int integerConstant) { + this.integerConstant = integerConstant; + } + + public Long getLongWrapperConstant() { + return longWrapperConstant; + } + + public void setLongWrapperConstant(Long longWrapperConstant) { + this.longWrapperConstant = longWrapperConstant; + } + + public Date getDateConstant() { + return dateConstant; + } + + public void setDateConstant(Date dateConstant) { + this.dateConstant = dateConstant; + } + + public List getNameConstants() { + return nameConstants; + } + + public String getEmptyStringConstant() { + return emptyStringConstant; + } + + public void setEmptyStringConstant(String emptyStringConstant) { + this.emptyStringConstant = emptyStringConstant; + } + + public CountryEnum getCountry() { + return country; + } + + public void setCountry(CountryEnum country) { + this.country = country; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Target2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Target2.java new file mode 100644 index 0000000000000000000000000000000000000000..da1ff550522bd24b0e13cbe90296c0732439ee4b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/constants/Target2.java @@ -0,0 +1,42 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.constants; + +/** + * + * @author Sjaak Derksen + */ +public class Target2 { + + private String someProp; + private String anotherProp; + private String someConstant; + + public String getSomeProp() { + return someProp; + } + + public void setSomeProp( String someProp ) { + this.someProp = someProp; + } + + public String getAnotherProp() { + return anotherProp; + } + + public void setAnotherProp( String anotherProp ) { + this.anotherProp = anotherProp; + } + + public String getSomeConstant() { + return someConstant; + } + + public void setSomeConstant( String someConstant ) { + this.someConstant = someConstant; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..87febcf735af7bdbe3d896380a8484c64e348d8e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Source.java @@ -0,0 +1,70 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.source.defaultExpressions.java; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import java.time.LocalDate; +import java.time.Month; +import java.time.ZoneOffset; +import java.util.Date; + +@AutoMappers({ + @AutoMapper(target = Target.class, reverseConvertGenerate = false, imports = {Date.class}), + @AutoMapper(target = Target1.class, + reverseConvertGenerate = false, + imports = {Date.class, LocalDate.class, ZoneOffset.class, Month.class}) +}) +public class Source { + + @AutoMappings({ + @AutoMapping(targetClass = Target.class, target = "sourceId", defaultExpression = "java( String.valueOf( \"test\" ) )"), + @AutoMapping( + targetClass = Target1.class, + target = "sourceId", + defaultExpression = "java( new StringBuilder()\n.append( \"test\" )\n.toString() )" + ) + }) + private int id = -1; + + @AutoMappings({ + @AutoMapping(targetClass = Target.class, target = "sourceDate", defaultExpression = "java( new Date( 30L ))"), + @AutoMapping( + targetClass = Target1.class, + target = "sourceDate", + defaultExpression = "java(" + + "Date.from(\n" + + "LocalDate.of( 2022, Month.JUNE, 5 )\n" + + ".atTime( 17, 10 )\n" + + ".toInstant( ZoneOffset.UTC )\n)" + + ")" + ) + }) + private Date date; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public boolean hasId() { + return id != -1; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..c6b681a26bd6702c490f087a1d66ae65faa2dc88 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Target.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.defaultExpressions.java; + +import java.util.Date; + +/** + * @author Jeffrey Smyth + */ +public class Target { + + private String sourceId; + private Date sourceDate; + + public String getSourceId() { + return sourceId; + } + + public void setSourceId(String sourceId) { + this.sourceId = sourceId; + } + + public Date getSourceDate() { + return sourceDate; + } + + public void setSourceDate(Date sourceDate) { + this.sourceDate = sourceDate; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Target1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Target1.java new file mode 100644 index 0000000000000000000000000000000000000000..fc1bc145f5205929665cd2e913ed8d8ce2620eec --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/defaultExpressions/java/Target1.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.defaultExpressions.java; + +import java.util.Date; + +/** + * @author Jeffrey Smyth + */ +public class Target1 { + + private String sourceId; + private Date sourceDate; + + public String getSourceId() { + return sourceId; + } + + public void setSourceId(String sourceId) { + this.sourceId = sourceId; + } + + public Date getSourceDate() { + return sourceDate; + } + + public void setSourceDate(Date sourceDate) { + this.sourceDate = sourceDate; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/BooleanWorkAroundMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/BooleanWorkAroundMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..b6077698832bf92a1376173d76c2445f11a99508 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/BooleanWorkAroundMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public interface BooleanWorkAroundMapper { + + BooleanWorkAroundMapper INSTANCE = Mappers.getMapper( BooleanWorkAroundMapper.class ); + + @Mapping( expression = "java(source.isVal())", target = "val" ) + TargetBooleanWorkAround mapST( SourceBooleanWorkAround source ); + + SourceBooleanWorkAround mapTS( TargetBooleanWorkAround target ); +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/MultiLineExpressionMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/MultiLineExpressionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..755e6b8d3a0dad0acb6ada8b7fceb4d1035b4ce2 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/MultiLineExpressionMapper.java @@ -0,0 +1,37 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import io.github.linpeilie.me.source.expressions.java.mapper.TimeAndFormat; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author Filip Hrisafov + */ +@Mapper(imports = TimeAndFormat.class) +public interface MultiLineExpressionMapper { + + + MultiLineExpressionMapper INSTANCE = Mappers.getMapper( MultiLineExpressionMapper.class ); + + @Mappings({ + @Mapping(target = "timeAndFormat", expression = "java( new TimeAndFormat(\ns.getTime(),\ns.getFormat()\n ))"), + @Mapping(target = "anotherProp", ignore = true) + }) + Target mapUsingMultiLineExpression(Source s); + + @Mappings({ + @Mapping( + target = "timeAndFormat", + expression = " java( new TimeAndFormat(\ns.getTime(),\ns.getFormat()\n )) " + ), + @Mapping(target = "anotherProp", ignore = true) + }) + Target1 mapUsingMultiLineExpressionWithLeadingSpaces(Source s); +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/QualifierProvider.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/QualifierProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..eb54e06bfb896ebd60e2e3c1cf36714b102595cf --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/QualifierProvider.java @@ -0,0 +1,17 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +public class QualifierProvider { + + public @interface ToUpper { + } + + @ToUpper + public String toUpper( String string ) { + return string.toUpperCase(); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..7395dc229d0d2096b816b55270ee977514a7e8e1 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Source.java @@ -0,0 +1,52 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.source.expressions.java; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import io.github.linpeilie.me.source.expressions.java.mapper.TimeAndFormat; +import java.util.Date; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +@AutoMappers({ + @AutoMapper(target = Target.class, reverseConvertGenerate = false, imports = TimeAndFormat.class), + @AutoMapper(target = Target1.class, reverseConvertGenerate = false, imports = TimeAndFormat.class) +}) +public class Source { + + @AutoMappings({ + @AutoMapping(targetClass = Target.class, target = "timeAndFormat", expression = "java( new TimeAndFormat(\nsource.getTime(),\nsource.getFormat()\n ))"), + @AutoMapping(target = "anotherProp", ignore = true), + @AutoMapping( + targetClass = Target1.class, + target = "timeAndFormat", + expression = " java( new TimeAndFormat(\nsource.getTime(),\nsource.getFormat()\n )) " + ), + }) + private String format; + private Date time; + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Source2.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Source2.java new file mode 100644 index 0000000000000000000000000000000000000000..0e6e666918bb57bd15ea1cc2df4016c081ec504c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Source2.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +/** + * + * @author Sjaak Derksen + */ +public class Source2 { + + private String anotherProp; + + public String getAnotherProp() { + return anotherProp; + } + + public void setAnotherProp( String anotherProp ) { + this.anotherProp = anotherProp; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceBooleanWorkAround.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceBooleanWorkAround.java new file mode 100644 index 0000000000000000000000000000000000000000..611eaad3d2497cc62c8ecad0e580377d80754d47 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceBooleanWorkAround.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; + +@AutoMapper(target = TargetBooleanWorkAround.class) +public class SourceBooleanWorkAround { + + @AutoMapping( expression = "java(source.isVal())", target = "val" ) + private Boolean val; + + public Boolean isVal() { + return val; + } + + public void setVal(Boolean val) { + this.val = val; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceList.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceList.java new file mode 100644 index 0000000000000000000000000000000000000000..0cfbcd879e85210d0dab7dfc988585621e65c868 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceList.java @@ -0,0 +1,31 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import java.util.Arrays; +import java.util.List; +import org.mapstruct.Mapping; + +@AutoMappers({ + @AutoMapper(target = TargetList.class, imports = { Arrays.class }) +}) +public class SourceList { + + @AutoMapping(target = "list", expression = "java(Arrays.asList( \"test2\" ))") + private List list; + + public List getList() { + return list; + } + + public void setList( List list ) { + this.list = list; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceTargetListMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceTargetListMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..722e80ba30db2208c007cbbf9e6f7f7fd23a0f5f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/SourceTargetListMapper.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import java.util.Arrays; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( imports = { Arrays.class } ) +public interface SourceTargetListMapper { + + SourceTargetListMapper INSTANCE = Mappers.getMapper( SourceTargetListMapper.class ); + + @Mapping(target = "list", expression = "java(Arrays.asList( \"test2\" ))") + TargetList map( SourceList source ); +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..0eb7fc18da39060d85483b0dcfa0eab4c295064e --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Target.java @@ -0,0 +1,34 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import io.github.linpeilie.me.source.expressions.java.mapper.TimeAndFormat; + +/** + * @author Sjaak Derksen + */ +public class Target { + + private TimeAndFormat timeAndFormat; + private String anotherProp; + + public TimeAndFormat getTimeAndFormat() { + return timeAndFormat; + } + + public String getAnotherProp() { + return anotherProp; + } + + public void setAnotherProp( String anotherProp ) { + this.anotherProp = anotherProp; + } + + public void setTimeAndFormat(TimeAndFormat timeAndFormat) { + this.timeAndFormat = timeAndFormat; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Target1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Target1.java new file mode 100644 index 0000000000000000000000000000000000000000..925d4df040cd7e4c3f7a87c7da689a725a00c2b3 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/Target1.java @@ -0,0 +1,34 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import io.github.linpeilie.me.source.expressions.java.mapper.TimeAndFormat; + +/** + * @author Sjaak Derksen + */ +public class Target1 { + + private TimeAndFormat timeAndFormat; + private String anotherProp; + + public TimeAndFormat getTimeAndFormat() { + return timeAndFormat; + } + + public String getAnotherProp() { + return anotherProp; + } + + public void setAnotherProp( String anotherProp ) { + this.anotherProp = anotherProp; + } + + public void setTimeAndFormat(TimeAndFormat timeAndFormat) { + this.timeAndFormat = timeAndFormat; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/TargetBooleanWorkAround.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/TargetBooleanWorkAround.java new file mode 100644 index 0000000000000000000000000000000000000000..53609a0158b0e378d293c8c6e88e01407d0a3426 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/TargetBooleanWorkAround.java @@ -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 io.github.linpeilie.me.source.expressions.java; + +public class TargetBooleanWorkAround { + private boolean val; + + public boolean isVal() { + return val; + } + + public void setVal(boolean val) { + this.val = val; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/TargetList.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/TargetList.java new file mode 100644 index 0000000000000000000000000000000000000000..23461720a62d59fbb5d38bb7b5c27309f2b0f5a7 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/TargetList.java @@ -0,0 +1,23 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class TargetList { + + private List list = new ArrayList<>(); + + public List getList() { + return list; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/mapper/TimeAndFormat.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/mapper/TimeAndFormat.java new file mode 100644 index 0000000000000000000000000000000000000000..cf91b0bf9e637e686d524af5b48e133494a68f33 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/expressions/java/mapper/TimeAndFormat.java @@ -0,0 +1,37 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.expressions.java.mapper; + +import java.util.Date; + +/** + * @author Sjaak Derksen + */ +public class TimeAndFormat { + private Date time; + private String format; + + public TimeAndFormat(Date time, String format) { + this.time = time; + this.format = format; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + public String getFormat() { + return format; + } + + public void setFormat(String tfFormat) { + this.format = tfFormat; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..2ae43c2b1427d90dc1abcaaa710d5c12fbde8112 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/Source.java @@ -0,0 +1,44 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.source.manytargetproperties; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; + +@AutoMapper(target = Target.class, uses = TimeAndFormatMapper.class, reverseConvertGenerate = false, + mapperName = "SourceToTargetForManyTargetPropertiesMapper") +public class Source { + + @AutoMappings({ + @AutoMapping(target = "time", source = "timeAndFormat"), + @AutoMapping(target = "format", source = "timeAndFormat") + }) + private TimeAndFormat timeAndFormat; + + @AutoMappings({ + @AutoMapping(target = "name1", source = "name"), + @AutoMapping(target = "name2", source = "name") + }) + private String name; + + public TimeAndFormat getTimeAndFormat() { + return timeAndFormat; + } + + public void setTimeAndFormat(TimeAndFormat timeAndFormat) { + this.timeAndFormat = timeAndFormat; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..1adea9a30ee11a3ec3a74864af390115148c05d9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/Target.java @@ -0,0 +1,51 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.manytargetproperties; + +import java.util.Date; + +/** + * @author Sjaak Derksen + */ +public class Target { + + private String format; + private Date time; + private String name1; + private String name2; + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + public String getName1() { + return name1; + } + + public void setName1(String name1) { + this.name1 = name1; + } + + public String getName2() { + return name2; + } + + public void setName2(String name2) { + this.name2 = name2; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/TimeAndFormat.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/TimeAndFormat.java new file mode 100644 index 0000000000000000000000000000000000000000..7d3ade7233b22da66a03c89b7ea3734e8b0c1c9b --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/TimeAndFormat.java @@ -0,0 +1,32 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.manytargetproperties; + +import java.util.Date; + +/** + * @author Sjaak Derksen + */ +public class TimeAndFormat { + private Date tfTime; + private String tfFormat; + + public Date getTfTime() { + return tfTime; + } + + public void setTfTime(Date tfTime) { + this.tfTime = tfTime; + } + + public String getTfFormat() { + return tfFormat; + } + + public void setTfFormat(String tfFormat) { + this.tfFormat = tfFormat; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/TimeAndFormatMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/TimeAndFormatMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..fb56518038389ab47ffc51a7a677b8baaf1f08c2 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/manytargetproperties/TimeAndFormatMapper.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.manytargetproperties; + +import java.util.Date; +import org.springframework.stereotype.Component; + +/** + * @author Sjaak Derksen + */ +@Component +public class TimeAndFormatMapper { + + public String getFormat(TimeAndFormat t) { + return t != null ? t.getTfFormat() : null; + } + + public Date getTime(TimeAndFormat t) { + return t != null ? t.getTfTime() : null; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalSource.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalSource.java new file mode 100644 index 0000000000000000000000000000000000000000..98c3aae7c94082f3f071f5577881308b3c72e98c --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalSource.java @@ -0,0 +1,36 @@ +package io.github.linpeilie.me.source.nullvaluecheckstrategy; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; + +import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION; + +@AutoMappers({ + @AutoMapper( + target = RockFestivalTarget.class, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + reverseConvertGenerate = false + ), + @AutoMapper( + target = RockFestivalTarget1.class, + nullValueCheckStrategy = ON_IMPLICIT_CONVERSION, + reverseConvertGenerate = false + ), +}) +public class RockFestivalSource { + + @AutoMapping( target = "stage", source = "artistName" ) + private String artistName; + + public String getArtistName() { + return artistName; + } + + public void setArtistName(String artistName) { + this.artistName = artistName; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalTarget.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalTarget.java new file mode 100644 index 0000000000000000000000000000000000000000..f07e7dbcd9ba2c4bae518c206e90c9b45fbf07af --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalTarget.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.nullvaluecheckstrategy; + +/** + * + * @author Sjaak Derksen + */ +public class RockFestivalTarget { + + private Stage stage; + + public Stage getStage() { + return stage; + } + + public void setStage(Stage stage) { + this.stage = stage; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalTarget1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalTarget1.java new file mode 100644 index 0000000000000000000000000000000000000000..e31627d3938566fde85295c138b6ffa08e72f018 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/RockFestivalTarget1.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.nullvaluecheckstrategy; + +/** + * + * @author Sjaak Derksen + */ +public class RockFestivalTarget1 { + + private Stage stage; + + public Stage getStage() { + return stage; + } + + public void setStage(Stage stage) { + this.stage = stage; + } + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/Stage.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/Stage.java new file mode 100644 index 0000000000000000000000000000000000000000..ea21d0ad0b49701f6eb46a027c3fca80183a5376 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/Stage.java @@ -0,0 +1,40 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie.me.source.nullvaluecheckstrategy; + +import java.util.Arrays; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public enum Stage { + + MAIN("Paul McCartney", "Ellie Goulding", "Disclosure", "Kaiser Chiefs", "Rammstein"), + KLUB_C("James Blake", "Lost Frequencies"), + THE_BARN("New Order", "Year and Years"); + + private final List artists; + + Stage(String... artist) { + this.artists = Arrays.asList( artist ); + } + + public static Stage forArtist( String name ) { + + if ( name == null ) { + throw new IllegalArgumentException(); + } + + for ( Stage value : Stage.values() ) { + if ( value.artists.contains( name ) ) { + return value; + } + } + return null; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/StageMapper.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/StageMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..63639ef719ba7febf79c3ced65e727a06a33ab7a --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/source/nullvaluecheckstrategy/StageMapper.java @@ -0,0 +1,11 @@ +package io.github.linpeilie.me.source.nullvaluecheckstrategy; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface StageMapper { + default Stage artistToStage(String name) { + return Stage.forArtist(name); + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/unmappedtarget/Source.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/unmappedtarget/Source.java new file mode 100644 index 0000000000000000000000000000000000000000..71e7b3adf4ba20f8c543c14912b144aecdc476a3 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/unmappedtarget/Source.java @@ -0,0 +1,38 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie.me.unmappedtarget; + +import io.github.linpeilie.annotations.AutoMapper; +import org.mapstruct.ReportingPolicy; + +@AutoMapper( + target = Target.class, + unmappedSourcePolicy = ReportingPolicy.WARN, + unmappedTargetPolicy = ReportingPolicy.IGNORE +) +public class Source { + + private Long foo; + + private String qux; + + public Long getFoo() { + return foo; + } + + public void setFoo(Long foo) { + this.foo = foo; + } + + public String getQux() { + return qux; + } + + public void setQux(String qux) { + this.qux = qux; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/unmappedtarget/Target.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/unmappedtarget/Target.java new file mode 100644 index 0000000000000000000000000000000000000000..411761d433b45fc86d4d748104c06440b8c94ecf --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/me/unmappedtarget/Target.java @@ -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 io.github.linpeilie.me.unmappedtarget; + +import io.github.linpeilie.annotations.AutoMapper; +import org.mapstruct.ReportingPolicy; + +@AutoMapper( + target = Source.class, + unmappedSourcePolicy = ReportingPolicy.WARN, + unmappedTargetPolicy = ReportingPolicy.IGNORE +) +public class Target { + + private Long foo; + private int bar; + + public Long getFoo() { + return foo; + } + + public void setFoo(Long foo) { + this.foo = foo; + } + + public int getBar() { + return bar; + } + + public void setBar(int bar) { + this.bar = bar; + } +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Car.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Car.java index 23aba5fd697ac7208aa96c5fbad9704c88b06c5f..4a67e749fab9bfe598e056f72e84f3a344dd5db5 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Car.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Car.java @@ -10,6 +10,7 @@ import lombok.Data; public class Car { private String make; + @AutoMapping(target = "seatMaterial", source = "seatConfiguration.seatMaterial") private SeatConfiguration seatConfiguration; private CarType type; private Tyre tyre; diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Car1.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Car1.java new file mode 100644 index 0000000000000000000000000000000000000000..45a2569e5f943267f0c360df340c5d6b864d1c6f --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/Car1.java @@ -0,0 +1,15 @@ +package io.github.linpeilie.model; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import java.time.LocalDateTime; +import lombok.Data; + +@AutoMapper(target = CarDto.class, imports = LocalDateTime.class) +@Data +public class Car1 { + + @AutoMapping(target = "seatMaterial", source = "seatConfiguration.seatMaterial", reverseConvertGenerate = false) + private SeatConfiguration seatConfiguration; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/CarDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/CarDto.java index b7bd6f150ca01175f71591868ea8b518bb9ab971..e0e5b6656852320b0e91a3d3d3ad43b72caf67f6 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/CarDto.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/CarDto.java @@ -10,5 +10,6 @@ public class CarDto { private String type; private List wheels; private TyreDTO tyre; + private String seatMaterial; } diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/EnglishRelease.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/EnglishRelease.java index 104423a2b91b5ac5aa35360998502baa41815fb0..2cbff8752c2e3f20ffa221b9b66ea90b8701acd4 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/EnglishRelease.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/EnglishRelease.java @@ -10,7 +10,7 @@ import lombok.Data; @AutoMapper(target = FrenchRelease.class, uses = Titles.class) public class EnglishRelease { - @AutoMapping(qualifiedByName = "EnglishToFrench") + @AutoMapping(qualifiedByName = "EnglishToFrench", defaultValue = "DefaultTitle") @ReverseAutoMapping(qualifiedByName = "FrenchToEnglish") private String title; diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsDto.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsDto.java index 7e9c50e3a7a6bd9a3705c9a9f3a1ac9594c6e93f..5ec6fd0a748dc458a13036439550e86c69305b5e 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsDto.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsDto.java @@ -9,7 +9,7 @@ import lombok.Data; @Data @AutoMappers({ @AutoMapper(target = Goods.class), - @AutoMapper(target = GoodsVo.class) +// @AutoMapper(target = GoodsVo.class) }) public class GoodsDto extends BaseDTO { diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsVo.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsVo.java index deb4910aed5aaf008561e86c29b0502ccb8cd7e2..2f2f39cbe67c3a89e15425227b32aadfe6081a8f 100644 --- a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsVo.java +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GoodsVo.java @@ -4,7 +4,7 @@ import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; @Data -@AutoMapper(target = GoodsDto.class) +//@AutoMapper(target = GoodsDto.class) public class GoodsVo extends BaseVO { private Integer price; diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GrantedAuthority.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GrantedAuthority.java new file mode 100644 index 0000000000000000000000000000000000000000..c38b0242bf4c0e9cbec62daf8fd682ef29184bd9 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/GrantedAuthority.java @@ -0,0 +1,7 @@ +package io.github.linpeilie.model; + +public class GrantedAuthority { + + private String authority; + +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/LoginUser.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/LoginUser.java new file mode 100644 index 0000000000000000000000000000000000000000..c9844dd7559345d0e28575b5a4680d03ca780623 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/LoginUser.java @@ -0,0 +1,14 @@ +package io.github.linpeilie.model; + +import java.util.Collection; +import lombok.Data; + +@Data +public class LoginUser { + + private Long userId; + + private String username; + + private Collection authorities; +} diff --git a/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/LoginUserVO.java b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/LoginUserVO.java new file mode 100644 index 0000000000000000000000000000000000000000..74cae5f118346be41a2240a66d90b6adeb83f029 --- /dev/null +++ b/example/spring-boot-with-lombok/src/main/java/io/github/linpeilie/model/LoginUserVO.java @@ -0,0 +1,18 @@ +package io.github.linpeilie.model; + +import io.github.linpeilie.annotations.AutoMapper; +import java.util.Collection; +import lombok.Data; +import org.mapstruct.CollectionMappingStrategy; + +@Data +@AutoMapper(target = LoginUser.class, collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE) +public class LoginUserVO { + + private Long userId; + + private String username; + + private Collection authorities; + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/AdderTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/AdderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..987685a493aeb49414e44e355d29141b31f0b70f --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/AdderTest.java @@ -0,0 +1,214 @@ +package io.github.linpeilie; + +import io.github.linpeilie.me.collection.adder.DogException; +import io.github.linpeilie.me.collection.adder._target.AdderUsageObserver; +import io.github.linpeilie.me.collection.adder._target.Target; +import io.github.linpeilie.me.collection.adder._target.Target2; +import io.github.linpeilie.me.collection.adder._target.Target3; +import io.github.linpeilie.me.collection.adder._target.TargetDali; +import io.github.linpeilie.me.collection.adder._target.TargetHuman; +import io.github.linpeilie.me.collection.adder._target.TargetOnlyGetter; +import io.github.linpeilie.me.collection.adder._target.TargetViaTargetType; +import io.github.linpeilie.me.collection.adder._target.TargetWithAnimals; +import io.github.linpeilie.me.collection.adder._target.TargetWithoutSetter; +import io.github.linpeilie.me.collection.adder.source.Foo; +import io.github.linpeilie.me.collection.adder.source.SingleElementSource; +import io.github.linpeilie.me.collection.adder.source.Source; +import io.github.linpeilie.me.collection.adder.source.Source2; +import io.github.linpeilie.me.collection.adder.source.Source3; +import io.github.linpeilie.me.collection.adder.source.SourceTeeth; +import io.github.linpeilie.me.collection.adder.source.SourceWithPets; +import java.util.ArrayList; +import java.util.Arrays; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest(classes = Application.class) +public class AdderTest { + + @Autowired + private Converter converter; + + @Test + public void testAdd() throws DogException { + AdderUsageObserver.setUsed(false); + + Source source = new Source(); + source.setPets(Arrays.asList("mouse")); + + Target target = converter.convert(source, Target.class); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(1); + assertThat(target.getPets().get(0)).isEqualTo(2L); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testAddWithExceptionNotInThrowsClause() throws DogException { + AdderUsageObserver.setUsed(false); + + Source source = new Source(); + source.setPets(Arrays.asList("cat")); + + assertThatThrownBy(() -> converter.convert(source, Target.class)) + .isInstanceOf(RuntimeException.class); + } + + @Test + public void testAddWithExistingTarget() { + AdderUsageObserver.setUsed(false); + + Source source = new Source(); + source.setPets(Arrays.asList("mouse")); + + Target target = new Target(); + target.setPets(new ArrayList<>(Arrays.asList(1L))); + + converter.convert(source, target); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(2); + assertThat(target.getPets().get(0)).isEqualTo(1L); + assertThat(target.getPets().get(1)).isEqualTo(2L); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testShouldUseDefaultStrategy() throws DogException { + AdderUsageObserver.setUsed(false); + + Source3 source = new Source3(); + source.setPets(Arrays.asList("mouse")); + + Target3 target = converter.convert(source, Target3.class); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(1); + assertThat(target.getPets().get(0)).isEqualTo(2L); + assertFalse(AdderUsageObserver.isUsed()); + } + + @Test + public void testShouldPreferSetterStrategyButThereIsNone() throws DogException { + AdderUsageObserver.setUsed(false); + + Source source = new Source(); + source.setPets(Arrays.asList("mouse")); + + TargetWithoutSetter target = converter.convert(source, TargetWithoutSetter.class); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(1); + assertThat(target.getPets().get(0)).isEqualTo(2L); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testShouldPreferHumanSingular() { + + AdderUsageObserver.setUsed(false); + + SourceTeeth source = new SourceTeeth(); + source.setTeeth(Arrays.asList("moler")); + + TargetHuman target = converter.convert(source, TargetHuman.class); + assertThat(target).isNotNull(); + assertThat(target.getTeeth().size()).isEqualTo(1); + assertThat(target.getTeeth().get(0)).isEqualTo(3); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testShouldFallBackToDaliSingularInAbsenceOfHumanSingular() { + AdderUsageObserver.setUsed(false); + + SourceTeeth source = new SourceTeeth(); + source.setTeeth(Arrays.asList("moler")); + + TargetDali target = converter.convert(source, TargetDali.class); + assertThat(target).isNotNull(); + assertThat(target.getTeeth().size()).isEqualTo(1); + assertThat(target.getTeeth().get(0)).isEqualTo(3); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testAddReverse() { + AdderUsageObserver.setUsed(false); + + Target source = new Target(); + source.setPets(Arrays.asList(3L)); + + Source target = converter.convert(source, Source.class); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(1); + assertThat(target.getPets().get(0)).isEqualTo("cat"); + } + + @Test + public void testAddOnlyGetter() throws DogException { + AdderUsageObserver.setUsed(false); + + Source source = new Source(); + source.setPets(Arrays.asList("mouse")); + + TargetOnlyGetter target = converter.convert(source, TargetOnlyGetter.class); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(1); + assertThat(target.getPets().get(0)).isEqualTo(2L); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testAddViaTargetType() { + AdderUsageObserver.setUsed(false); + + Source source = new Source(); + source.setPets(Arrays.asList("mouse")); + + TargetViaTargetType target = converter.convert(source, TargetViaTargetType.class); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(1); + assertThat(target.getPets().get(0)).isNotNull(); + assertThat(target.getPets().get(0).getValue()).isEqualTo(2L); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testSingleElementSource() { + AdderUsageObserver.setUsed(false); + + SingleElementSource source = new SingleElementSource(); + source.setPet("mouse"); + + Target target = converter.convert(source, Target.class); + assertThat(target).isNotNull(); + assertThat(target.getPets().size()).isEqualTo(1); + assertThat(target.getPets().get(0)).isEqualTo(2L); + assertTrue(AdderUsageObserver.isUsed()); + } + + @Test + public void testMissingImport() { + Source2 source = new Source2(); + source.setAttributes(Arrays.asList(new Foo())); + + Target2 target = converter.convert(source, Target2.class); + assertThat(target).isNotNull(); + assertThat(target.getAttributes().size()).isEqualTo(1); + } + + @Test + public void useIterationNameFromSource() { + SourceWithPets source = new SourceWithPets(); + source.setPets(Arrays.asList("dog", "cat")); + + TargetWithAnimals target = converter.convert(source, TargetWithAnimals.class); + + assertThat(target.getAnimals()).containsExactly("dog", "cat"); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/BigNumbersConversionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/BigNumbersConversionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..816059b00d7fde1bfac3d22aa23f6504f7d1f975 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/BigNumbersConversionTest.java @@ -0,0 +1,169 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie; + +import io.github.linpeilie.me.conversion.bignumbers.BigDecimalSource; +import io.github.linpeilie.me.conversion.bignumbers.BigDecimalTarget; +import io.github.linpeilie.me.conversion.bignumbers.BigIntegerSource; +import io.github.linpeilie.me.conversion.bignumbers.BigIntegerTarget; +import java.math.BigDecimal; +import java.math.BigInteger; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class BigNumbersConversionTest { + + @Autowired + private Converter converter; + + @Test + public void shouldApplyBigIntegerConversions() { + BigIntegerSource source = new BigIntegerSource(); + source.setB( new BigInteger( "1" ) ); + source.setBb( new BigInteger( "2" ) ); + source.setS( new BigInteger( "3" ) ); + source.setSs( new BigInteger( "4" ) ); + source.setI( new BigInteger( "5" ) ); + source.setIi( new BigInteger( "6" ) ); + source.setL( new BigInteger( "7" ) ); + source.setLl( new BigInteger( "8" ) ); + source.setF( new BigInteger( "9" ) ); + source.setFf( new BigInteger( "10" ) ); + source.setD( new BigInteger( "11" ) ); + source.setDd( new BigInteger( "12" ) ); + source.setString( new BigInteger( "13" ) ); + + BigIntegerTarget target = converter.convert( source, BigIntegerTarget.class ); + + assertThat( target ).isNotNull(); + assertThat( target.getB() ).isEqualTo( (byte) 1 ); + assertThat( target.getBb() ).isEqualTo( (byte) 2 ); + assertThat( target.getS() ).isEqualTo( (short) 3 ); + assertThat( target.getSs() ).isEqualTo( (short) 4 ); + assertThat( target.getI() ).isEqualTo( 5 ); + assertThat( target.getIi() ).isEqualTo( 6 ); + assertThat( target.getL() ).isEqualTo( 7 ); + assertThat( target.getLl() ).isEqualTo( 8 ); + assertThat( target.getF() ).isEqualTo( 9.0f ); + assertThat( target.getFf() ).isEqualTo( 10.0f ); + assertThat( target.getD() ).isEqualTo( 11.0d ); + assertThat( target.getDd() ).isEqualTo( 12.0d ); + assertThat( target.getString() ).isEqualTo( "13" ); + } + + @Test + public void shouldApplyReverseBigIntegerConversions() { + BigIntegerTarget target = new BigIntegerTarget(); + target.setB( (byte) 1 ); + target.setBb( (byte) 2 ); + target.setS( (short) 3 ); + target.setSs( (short) 4 ); + target.setI( 5 ); + target.setIi( 6 ); + target.setL( 7 ); + target.setLl( 8L ); + target.setF( 9.0f ); + target.setFf( 10.0f ); + target.setD( 11.0d ); + target.setDd( 12.0d ); + target.setString( "13" ); + + BigIntegerSource source = converter.convert( target, BigIntegerSource.class ); + + assertThat( source ).isNotNull(); + assertThat( source.getB() ).isEqualTo( new BigInteger( "1" ) ); + assertThat( source.getBb() ).isEqualTo( new BigInteger( "2" ) ); + assertThat( source.getS() ).isEqualTo( new BigInteger( "3" ) ); + assertThat( source.getSs() ).isEqualTo( new BigInteger( "4" ) ); + assertThat( source.getI() ).isEqualTo( new BigInteger( "5" ) ); + assertThat( source.getIi() ).isEqualTo( new BigInteger( "6" ) ); + assertThat( source.getL() ).isEqualTo( new BigInteger( "7" ) ); + assertThat( source.getLl() ).isEqualTo( new BigInteger( "8" ) ); + assertThat( source.getF() ).isEqualTo( new BigInteger( "9" ) ); + assertThat( source.getFf() ).isEqualTo( new BigInteger( "10" ) ); + assertThat( source.getD() ).isEqualTo( new BigInteger( "11" ) ); + assertThat( source.getDd() ).isEqualTo( new BigInteger( "12" ) ); + assertThat( source.getString() ).isEqualTo( new BigInteger( "13" ) ); + } + + @Test + public void shouldApplyBigDecimalConversions() { + BigDecimalSource source = new BigDecimalSource(); + source.setB( new BigDecimal( "1.45" ) ); + source.setBb( new BigDecimal( "2.45" ) ); + source.setS( new BigDecimal( "3.45" ) ); + source.setSs( new BigDecimal( "4.45" ) ); + source.setI( new BigDecimal( "5.45" ) ); + source.setIi( new BigDecimal( "6.45" ) ); + source.setL( new BigDecimal( "7.45" ) ); + source.setLl( new BigDecimal( "8.45" ) ); + source.setF( new BigDecimal( "9.45" ) ); + source.setFf( new BigDecimal( "10.45" ) ); + source.setD( new BigDecimal( "11.45" ) ); + source.setDd( new BigDecimal( "12.45" ) ); + source.setString( new BigDecimal( "13.45" ) ); + source.setBigInteger( new BigDecimal( "14.45" ) ); + + BigDecimalTarget target = converter.convert( source, BigDecimalTarget.class ); + + assertThat( target ).isNotNull(); + assertThat( target.getB() ).isEqualTo( (byte) 1 ); + assertThat( target.getBb() ).isEqualTo( (byte) 2 ); + assertThat( target.getS() ).isEqualTo( (short) 3 ); + assertThat( target.getSs() ).isEqualTo( (short) 4 ); + assertThat( target.getI() ).isEqualTo( 5 ); + assertThat( target.getIi() ).isEqualTo( 6 ); + assertThat( target.getL() ).isEqualTo( 7 ); + assertThat( target.getLl() ).isEqualTo( 8 ); + assertThat( target.getF() ).isEqualTo( 9.45f ); + assertThat( target.getFf() ).isEqualTo( 10.45f ); + assertThat( target.getD() ).isEqualTo( 11.45d ); + assertThat( target.getDd() ).isEqualTo( 12.45d ); + assertThat( target.getString() ).isEqualTo( "13.45" ); + assertThat( target.getBigInteger() ).isEqualTo( new BigInteger( "14" ) ); + } + + @Test + public void shouldApplyReverseBigDecimalConversions() { + BigDecimalTarget target = new BigDecimalTarget(); + target.setB( (byte) 1 ); + target.setBb( (byte) 2 ); + target.setS( (short) 3 ); + target.setSs( (short) 4 ); + target.setI( 5 ); + target.setIi( 6 ); + target.setL( 7 ); + target.setLl( 8L ); + target.setF( 9.0f ); + target.setFf( 10.0f ); + target.setD( 11.0d ); + target.setDd( 12.0d ); + target.setString( "13.45" ); + target.setBigInteger( new BigInteger( "14" ) ); + + BigDecimalSource source = converter.convert( target, BigDecimalSource.class ); + + assertThat( source ).isNotNull(); + assertThat( source.getB() ).isEqualTo( new BigDecimal( "1" ) ); + assertThat( source.getBb() ).isEqualTo( new BigDecimal( "2" ) ); + assertThat( source.getS() ).isEqualTo( new BigDecimal( "3" ) ); + assertThat( source.getSs() ).isEqualTo( new BigDecimal( "4" ) ); + assertThat( source.getI() ).isEqualTo( new BigDecimal( "5" ) ); + assertThat( source.getIi() ).isEqualTo( new BigDecimal( "6" ) ); + assertThat( source.getL() ).isEqualTo( new BigDecimal( "7" ) ); + assertThat( source.getLl() ).isEqualTo( new BigDecimal( "8" ) ); + assertThat( source.getF() ).isEqualTo( new BigDecimal( "9.0" ) ); + assertThat( source.getFf() ).isEqualTo( new BigDecimal( "10.0" ) ); + assertThat( source.getD() ).isEqualTo( new BigDecimal( "11.0" ) ); + assertThat( source.getDd() ).isEqualTo( new BigDecimal( "12.0" ) ); + assertThat( source.getString() ).isEqualTo( new BigDecimal( "13.45" ) ); + assertThat( source.getBigInteger() ).isEqualTo( new BigDecimal( "14" ) ); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CallbackMethodTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CallbackMethodTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fec987e9c5adc5b21d864bed9fb290a8bafb9fb7 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CallbackMethodTest.java @@ -0,0 +1,100 @@ +package io.github.linpeilie; + +import io.github.linpeilie.me.callbacks.ClassContainingCallbacks; +import io.github.linpeilie.me.callbacks.Invocation; +import io.github.linpeilie.me.callbacks.Source; +import io.github.linpeilie.me.callbacks.Target; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class CallbackMethodTest { + + @Autowired + private Converter converter; + + @BeforeEach + public void reset() { + ClassContainingCallbacks.reset(); + io.github.linpeilie.me.callbacks.BaseMapper.reset(); + } + + @Test + public void callbackMethodsForBeanMappingCalled() { + converter.convert(createSource(), Target.class); + + assertBeanMappingInvocations(ClassContainingCallbacks.getInvocations()); + assertBeanMappingInvocations(io.github.linpeilie.me.callbacks.BaseMapper.getInvocations()); + } + + @Test + public void callbackMethodsForBeanMappingWithResultParamCalled() { + converter.convert(createSource(), createEmptyTarget()); + + assertBeanMappingInvocations(ClassContainingCallbacks.getInvocations()); + assertBeanMappingInvocations(io.github.linpeilie.me.callbacks.BaseMapper.getInvocations()); + } + + private void assertBeanMappingInvocations(List invocations) { + Source source = createSource(); + Target target = createResultTarget(); + Target emptyTarget = createEmptyTarget(); + + assertThat(invocations).isEqualTo(beanMappingInvocationList(source, target, emptyTarget)); + } + + private List beanMappingInvocationList(Object source, Object target, Object emptyTarget) { + List invocations = new ArrayList<>(); + + invocations.addAll(allBeforeMappingMethods(source, emptyTarget, Target.class)); + invocations.addAll(allAfterMappingMethods(source, target, Target.class)); + + return invocations; + } + + private List allAfterMappingMethods(Object source, Object target, Class targetClass) { + return new ArrayList<>(Arrays.asList( + new Invocation("noArgsAfterMapping"), + new Invocation("withSourceAfterMapping", source), + new Invocation("withSourceAsObjectAfterMapping", source), + new Invocation("withSourceAndTargetAfterMapping", source, target), + new Invocation("withTargetAfterMapping", target), + new Invocation("withTargetAsObjectAfterMapping", target), + new Invocation("withTargetAndTargetTypeAfterMapping", target, targetClass))); + } + + private List allBeforeMappingMethods(Object source, Object emptyTarget, Class targetClass) { + return new ArrayList<>(Arrays.asList( + new Invocation("noArgsBeforeMapping"), + new Invocation("withSourceBeforeMapping", source), + new Invocation("withSourceAsObjectBeforeMapping", source), + new Invocation("withSourceAndTargetTypeBeforeMapping", source, targetClass), + new Invocation("withSourceAndTargetBeforeMapping", source, emptyTarget), + new Invocation("withTargetBeforeMapping", emptyTarget), + new Invocation("withTargetAsObjectBeforeMapping", emptyTarget))); + } + + private Source createSource() { + Source source = new Source(); + source.setFoo("foo"); + return source; + } + + private Target createEmptyTarget() { + return new Target(); + } + + private Target createResultTarget() { + Target target = createEmptyTarget(); + target.setFoo("foo"); + return target; + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CarMapperTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CarMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..eff8da7746029e2974750b91a62315dd9d74cccd --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CarMapperTest.java @@ -0,0 +1,283 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.complex._target.CarDto; +import io.github.linpeilie.me.complex._target.PersonDto; +import io.github.linpeilie.me.complex.source.Car; +import io.github.linpeilie.me.complex.source.Category; +import io.github.linpeilie.me.complex.source.Person; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class CarMapperTest { + + @Autowired + private Converter converter; + + @Test + public void shouldMapAttributeByName() { + //given + Car car = new Car( + "Morris", + 2, + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime(), + new Person("Bob"), + new ArrayList<>() + ); + + //when + CarDto carDto = converter.convert(car, CarDto.class); + + //then + assertThat(carDto).isNotNull(); + assertThat(carDto.getMake()).isEqualTo(car.getMake()); + } + + @Test + public void shouldMapReferenceAttribute() { + //given + Car car = new Car( + "Morris", + 2, + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime(), + new Person("Bob"), + new ArrayList<>() + ); + + //when + CarDto carDto = converter.convert(car, CarDto.class); + + //then + assertThat(carDto).isNotNull(); + assertThat(carDto.getDriver()).isNotNull(); + assertThat(carDto.getDriver().getName()).isEqualTo("Bob"); + } + + @Test + public void shouldReverseMapReferenceAttribute() { + //given + CarDto carDto = new CarDto("Morris", 2, "1980", new PersonDto("Bob"), new ArrayList<>()); + + //when + Car car = converter.convert(carDto, Car.class); + + //then + assertThat(car).isNotNull(); + assertThat(car.getDriver()).isNotNull(); + assertThat(car.getDriver().getName()).isEqualTo("Bob"); + } + + @Test + public void shouldMapAttributeWithCustomMapping() { + //given + Car car = new Car( + "Morris", + 2, + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime(), + new Person("Bob"), + new ArrayList<>() + ); + + //when + CarDto carDto = converter.convert(car, CarDto.class); + + //then + assertThat(carDto).isNotNull(); + assertThat(carDto.getSeatCount()).isEqualTo(car.getNumberOfSeats()); + } + + @Test + public void shouldConsiderCustomMappingForReverseMapping() { + //given + CarDto carDto = new CarDto("Morris", 2, "1980", new PersonDto("Bob"), new ArrayList<>()); + + //when + Car car = converter.convert(carDto, Car.class); + + //then + assertThat(car).isNotNull(); + assertThat(car.getNumberOfSeats()).isEqualTo(carDto.getSeatCount()); + } + + @Test + public void shouldApplyConverter() { + //given + Car car = new Car( + "Morris", + 2, + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime(), + new Person("Bob"), + new ArrayList<>() + ); + + //when + CarDto carDto = converter.convert(car, CarDto.class); + + //then + assertThat(carDto).isNotNull(); + assertThat(carDto.getManufacturingYear()).isEqualTo("1980"); + } + + @Test + public void shouldApplyConverterForReverseMapping() { + //given + CarDto carDto = new CarDto("Morris", 2, "1980", new PersonDto("Bob"), new ArrayList<>()); + + //when + Car car = converter.convert(carDto, Car.class); + + //then + assertThat(car).isNotNull(); + assertThat(car.getManufacturingDate()).isEqualTo( + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime() + ); + } + + @Test + public void shouldMapIterable() { + //given + Car car1 = new Car( + "Morris", + 2, + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime(), + new Person("Bob"), + new ArrayList<>() + ); + Car car2 = new Car( + "Railton", + 4, + new GregorianCalendar(1934, Calendar.JANUARY, 1).getTime(), + new Person("Bill"), + new ArrayList<>() + ); + + //when + List dtos = converter.convert(Arrays.asList(car1, car2), CarDto.class); + + //then + assertThat(dtos).isNotNull(); + assertThat(dtos).hasSize(2); + + assertThat(dtos.get(0).getMake()).isEqualTo("Morris"); + assertThat(dtos.get(0).getSeatCount()).isEqualTo(2); + assertThat(dtos.get(0).getManufacturingYear()).isEqualTo("1980"); + assertThat(dtos.get(0).getDriver().getName()).isEqualTo("Bob"); + + assertThat(dtos.get(1).getMake()).isEqualTo("Railton"); + assertThat(dtos.get(1).getSeatCount()).isEqualTo(4); + assertThat(dtos.get(1).getManufacturingYear()).isEqualTo("1934"); + assertThat(dtos.get(1).getDriver().getName()).isEqualTo("Bill"); + } + + @Test + public void shouldReverseMapIterable() { + //given + CarDto car1 = new CarDto("Morris", 2, "1980", new PersonDto("Bob"), new ArrayList<>()); + CarDto car2 = new CarDto("Railton", 4, "1934", new PersonDto("Bill"), new ArrayList<>()); + + //when + List cars = converter.convert(Arrays.asList(car1, car2), Car.class); + + //then + assertThat(cars).isNotNull(); + assertThat(cars).hasSize(2); + + assertThat(cars.get(0).getMake()).isEqualTo("Morris"); + assertThat(cars.get(0).getNumberOfSeats()).isEqualTo(2); + assertThat(cars.get(0).getManufacturingDate()).isEqualTo( + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime() + ); + assertThat(cars.get(0).getDriver().getName()).isEqualTo("Bob"); + + assertThat(cars.get(1).getMake()).isEqualTo("Railton"); + assertThat(cars.get(1).getNumberOfSeats()).isEqualTo(4); + assertThat(cars.get(1).getManufacturingDate()).isEqualTo( + new GregorianCalendar(1934, Calendar.JANUARY, 1).getTime() + ); + assertThat(cars.get(1).getDriver().getName()).isEqualTo("Bill"); + } + + @Test + public void shouldMapIterableAttribute() { + //given + Car car = new Car( + "Morris", + 2, + new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime(), + new Person("Bob"), + Arrays.asList(new Person("Alice"), new Person("Bill")) + ); + + //when + CarDto dto = converter.convert(car, CarDto.class); + + //then + assertThat(dto).isNotNull(); + + assertThat(dto.getPassengers()).hasSize(2); + assertThat(dto.getPassengers().get(0).getName()).isEqualTo("Alice"); + assertThat(dto.getPassengers().get(1).getName()).isEqualTo("Bill"); + } + + @Test + public void shouldReverseMapIterableAttribute() { + //given + CarDto carDto = new CarDto( + "Morris", + 2, + "1980", + new PersonDto("Bob"), + Arrays.asList(new PersonDto("Alice"), new PersonDto("Bill")) + ); + + //when + Car car = converter.convert(carDto, Car.class); + + //then + assertThat(car).isNotNull(); + + assertThat(car.getPassengers()).hasSize(2); + assertThat(car.getPassengers().get(0).getName()).isEqualTo("Alice"); + assertThat(car.getPassengers().get(1).getName()).isEqualTo("Bill"); + } + + @Test + public void shouldMapEnumToString() { + //given + Car car = new Car(); + car.setCategory(Category.CONVERTIBLE); + //when + CarDto carDto = converter.convert(car, CarDto.class); + + //then + assertThat(carDto).isNotNull(); + assertThat(carDto.getCategory()).isEqualTo("CONVERTIBLE"); + } + + @Test + public void shouldMapStringToEnum() { + //given + CarDto carDto = new CarDto(); + carDto.setCategory("CONVERTIBLE"); + //when + Car car = converter.convert(carDto, Car.class); + + //then + assertThat(car).isNotNull(); + assertThat(car.getCategory()).isEqualTo(Category.CONVERTIBLE); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CollectionMapping1Test.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CollectionMapping1Test.java new file mode 100644 index 0000000000000000000000000000000000000000..453deedc3f723371750cb262f433f8938dfab1b3 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CollectionMapping1Test.java @@ -0,0 +1,402 @@ +package io.github.linpeilie; + +import io.github.linpeilie.me.collection.Colour; +import io.github.linpeilie.me.collection.Source; +import io.github.linpeilie.me.collection.StringHolder; +import io.github.linpeilie.me.collection.StringHolderArrayList; +import io.github.linpeilie.me.collection.StringHolderToLongMap; +import io.github.linpeilie.me.collection.Target; +import io.github.linpeilie.me.collection.TestList; +import io.github.linpeilie.me.collection.TestMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; + +@SpringBootTest(classes = Application.class) +public class CollectionMapping1Test { + + @Autowired + private Converter converter; + + @Test + public void shouldMapNullList() { + Source source = new Source(); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getStringList()).isNull(); + } + + @Test + public void shouldReverseMapNullList() { + Target target = new Target(); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getStringList()).isNull(); + } + + @Test + public void shouldMapList() { + Source source = new Source(); + source.setStringList(Arrays.asList("Bob", "Alice")); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getStringList()).containsExactly("Bob", "Alice"); + } + + @Test + public void shouldMapListWithoutSetter() { + Source source = new Source(); + source.setStringList2(Arrays.asList("Bob", "Alice")); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getStringListNoSetter()).containsExactly("Bob", "Alice"); + } + + @Test + public void shouldReverseMapList() { + Target target = new Target(); + target.setStringList(Arrays.asList("Bob", "Alice")); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getStringList()).containsExactly("Bob", "Alice"); + } + + @Test + public void shouldMapListAsCopy() { + Source source = new Source(); + source.setStringList(Arrays.asList("Bob", "Alice")); + + Target target = converter.convert(source, Target.class); + target.getStringList().add("Bill"); + + assertThat(source.getStringList()).containsExactly("Bob", "Alice"); + assertThat(source.getStringList()).isNotEqualTo(target.getStringList()); + } + + @Test + public void shouldMapListWithClearAndAddAll() { + Source source = new Source(); + source.setOtherStringList(Arrays.asList("Bob", "Alice")); + + Target target = converter.convert(source, Target.class); + target.getOtherStringList().add("Bill"); + + assertThat(source.getOtherStringList()).containsExactly("Bob", "Alice"); + + // prepare a test list to monitor add all behaviour + List testList = new TestList<>(); + testList.addAll(target.getOtherStringList()); + TestList.setAddAllCalled(false); + target.setOtherStringList(testList); + + // prepare new source + source.setOtherStringList(Arrays.asList("Bob")); + List originalInstance = target.getOtherStringList(); + + converter.convert(source, target); + + assertThat(target.getOtherStringList()).isSameAs(originalInstance); + assertThat(target.getOtherStringList()).containsExactly("Bob"); + assertThat(TestList.isAddAllCalled()).isTrue(); + TestList.setAddAllCalled(false); + } + + @Test + public void shouldReverseMapListAsCopy() { + Target target = new Target(); + target.setStringList(Arrays.asList("Bob", "Alice")); + + Source source = converter.convert(target, Source.class); + source.getStringList().add("Bill"); + + assertThat(target.getStringList()).containsExactly("Bob", "Alice"); + } + + @Test + public void shouldMapArrayList() { + Source source = new Source(); + source.setStringArrayList(new ArrayList<>(Arrays.asList("Bob", "Alice"))); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getStringArrayList()).containsExactly("Bob", "Alice"); + } + + @Test + public void shouldReverseMapArrayList() { + Target target = new Target(); + target.setStringArrayList(new ArrayList<>(Arrays.asList("Bob", "Alice"))); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getStringArrayList()).containsExactly("Bob", "Alice"); + } + + @Test + public void shouldMapSet() { + Source source = new Source(); + source.setStringSet(new HashSet<>(Arrays.asList("Bob", "Alice"))); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getStringSet()).contains("Bob", "Alice"); + } + + @Test + public void shouldReverseMapSet() { + Target target = new Target(); + target.setStringSet(new HashSet<>(Arrays.asList("Bob", "Alice"))); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getStringSet()).contains("Bob", "Alice"); + } + + @Test + public void shouldMapSetAsCopy() { + Source source = new Source(); + source.setStringSet(new HashSet<>(Arrays.asList("Bob", "Alice"))); + + Target target = converter.convert(source, Target.class); + target.getStringSet().add("Bill"); + + assertThat(source.getStringSet()).containsOnly("Bob", "Alice"); + } + + @Test + public void shouldMapHashSetAsCopy() { + Source source = new Source(); + source.setStringHashSet(new HashSet<>(Arrays.asList("Bob", "Alice"))); + + Target target = converter.convert(source, Target.class); + target.getStringHashSet().add("Bill"); + + assertThat(source.getStringHashSet()).containsOnly("Bob", "Alice"); + } + + @Test + public void shouldReverseMapSetAsCopy() { + Target target = new Target(); + target.setStringSet(new HashSet<>(Arrays.asList("Bob", "Alice"))); + + Source source = converter.convert(target, Source.class); + source.getStringSet().add("Bill"); + + assertThat(target.getStringSet()).containsOnly("Bob", "Alice"); + } + + @Test + public void shouldMapListToCollection() { + Source source = new Source(); + source.setIntegerList(Arrays.asList(1, 2)); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getIntegerCollection()).containsOnly(1, 2); + } + + @Test + public void shouldReverseMapListToCollection() { + Target target = new Target(); + target.setIntegerCollection(Arrays.asList(1, 2)); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getIntegerList()).containsOnly(1, 2); + } + + @Test + public void shouldMapIntegerSetToRawSet() { + Source source = new Source(); + source.setIntegerSet(new HashSet<>(Arrays.asList(1, 2))); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getSet()).containsOnly(1, 2); + } + + @Test + public void shouldMapIntegerSetToStringSet() { + Source source = new Source(); + source.setAnotherIntegerSet(new HashSet<>(Arrays.asList(1, 2))); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getAnotherStringSet()).containsOnly("1", "2"); + } + + @Test + public void shouldReverseMapIntegerSetToStringSet() { + Target target = new Target(); + target.setAnotherStringSet(new HashSet<>(Arrays.asList("1", "2"))); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getAnotherIntegerSet()).containsOnly(1, 2); + } + + @Test + public void shouldMapSetOfEnumToStringSet() { + Source source = new Source(); + source.setColours(EnumSet.of(Colour.BLUE, Colour.GREEN)); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getColours()).containsOnly("BLUE", "GREEN"); + } + + @Test + public void shouldReverseMapSetOfEnumToStringSet() { + Target target = new Target(); + target.setColours(new HashSet<>(Arrays.asList("BLUE", "GREEN"))); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getColours()).containsOnly(Colour.GREEN, Colour.BLUE); + } + + @Test + public void shouldMapMapAsCopy() { + Source source = new Source(); + + Map map = new HashMap<>(); + map.put("Bob", 123L); + map.put("Alice", 456L); + source.setStringLongMap(map); + + Target target = converter.convert(source, Target.class); + target.getStringLongMap().put("Bill", 789L); + + assertThat(source.getStringLongMap()).hasSize(2); + assertThat(target.getStringLongMap()).hasSize(3); + } + + @Test + public void shouldMapMapWithClearAndPutAll() { + Source source = new Source(); + + Map map = new HashMap<>(); + map.put("Bob", 123L); + map.put("Alice", 456L); + source.setOtherStringLongMap(map); + + Target target = converter.convert(source, Target.class); + target.getOtherStringLongMap().put("Bill", 789L); + + assertThat(source.getOtherStringLongMap()).hasSize(2); + assertThat(target.getOtherStringLongMap()).hasSize(3); + + source.getOtherStringLongMap().remove("Alice"); + + // prepare a test list to monitor add all behaviour + Map originalInstance = new TestMap<>(); + originalInstance.putAll(target.getOtherStringLongMap()); + TestMap.setPuttAllCalled(false); + target.setOtherStringLongMap(originalInstance); + + converter.convert(source, target); + + assertThat(target.getOtherStringLongMap()).isSameAs(originalInstance); + assertThat(target.getOtherStringLongMap()).hasSize(1); + assertThat(TestMap.isPuttAllCalled()).isTrue(); + TestMap.setPuttAllCalled(false); + } + + @Test + public void shouldEnumSetAsCopy() { + Source source = new Source(); + source.setEnumSet(EnumSet.of(Colour.BLUE, Colour.GREEN)); + + Target target = converter.convert(source, Target.class); + source.getEnumSet().add(Colour.RED); + + assertThat(source.getEnumSet()).containsOnly(Colour.BLUE, Colour.GREEN, Colour.RED); + assertThat(target.getEnumSet()).containsOnly(Colour.BLUE, Colour.GREEN); + } + + @Test + public void shouldMapNonGenericList() { + Source source = new Source(); + source.setStringList3(new ArrayList<>(Arrays.asList("Bob", "Alice"))); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getNonGenericStringList()).containsExactly( + new StringHolder("Bob"), + new StringHolder("Alice")); + + // Inverse direction + Target newTarget = new Target(); + StringHolderArrayList nonGenericStringList = new StringHolderArrayList(); + nonGenericStringList.addAll(Arrays.asList(new StringHolder("Bill"), new StringHolder("Bob"))); + newTarget.setNonGenericStringList(nonGenericStringList); + + Source mappedSource = converter.convert(newTarget, Source.class); + + assertThat(mappedSource).isNotNull(); + assertThat(mappedSource.getStringList3()).containsExactly("Bill", "Bob"); + } + + @Test + public void shouldMapNonGenericMap() { + Source source = new Source(); + Map map = new HashMap<>(); + map.put("Bob", 123L); + map.put("Alice", 456L); + source.setStringLongMapForNonGeneric(map); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getNonGenericMapStringtoLong()).contains( + entry(new StringHolder("Bob"), 123L), + entry(new StringHolder("Alice"), 456L)); + + // Inverse direction + Target newTarget = new Target(); + StringHolderToLongMap stringToLongMap = new StringHolderToLongMap(); + stringToLongMap.put(new StringHolder("Blue"), 321L); + stringToLongMap.put(new StringHolder("Green"), 654L); + newTarget.setNonGenericMapStringtoLong(stringToLongMap); + + Source mappedSource = converter.convert(newTarget, Source.class); + + assertThat(mappedSource).isNotNull(); + assertThat(mappedSource.getStringLongMapForNonGeneric()).contains( + entry("Blue", 321L), + entry("Green", 654L)); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CollectionMappingTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CollectionMappingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..51c3d018fb00fc1f9568c8e21016892f9c3ca697 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CollectionMappingTest.java @@ -0,0 +1,117 @@ +package io.github.linpeilie; + +import com.google.common.collect.ImmutableMap; +import io.github.linpeilie.me.collection.forged.Source; +import io.github.linpeilie.me.collection.forged.Source1; +import io.github.linpeilie.me.collection.forged.Target; +import io.github.linpeilie.me.collection.forged.Target1; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class CollectionMappingTest { + + @Autowired + private Converter converter; + + @Test + public void shouldForgeNewMapMappingMethod() { + + Map sourceMap = ImmutableMap.builder().put("rabbit", 1L).build(); + Source source = new Source(); + source.setBarMap(sourceMap); + source.publicBarMap = ImmutableMap.builder().put("fox", 2L).build(); + + Target target = converter.convert(source, Target.class); + assertThat(target).isNotNull(); + Map targetMap = ImmutableMap.builder().put("rabbit", "1").build(); + Map targetMap2 = ImmutableMap.builder().put("fox", "2").build(); + assertThat(target.getBarMap()).isEqualTo(targetMap); + assertThat(target.getPublicBarMap()).isEqualTo(targetMap2); + + Source source2 = converter.convert(target, Source.class); + assertThat(source2).isNotNull(); + assertThat(source2.getBarMap()).isEqualTo(sourceMap); + assertThat(source2.publicBarMap).isEqualTo(source.publicBarMap); + } + + @Test + public void shouldForgeNewIterableMappingMethodReturnNullOnNullSource() { + + Source source = new Source(); + source.setFooSet(null); + source.publicFooSet = null; + + Target target = converter.convert(source, Target.class); + assertThat(target).isNotNull(); + assertThat(target.getFooSet()).isNull(); + assertThat(target.getPublicFooSet()).isNull(); + + Source source2 = converter.convert(target, Source.class); + assertThat(source2).isNotNull(); + assertThat(source2.getFooSet()).isNull(); + assertThat(source2.publicFooSet).isNull(); + } + + @Test + public void shouldForgeNewMapMappingMethodReturnNullOnNullSource() { + + Source source = new Source(); + source.setBarMap(null); + source.publicBarMap = null; + + Target target = converter.convert(source, Target.class); + assertThat(target).isNotNull(); + assertThat(target.getBarMap()).isNull(); + assertThat(target.getPublicBarMap()).isNull(); + + Source source2 = converter.convert(target, Source.class); + assertThat(source2).isNotNull(); + assertThat(source2.getBarMap()).isNull(); + assertThat(source2.publicBarMap).isNull(); + } + + @Test + public void shouldForgeNewIterableMappingMethodReturnEmptyOnNullSource() { + + Source1 source = new Source1(); + source.setFooSet(null); + source.publicFooSet = null; + + Target1 target = converter.convert(source, Target1.class); + assertThat(target).isNotNull(); + assertThat(target.getFooSet()).isEmpty(); + assertThat(target.getPublicFooSet()).isEmpty(); + + target.setPublicBarMap(null); + + Source1 source2 = converter.convert(target, Source1.class); + assertThat(source2).isNotNull(); + assertThat(source2.getFooSet()).isEmpty(); + assertThat(source2.publicBarMap).isEmpty(); + } + + @Test + public void shouldForgeNewMapMappingMethodReturnEmptyOnNullSource() { + + Source1 source = new Source1(); + source.setBarMap(null); + source.publicBarMap = null; + + Target1 target = converter.convert(source, Target1.class); + assertThat(target).isNotNull(); + assertThat(target.getBarMap()).isEmpty(); + assertThat(target.getPublicBarMap()).isEmpty(); + + target.setPublicBarMap(null); + + Source1 source2 = converter.convert(target, Source1.class); + assertThat(source2).isNotNull(); + assertThat(source2.getBarMap()).isEmpty(); + assertThat(source2.publicBarMap).isEmpty(); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalExpressionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalExpressionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..68e99a1d3f5440b695beac7f31c520d096333c48 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalExpressionTest.java @@ -0,0 +1,92 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.conditional.expression.Employee; +import io.github.linpeilie.me.conditional.expression.EmployeeDto; +import io.github.linpeilie.me.conditional.expression.Order; +import io.github.linpeilie.me.conditional.expression.OrderDTO; +import io.github.linpeilie.me.conditional.expression.Source; +import io.github.linpeilie.me.conditional.expression.Target; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class ConditionalExpressionTest { + + @Autowired + private Converter converter; + + @Test + public void conditionalExpressionInStaticClassMethod() { + EmployeeDto dto = new EmployeeDto(); + dto.setName("Tester"); + dto.setUniqueIdNumber("SSID-001"); + dto.setCountry(null); + + Employee employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isNull(); + + dto.setCountry("UK"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isEqualTo("SSID-001"); + assertThat(employee.getSsid()).isNull(); + + dto.setCountry("US"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isEqualTo("SSID-001"); + + dto.setCountry("CH"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isNull(); + } + + @Test + public void conditionalSimpleExpression() { + Target target = converter.convert(new Source(50), Target.class); + assertThat(target.getValue()).isEqualTo(50); + + target = converter.convert(new Source(101), Target.class); + assertThat(target.getValue()).isEqualTo(0); + } + + @Test + public void conditionalExpressionForSourceToTarget() { + OrderDTO orderDto = new OrderDTO(); + + Order order = converter.convert(orderDto, Order.class); + assertThat(order).isNotNull(); + assertThat(order.getCustomer()).isNull(); + + orderDto = new OrderDTO(); + orderDto.setCustomerName("Tester"); + order = converter.convert(orderDto, Order.class); + + assertThat(order).isNotNull(); + assertThat(order.getCustomer()).isNotNull(); + assertThat(order.getCustomer().getName()).isEqualTo("Tester"); + assertThat(order.getCustomer().getAddress()).isNull(); + + orderDto = new OrderDTO(); + orderDto.setLine1("Line 1"); + order = converter.convert(orderDto, Order.class); + + assertThat(order).isNotNull(); + assertThat(order.getCustomer()).isNotNull(); + assertThat(order.getCustomer().getName()).isNull(); + assertThat(order.getCustomer().getAddress()).isNotNull(); + assertThat(order.getCustomer().getAddress().getLine1()).isEqualTo("Line 1"); + assertThat(order.getCustomer().getAddress().getLine2()).isNull(); + + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalMappingTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalMappingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d32c1042fd569315ed44f18f4ed4a2e2d5c2e778 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalMappingTest.java @@ -0,0 +1,112 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.conditional.basic.Author; +import io.github.linpeilie.me.conditional.basic.AuthorDto; +import io.github.linpeilie.me.conditional.basic.BasicEmployee; +import io.github.linpeilie.me.conditional.basic.BasicEmployee1; +import io.github.linpeilie.me.conditional.basic.BasicEmployee2; +import io.github.linpeilie.me.conditional.basic.BasicEmployee3; +import io.github.linpeilie.me.conditional.basic.BasicEmployeeDto; +import io.github.linpeilie.me.conditional.basic.Book; +import io.github.linpeilie.me.conditional.basic.BookDto; +import io.github.linpeilie.me.conditional.basic.EmployeeDto; +import java.util.Arrays; +import java.util.Collections; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Filip Hrisafov + */ +@SpringBootTest(classes = Application.class) +public class ConditionalMappingTest { + + @Autowired + private Converter converter; + + @Test + public void conditionalMethodInMapper() { + BasicEmployee employee = converter.convert(new BasicEmployeeDto("Tester"), BasicEmployee.class); + assertThat(employee.getName()).isEqualTo("Tester"); + + employee = converter.convert(new BasicEmployeeDto(""), BasicEmployee.class); + assertThat(employee.getName()).isNull(); + + employee = converter.convert(new BasicEmployeeDto(" "), BasicEmployee.class); + assertThat(employee.getName()).isNull(); + } + + @Test + public void conditionalMethodAndBeanPresenceCheckMapper() { + BasicEmployee employee = converter.convert(new EmployeeDto("Tester"), BasicEmployee.class); + assertThat(employee.getName()).isEqualTo("Tester"); + + employee = converter.convert(new EmployeeDto(""), BasicEmployee.class); + assertThat(employee.getName()).isNull(); + + employee = converter.convert(new EmployeeDto(" "), BasicEmployee.class); + assertThat(employee.getName()).isNull(); + } + + @Test + public void conditionalMethodWithSourceParameter() { + BasicEmployee3 employee = converter.convert(new BasicEmployeeDto("Tester"), BasicEmployee3.class); + assertThat(employee.getName()).isNull(); + + employee = converter.convert(new BasicEmployeeDto("Tester", "map"), BasicEmployee3.class); + assertThat(employee.getName()).isEqualTo("Tester"); + } + + @Test + public void conditionalMethodWithSourceParameterAndValue() { + BasicEmployee2 employee = converter.convert(new BasicEmployeeDto(" ", "empty"), BasicEmployee2.class); + assertThat(employee.getName()).isEqualTo(" "); + + employee = converter.convert(new BasicEmployeeDto(" ", "blank"), BasicEmployee2.class); + assertThat(employee.getName()).isNull(); + + employee = converter.convert(new BasicEmployeeDto("Tester", "blank"), BasicEmployee2.class); + assertThat(employee.getName()).isEqualTo("Tester"); + } + + @Test + public void conditionalMethodForCollection() { + Author author = new Author(); + AuthorDto dto = converter.convert(author, AuthorDto.class); + + assertThat(dto.getBooks()).isNull(); + + author.setBooks(Collections.emptyList()); + dto = converter.convert(author, AuthorDto.class); + + assertThat(dto.getBooks()).isNull(); + + author.setBooks(Arrays.asList( + new Book("Test"), + new Book("Test Vol. 2") + )); + dto = converter.convert(author, AuthorDto.class); + + assertThat(dto.getBooks()) + .extracting(BookDto::getName) + .containsExactly("Test", "Test Vol. 2"); + } + + @Test + public void conditionalMethodWithMappingTarget() { + BasicEmployee1 targetEmployee = new BasicEmployee1(); + targetEmployee.setName("CurrentName"); + converter.convert(new BasicEmployeeDto("ReplacementName"), targetEmployee); + + assertThat(targetEmployee.getName()).isEqualTo("CurrentName"); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalQualifierTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalQualifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1134577a7ffb92ba50bc47ae4d9e66703719b061 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ConditionalQualifierTest.java @@ -0,0 +1,108 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.conditional.qualifier.Employee; +import io.github.linpeilie.me.conditional.qualifier.EmployeeDto; +import io.github.linpeilie.me.conditional.qualifier.Order; +import io.github.linpeilie.me.conditional.qualifier.OrderDTO; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class ConditionalQualifierTest { + + @Autowired + private Converter converter; + + @Test + public void conditionalMethodWithSourceParameter() { + EmployeeDto dto = new EmployeeDto(); + dto.setName("Tester"); + dto.setUniqueIdNumber("SSID-001"); + dto.setCountry(null); + + Employee employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isNull(); + + dto.setCountry("UK"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isEqualTo("SSID-001"); + assertThat(employee.getSsid()).isNull(); + + dto.setCountry("US"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isEqualTo("SSID-001"); + + dto.setCountry("CH"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isNull(); + } + + @Test + public void conditionalClassQualifiers() { + EmployeeDto dto = new EmployeeDto(); + dto.setName("Tester"); + dto.setUniqueIdNumber("SSID-001"); + dto.setCountry(null); + + Employee employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isNull(); + + dto.setCountry("UK"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isEqualTo("SSID-001"); + assertThat(employee.getSsid()).isNull(); + + dto.setCountry("US"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isEqualTo("SSID-001"); + + dto.setCountry("CH"); + employee = converter.convert(dto, Employee.class); + assertThat(employee.getNin()).isNull(); + assertThat(employee.getSsid()).isNull(); + } + + @Test + public void conditionalQualifiersForSourceToTarget() { + OrderDTO orderDto = new OrderDTO(); + + Order order = converter.convert(orderDto, Order.class); + assertThat(order).isNotNull(); + assertThat(order.getCustomer()).isNull(); + + orderDto = new OrderDTO(); + orderDto.setCustomerName("Tester"); + order = converter.convert(orderDto, Order.class); + + assertThat(order).isNotNull(); + assertThat(order.getCustomer()).isNotNull(); + assertThat(order.getCustomer().getName()).isEqualTo("Tester"); + assertThat(order.getCustomer().getAddress()).isNull(); + + orderDto = new OrderDTO(); + orderDto.setLine1("Line 1"); + order = converter.convert(orderDto, Order.class); + + assertThat(order).isNotNull(); + assertThat(order.getCustomer()).isNotNull(); + assertThat(order.getCustomer().getName()).isNull(); + assertThat(order.getCustomer().getAddress()).isNotNull(); + assertThat(order.getCustomer().getAddress().getLine1()).isEqualTo("Line 1"); + assertThat(order.getCustomer().getAddress().getLine2()).isNull(); + + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CurrencyConversionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CurrencyConversionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3bfec65affc921168a7128ccd7a1bd7821787329 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/CurrencyConversionTest.java @@ -0,0 +1,55 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import cn.hutool.core.collection.CollectionUtil; +import io.github.linpeilie.me.conversion.currency.CurrencySource; +import io.github.linpeilie.me.conversion.currency.CurrencyTarget; +import java.util.Currency; +import java.util.HashSet; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class CurrencyConversionTest { + + @Autowired + private Converter converter; + + @Test + public void shouldApplyCurrencyConversions() { + final CurrencySource source = new CurrencySource(); + source.setCurrencyA(Currency.getInstance("USD")); + Set currencies = new HashSet<>(); + currencies.add(Currency.getInstance("EUR")); + currencies.add(Currency.getInstance("CHF")); + source.setUniqueCurrencies(currencies); + + CurrencyTarget target = converter.convert(source, CurrencyTarget.class); + + assertThat(target).isNotNull(); + assertThat(target.getCurrencyA()).isEqualTo("USD"); + assertThat(target.getUniqueCurrencies()).isNotEmpty().containsExactlyInAnyOrder("EUR", "CHF"); + } + + @Test + public void shouldApplyReverseConversions() { + final CurrencyTarget target = new CurrencyTarget(); + target.setCurrencyA("USD"); + target.setUniqueCurrencies(CollectionUtil.newHashSet("JPY")); + + CurrencySource source = converter.convert(target, CurrencySource.class); + + assertThat(source).isNotNull(); + assertThat(source.getCurrencyA().getCurrencyCode()).isEqualTo(Currency.getInstance("USD").getCurrencyCode()); + assertThat(source.getUniqueCurrencies()).containsExactlyInAnyOrder(Currency.getInstance("JPY")); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DateConversionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DateConversionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ae1e360c67728663ebfcf342ce0d7b35fd1d2b49 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DateConversionTest.java @@ -0,0 +1,128 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.conversion.date.Source; +import io.github.linpeilie.me.conversion.date.Target; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.GregorianCalendar; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.EnabledOnJre; +import org.junit.jupiter.api.condition.JRE; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests application of format strings for conversions between strings and dates. + * + * @author Gunnar Morling + */ +@SpringBootTest(classes = Application.class) +public class DateConversionTest { + + @Autowired + private Converter converter; + + @Test + @EnabledOnJre(JRE.JAVA_8) + public void shouldApplyDateFormatForConversions() { + Source source = new Source(); + source.setDate(new GregorianCalendar(2013, Calendar.JULY, 6).getTime()); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getDate()).isEqualTo("06.07.2013"); + } + + @Test + @EnabledForJreRange(min = JRE.JAVA_11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ + public void shouldApplyDateFormatForConversionsJdk11() { + Source source = new Source(); + source.setDate(new GregorianCalendar(2013, Calendar.JULY, 6).getTime()); + source.setAnotherDate(new GregorianCalendar(2013, Calendar.FEBRUARY, 14).getTime()); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getDate()).isEqualTo("06.07.2013"); + assertThat(target.getAnotherDate()).isEqualTo("14.02.13, 00:00"); + } + + @Test + @EnabledOnJre(JRE.JAVA_8) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ + public void shouldApplyDateFormatForConversionInReverseMapping() { + Target target = new Target(); + target.setDate("06.07.2013"); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getDate()).isEqualTo(new GregorianCalendar(2013, Calendar.JULY, 6).getTime()); + } + + @Test + @EnabledForJreRange(min = JRE.JAVA_11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ + public void shouldApplyDateFormatForConversionInReverseMappingJdk11() { + Target target = new Target(); + target.setDate("06.07.2013"); + target.setAnotherDate("14.02.13, 8:30"); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getDate()).isEqualTo(new GregorianCalendar(2013, Calendar.JULY, 6).getTime()); + assertThat(source.getAnotherDate()).isEqualTo( + new GregorianCalendar(2013, Calendar.FEBRUARY, 14, 8, 30).getTime()); + } + + @Test + public void shouldApplyDateToSqlConversion() { + GregorianCalendar time = new GregorianCalendar(2016, Calendar.AUGUST, 24, 20, 30, 30); + GregorianCalendar sqlDate = new GregorianCalendar(2016, Calendar.AUGUST, 23, 21, 35, 35); + GregorianCalendar timestamp = new GregorianCalendar(2016, Calendar.AUGUST, 22, 21, 35, 35); + Source source = new Source(); + source.setTime(time.getTime()); + source.setSqlDate(sqlDate.getTime()); + source.setTimestamp(timestamp.getTime()); + + Target target = converter.convert(source, Target.class); + Time expectedTime = new Time(time.getTime().getTime()); + java.sql.Date expectedSqlDate = new java.sql.Date(sqlDate.getTime().getTime()); + Timestamp expectedTimestamp = new Timestamp(timestamp.getTime().getTime()); + + assertThat(target.getTime()).isEqualTo(expectedTime); + assertThat(target.getSqlDate()).isEqualTo(expectedSqlDate); + assertThat(target.getTimestamp()).isEqualTo(expectedTimestamp); + } + + @Test + public void shouldApplySqlToDateConversion() { + Target target = new Target(); + GregorianCalendar time = new GregorianCalendar(2016, Calendar.AUGUST, 24, 20, 30, 30); + GregorianCalendar sqlDate = new GregorianCalendar(2016, Calendar.AUGUST, 23, 21, 35, 35); + GregorianCalendar timestamp = new GregorianCalendar(2016, Calendar.AUGUST, 22, 21, 35, 35); + target.setTime(new Time(time.getTime().getTime())); + target.setSqlDate(new java.sql.Date(sqlDate.getTime().getTime())); + target.setTimestamp(new Timestamp(timestamp.getTime().getTime())); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getTime()).isEqualTo(target.getTime()); + assertThat(source.getSqlDate()).isEqualTo(target.getSqlDate()); + assertThat(source.getTimestamp()).isEqualTo(target.getTimestamp()); + } +} \ No newline at end of file diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DefaultCollectionImplementationTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DefaultCollectionImplementationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8228cb8dcd4c1f85a8e7c90eaf4ce12bd19ffc09 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DefaultCollectionImplementationTest.java @@ -0,0 +1,50 @@ +package io.github.linpeilie; + +import io.github.linpeilie.me.collection.defaultimplementation.Source; +import io.github.linpeilie.me.collection.defaultimplementation.SourceFoo; +import io.github.linpeilie.me.collection.defaultimplementation.Target; +import io.github.linpeilie.me.collection.defaultimplementation.TargetFoo; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; + +@SpringBootTest(classes = Application.class) +public class DefaultCollectionImplementationTest { + + @Autowired + private Converter converter; + + @Test + public void shouldUseDefaultImplementationForList() { + List target = converter.convert(createSourceFooList(), TargetFoo.class); + + assertResultList(target); + } + + @Test + public void shouldUseDefaultImplementationForListWithoutSetter() { + Source source = new Source(); + source.setFooList(createSourceFooList()); + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getFooListNoSetter()).containsExactly(new TargetFoo("Bob"), new TargetFoo("Alice")); + } + + private void assertResultList(Iterable fooIterable) { + assertThat(fooIterable).isNotNull(); + assertThat(fooIterable).containsOnly(new TargetFoo("Bob"), new TargetFoo("Alice")); + } + + private List createSourceFooList() { + return Arrays.asList(new SourceFoo("Bob"), new SourceFoo("Alice")); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DefaultValueTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DefaultValueTest.java new file mode 100644 index 0000000000000000000000000000000000000000..94d5ecd14c53f8936731516c9700a9375a4eb1a0 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/DefaultValueTest.java @@ -0,0 +1,81 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.defaultvalue.CountryDts; +import io.github.linpeilie.me.defaultvalue.CountryEntity; +import io.github.linpeilie.me.defaultvalue.Region; +import io.github.linpeilie.me.defaultvalue.other.Continent; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class DefaultValueTest { + @Autowired + private Converter converter; + + @Test + /** + * Checks: + *
    + *
  • On code: Using defaultValue without type conversion
  • + *
  • On id: Type conversion of the defaultValue (string expr to int)
  • + *
  • On name: Using ConstantExpression instead of defaultValue
  • + *
  • On zipcode: Ignoring defaultValue on primitive target types
  • + *
  • On region: Using defaultValue before the assignment by an intern method (mapToString)
  • + *
+ */ + public void shouldDefaultValueAndUseConstantExpression() { + CountryEntity countryEntity = new CountryEntity(); + + CountryDts countryDts = converter.convert(countryEntity, CountryDts.class); + + // id is null so it should fall back to the default value + assertThat(countryDts.getId()).isEqualTo(42); + + // code is null so it should fall back to the default value + assertThat(countryDts.getCode()).isEqualTo("DE"); + assertThat(countryDts.getZipcode()).isEqualTo(0); + assertThat(countryDts.getRegion()).isEqualTo("someRegion"); + assertThat(countryDts.getContinent()).isEqualTo(Continent.EUROPE); + } + + @Test + public void shouldIgnoreDefaultValue() { + CountryEntity countryEntity = new CountryEntity(); + countryEntity.setCode("US"); + Region region = new Region(); + region.setCode("foobar"); + countryEntity.setRegion(region); + countryEntity.setContinent(Continent.NORTH_AMERICA); + + CountryDts countryDts = converter.convert(countryEntity, CountryDts.class); + + // the source entity had a code set, so the default value shouldn't be used + assertThat(countryDts.getCode()).isEqualTo("US"); + assertThat(countryDts.getRegion()).isEqualTo("foobar"); + assertThat(countryDts.getContinent()).isEqualTo(Continent.NORTH_AMERICA); + } + + @Test + public void shouldHandleUpdateMethodsFromDtsToEntity() { + CountryEntity countryEntity = new CountryEntity(); + CountryDts countryDts = new CountryDts(); + + converter.convert(countryDts, countryEntity); + + assertThat(countryEntity.getId()).isEqualTo(0); + // no code is set, so fall back to default value + assertThat(countryEntity.getCode()).isEqualTo("DE"); + assertThat(countryEntity.getZipcode()).isEqualTo(0); + assertThat(countryEntity.getContinent()).isEqualTo(Continent.EUROPE); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ImmutableProductTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ImmutableProductTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8b5374e89abc2c04b122db26a63283b7807c3a05 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/ImmutableProductTest.java @@ -0,0 +1,42 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.collection.immutabletarget.CupboardDto; +import io.github.linpeilie.me.collection.immutabletarget.CupboardEntity; +import java.util.Arrays; +import java.util.Collections; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sjaak Derksen + */ +@SpringBootTest(classes = Application.class) +public class ImmutableProductTest { + + @Autowired + private Converter converter; + + @Test + public void shouldHandleImmutableTarget() { + + CupboardDto in = new CupboardDto(); + in.setContent(Arrays.asList("cups", "soucers")); + CupboardEntity out = new CupboardEntity(); + out.setContent(Collections.emptyList()); + + converter.convert(in, out); + + assertThat(out.getContent()).isNotNull(); + assertThat(out.getContent()).containsExactly("cups", "soucers"); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/IterableToNonIterableMappingTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/IterableToNonIterableMappingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0fef9fec5ff5b5c23136389591bb33be364bfdf4 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/IterableToNonIterableMappingTest.java @@ -0,0 +1,72 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.collection.iterabletononiterable.Fruit; +import io.github.linpeilie.me.collection.iterabletononiterable.FruitSalad; +import io.github.linpeilie.me.collection.iterabletononiterable.FruitsMenu; +import io.github.linpeilie.me.collection.iterabletononiterable.Source; +import io.github.linpeilie.me.collection.iterabletononiterable.Target; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class IterableToNonIterableMappingTest { + + @Autowired + private Converter converter; + + @Test + public void shouldMapStringListToStringUsingCustomMapper() { + Source source = new Source(); + source.setNames(Arrays.asList("Alice", "Bob", "Jim")); + source.publicNames = Arrays.asList("Alice", "Bob", "Jim"); + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getNames()).isEqualTo("Alice-Bob-Jim"); + assertThat(target.publicNames).isEqualTo("Alice-Bob-Jim"); + } + + @Test + public void shouldReverseMapStringListToStringUsingCustomMapper() { + Target target = new Target(); + target.setNames("Alice-Bob-Jim"); + target.publicNames = "Alice-Bob-Jim"; + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getNames()).isEqualTo(Arrays.asList("Alice", "Bob", "Jim")); + assertThat(source.publicNames).isEqualTo(Arrays.asList("Alice", "Bob", "Jim")); + } + + @Test + public void shouldMapIterableToNonIterable() { + List fruits = Arrays.asList(new Fruit("mango"), new Fruit("apple"), + new Fruit("banana")); + FruitsMenu menu = new FruitsMenu(fruits); + FruitSalad salad = converter.convert(menu, FruitSalad.class); + assertThat(salad.getFruits().get(0).getType()).isEqualTo("mango"); + assertThat(salad.getFruits().get(1).getType()).isEqualTo("apple"); + assertThat(salad.getFruits().get(2).getType()).isEqualTo("banana"); + } + + @Test + public void shouldMapNonIterableToIterable() { + List fruits = Arrays.asList(new Fruit("mango"), new Fruit("apple"), + new Fruit("banana")); + FruitSalad salad = new FruitSalad(fruits); + FruitsMenu menu = converter.convert(salad, FruitsMenu.class); + assertThat(salad.getFruits()).extracting(Fruit::getType).containsExactly("mango", "apple", "banana"); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/JavaExpressionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/JavaExpressionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7f2cb20b214bfada726e82d5668eb03a2604331d --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/JavaExpressionTest.java @@ -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 io.github.linpeilie; + +import io.github.linpeilie.me.source.expressions.java.BooleanWorkAroundMapper; +import io.github.linpeilie.me.source.expressions.java.MultiLineExpressionMapper; +import io.github.linpeilie.me.source.expressions.java.QualifierProvider; +import io.github.linpeilie.me.source.expressions.java.Source; +import io.github.linpeilie.me.source.expressions.java.Source2; +import io.github.linpeilie.me.source.expressions.java.SourceBooleanWorkAround; +import io.github.linpeilie.me.source.expressions.java.SourceList; +import io.github.linpeilie.me.source.expressions.java.SourceTargetListMapper; +import io.github.linpeilie.me.source.expressions.java.Target; +import io.github.linpeilie.me.source.expressions.java.Target1; +import io.github.linpeilie.me.source.expressions.java.TargetBooleanWorkAround; +import io.github.linpeilie.me.source.expressions.java.TargetList; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class JavaExpressionTest { + + @Autowired + private Converter converter; + + private Date getTime(String format, String date) throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + return dateFormat.parse(date); + } + + @Test + public void testBooleanGetterWorkAround() throws ParseException { + SourceBooleanWorkAround source = new SourceBooleanWorkAround(); + source.setVal(Boolean.TRUE); + + TargetBooleanWorkAround target = converter.convert(source, TargetBooleanWorkAround.class); + assertThat(target).isNotNull(); + assertThat(target.isVal()).isTrue(); + + SourceBooleanWorkAround source2 = converter.convert(target, SourceBooleanWorkAround.class); + assertThat(source2).isNotNull(); + assertThat(source2.isVal()).isTrue(); + } + + @Test + public void testGetterOnly() throws ParseException { + SourceList source = new SourceList(); + source.setList(Arrays.asList("test1")); + + TargetList target = converter.convert(source, TargetList.class); + assertThat(target).isNotNull(); + assertThat(target.getList()).isEqualTo(Arrays.asList("test2")); + } + + @Test + public void testMultiLineJavaExpressionInsertion() throws ParseException { + Source source = new Source(); + String format = "dd-MM-yyyy,hh:mm:ss"; + Date time = getTime(format, "09-01-2014,01:35:03"); + + source.setFormat(format); + source.setTime(time); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getTimeAndFormat().getTime()).isEqualTo(time); + assertThat(target.getTimeAndFormat().getFormat()).isEqualTo(format); + assertThat(target.getAnotherProp()).isNull(); + + Target1 target1 = converter.convert(source, Target1.class); + + assertThat(target1).isNotNull(); + assertThat(target1.getTimeAndFormat().getTime()).isEqualTo(time); + assertThat(target1.getTimeAndFormat().getFormat()).isEqualTo(format); + assertThat(target1.getAnotherProp()).isNull(); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/LossyConversionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/LossyConversionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..378081f6d51517c075ab3b9883ebfb1f40cb0edf --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/LossyConversionTest.java @@ -0,0 +1,34 @@ +package io.github.linpeilie; + +import io.github.linpeilie.me.conversion.lossy.CutleryInventoryDto; +import io.github.linpeilie.me.conversion.lossy.CutleryInventoryEntity; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.withinPercentage; + +@SpringBootTest(classes = Application.class) +public class LossyConversionTest { + + @Autowired + private Converter converter; + + @Test + public void testNoErrorCase() { + + CutleryInventoryDto dto = new CutleryInventoryDto(); + dto.setNumberOfForks(5); + dto.setNumberOfKnifes((short) 7); + dto.setNumberOfSpoons((byte) 3); + dto.setApproximateKnifeLength(3.7f); + + CutleryInventoryEntity entity = converter.convert(dto, CutleryInventoryEntity.class); + assertThat(entity.getNumberOfForks()).isEqualTo(5L); + assertThat(entity.getNumberOfKnifes()).isEqualTo(7); + assertThat(entity.getNumberOfSpoons()).isEqualTo((short) 3); + assertThat(entity.getApproximateKnifeLength()).isCloseTo(3.7d, withinPercentage(0.0001d)); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/MappingControlTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/MappingControlTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3042759d6dfa8d85ddca51079539c72081263200 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/MappingControlTest.java @@ -0,0 +1,112 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.mappingcontrol.CoolBeerDTO; +import io.github.linpeilie.me.mappingcontrol.CustomerDto; +import io.github.linpeilie.me.mappingcontrol.FridgeDTO; +import io.github.linpeilie.me.mappingcontrol.OrderItemDto; +import io.github.linpeilie.me.mappingcontrol.OrderItemKeyDto; +import io.github.linpeilie.me.mappingcontrol.ShelveDTO; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +@SpringBootTest(classes = Application.class) +public class MappingControlTest { + + @Autowired + private Converter converter; + + /** + * Test the deep cloning annotation + */ + @Test + public void testDeepCloning() { + + FridgeDTO in = createFridgeDTO(); + FridgeDTO out = converter.convert(in, FridgeDTO.class); + + assertThat(out).isNotNull(); + assertThat(out.getShelve()).isNotNull(); + assertThat(out.getShelve()).isNotSameAs(in.getShelve()); + assertThat(out.getShelve().getCoolBeer()).isNotSameAs(in.getShelve().getCoolBeer()); + assertThat(out.getShelve().getCoolBeer().getBeerCount()).isEqualTo("5"); + } + + @Test + public void testDeepCloningViaBeanMapping() { + + FridgeDTO in = createFridgeDTO(); + FridgeDTO out = converter.convert(in, FridgeDTO.class); + + assertThat(out).isNotNull(); + assertThat(out.getShelve()).isNotNull(); + assertThat(out.getShelve()).isNotSameAs(in.getShelve()); + assertThat(out.getShelve().getCoolBeer()).isNotSameAs(in.getShelve().getCoolBeer()); + assertThat(out.getShelve().getCoolBeer().getBeerCount()).isEqualTo("5"); + } + + /** + * Test the deep cloning annotation with lists + */ + @Test + public void testDeepCloningListsAndMaps() { + + CustomerDto in = new CustomerDto(); + in.setId(10L); + in.setCustomerName("Jaques"); + OrderItemDto order1 = new OrderItemDto(); + order1.setName("Table"); + order1.setQuantity(2L); + in.setOrders(new ArrayList<>(Collections.singleton(order1))); + OrderItemKeyDto key = new OrderItemKeyDto(); + key.setStockNumber(5); + Map stock = new HashMap<>(); + stock.put(key, order1); + in.setStock(stock); + + CustomerDto out = converter.convert(in, CustomerDto.class); + + assertThat(out.getId()).isEqualTo(10); + assertThat(out.getCustomerName()).isEqualTo("Jaques"); + assertThat(out.getOrders()) + .extracting("name", "quantity") + .containsExactly(tuple("Table", 2L)); + assertThat(out.getStock()).isNotNull(); + assertThat(out.getStock()).hasSize(1); + + Map.Entry entry = out.getStock().entrySet().iterator().next(); + assertThat(entry.getKey().getStockNumber()).isEqualTo(5); + assertThat(entry.getValue().getName()).isEqualTo("Table"); + assertThat(entry.getValue().getQuantity()).isEqualTo(2L); + + // check mapper really created new objects + assertThat(out).isNotSameAs(in); + assertThat(out.getOrders().get(0)).isNotSameAs(order1); + assertThat(entry.getKey()).isNotSameAs(key); + assertThat(entry.getValue()).isNotSameAs(order1); + assertThat(entry.getValue()).isNotSameAs(out.getOrders().get(0)); + } + + private FridgeDTO createFridgeDTO() { + FridgeDTO fridgeDTO = new FridgeDTO(); + ShelveDTO shelveDTO = new ShelveDTO(); + CoolBeerDTO coolBeerDTO = new CoolBeerDTO(); + fridgeDTO.setShelve(shelveDTO); + shelveDTO.setCoolBeer(coolBeerDTO); + coolBeerDTO.setBeerCount("5"); + return fridgeDTO; + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NoSetterCollectionMappingTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NoSetterCollectionMappingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2db007ab4c79a854f9bd73c19cadd975cfb2b83b --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NoSetterCollectionMappingTest.java @@ -0,0 +1,53 @@ +package io.github.linpeilie; + +import io.github.linpeilie.me.collection.defaultimplementation.NoSetterSource; +import io.github.linpeilie.me.collection.defaultimplementation.NoSetterTarget; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; + +@SpringBootTest(classes = Application.class) +public class NoSetterCollectionMappingTest { + + @Autowired + private Converter converter; + + @Test + public void compilesAndMapsCorrectly() { + NoSetterSource source = new NoSetterSource(); + source.setListValues(Arrays.asList("foo", "bar")); + HashMap mapValues = new HashMap<>(); + mapValues.put("fooKey", "fooVal"); + mapValues.put("barKey", "barVal"); + + source.setMapValues(mapValues); + NoSetterTarget target = converter.convert(source, NoSetterTarget.class); + + assertThat(target.getListValues()).containsExactly("foo", "bar"); + assertThat(target.getMapValues()).contains(entry("fooKey", "fooVal"), entry("barKey", "barVal")); + + // now test existing instances + + NoSetterSource source2 = new NoSetterSource(); + source2.setListValues(Arrays.asList("baz")); + List originalCollectionInstance = target.getListValues(); + Map originalMapInstance = target.getMapValues(); + + NoSetterTarget target2 = converter.convert(source2, target); + + assertThat(target2.getListValues()).isSameAs(originalCollectionInstance); + assertThat(target2.getListValues()).containsExactly("baz"); + assertThat(target2.getMapValues()).isSameAs(originalMapInstance); + // source2 mapvalues is empty, so the map is not cleared + //assertThat( target2.getMapValues() ).contains( entry( "fooKey", "fooVal" ), entry( "barKey", "barVal" ) ); + + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullCheckTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullCheckTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b632765c5ad90c5aff8958894fb13ee72c0392f7 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullCheckTest.java @@ -0,0 +1,89 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.nullcheck.NullObject; +import io.github.linpeilie.me.nullcheck.Source; +import io.github.linpeilie.me.nullcheck.Target; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@SpringBootTest(classes = Application.class) +public class NullCheckTest { + + @Autowired + private Converter converter; + + @Test + public void shouldThrowNullptrWhenCustomMapperIsInvoked() { + + Source source = new Source(); + source.setNumber("5"); + source.setSomeInteger(7); + source.setSomeLong(2L); + + assertThatThrownBy(() -> converter.convert(source, Target.class)) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void shouldSurroundTypeConversionWithNullCheck() { + + Source source = new Source(); + source.setSomeObject(new NullObject()); + source.setSomeInteger(7); + source.setSomeLong(2L); + + Target target = converter.convert(source, Target.class); + + assertThat(target.getNumber()).isNull(); + + } + + @Test + public void shouldSurroundArrayListConstructionWithNullCheck() { + + Source source = new Source(); + source.setSomeObject(new NullObject()); + source.setSomeInteger(7); + source.setSomeLong(2L); + + Target target = converter.convert(source, Target.class); + + assertThat(target.getSomeList()).isNull(); + } + + @Test + public void shouldSurroundConversionPassedToMappingMethodWithNullCheck() { + + Source source = new Source(); + source.setSomeObject(new NullObject()); + source.setSomeLong(2L); + + Target target = converter.convert(source, Target.class); + + assertThat(target.getSomeList()).isNull(); + assertThat(target.getSomeInteger()).isNull(); + } + + @Test + public void shouldSurroundConversionFromWrappedPassedToMappingMethodWithPrimitiveArgWithNullCheck() { + + Source source = new Source(); + source.setSomeObject(new NullObject()); + source.setSomeInteger(7); + + Target target = converter.convert(source, Target.class); + + assertThat(target.getSomeList()).isNull(); + assertThat(target.getSomeLong()).isNull(); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValueCheckTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValueCheckTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e23a7539649582345bd9497ba2940f43efa639dc --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValueCheckTest.java @@ -0,0 +1,58 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.nullcheck.strategy.HouseDto; +import io.github.linpeilie.me.nullcheck.strategy.HouseEntity; +import io.github.linpeilie.me.nullcheck.strategy.HouseEntity1; +import io.github.linpeilie.me.nullcheck.strategy.HouseEntity2; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class NullValueCheckTest { + + @Autowired + private Converter converter; + + @Test + public void testDefinedOnMapper() { + + HouseEntity entity = converter.convert(new HouseDto(), HouseEntity.class); + + assertThat(entity).isNotNull(); + assertThat(entity.ownerSet()).isFalse(); + assertThat(entity.numberSet()).isFalse(); + + } + + @Test + public void testDefinedOnBean() { + + HouseEntity1 entity = converter.convert(new HouseDto(), HouseEntity1.class); + + assertThat(entity).isNotNull(); + assertThat(entity.ownerSet()).isTrue(); + assertThat(entity.numberSet()).isTrue(); + + } + + @Test + public void testDefinedOnMapping() { + + HouseEntity2 entity = converter.convert(new HouseDto(), HouseEntity2.class); + + assertThat(entity).isNotNull(); + assertThat(entity.ownerSet()).isTrue(); + assertThat(entity.numberSet()).isFalse(); + + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValueMappingTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValueMappingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9d0701e02210c9c57f77b01339d916315450eb47 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValueMappingTest.java @@ -0,0 +1,56 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.nullvaluemapping._target.CarDto; +import io.github.linpeilie.me.nullvaluemapping.source.Car; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class NullValueMappingTest { + + @Autowired + private Converter converter; + + @Test + public void shouldMapExpressionAndConstantRegardlessNullArg() { + //given + Car car = new Car("Morris", 2); + + //when + CarDto carDto1 = converter.convert(car, CarDto.class); + + //then + assertThat(carDto1).isNotNull(); + assertThat(carDto1.getMake()).isEqualTo(car.getMake()); + assertThat(carDto1.getSeatCount()).isEqualTo(car.getNumberOfSeats()); + assertThat(carDto1.getModel()).isEqualTo("ModelT"); + assertThat(carDto1.getCatalogId()).isNotEmpty(); + } + + @Test + public void shouldMapIterableWithNullArg() { + + //given + Car car = new Car("Morris", 2); + + //when + List carDtos1 = converter.convert(Arrays.asList(car), CarDto.class); + + //then + assertThat(carDtos1).isNotNull(); + assertThat(carDtos1.size()).isEqualTo(1); + + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValuePropertyMappingTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValuePropertyMappingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..88143471cfbf60980f81b0eca17298c3af2193bc --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NullValuePropertyMappingTest.java @@ -0,0 +1,109 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package io.github.linpeilie; + +import io.github.linpeilie.me.nullvaluepropertymapping.AddressDTO; +import io.github.linpeilie.me.nullvaluepropertymapping.AddressDTO1; +import io.github.linpeilie.me.nullvaluepropertymapping.AddressDTO2; +import io.github.linpeilie.me.nullvaluepropertymapping.Customer; +import io.github.linpeilie.me.nullvaluepropertymapping.CustomerDTO; +import io.github.linpeilie.me.nullvaluepropertymapping.CustomerDTO1; +import io.github.linpeilie.me.nullvaluepropertymapping.HomeDTO; +import io.github.linpeilie.me.nullvaluepropertymapping.HomeDTO1; +import io.github.linpeilie.me.nullvaluepropertymapping.UserDTO; +import io.github.linpeilie.me.nullvaluepropertymapping.UserDTO1; +import java.util.Arrays; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class NullValuePropertyMappingTest { + + @Autowired + private Converter converter; + + @Test + public void testStrategyAppliedOnForgedMethod() { + + Customer customer = new Customer(); + customer.setAddress( null ); + + UserDTO1 userDTO = new UserDTO1(); + userDTO.setHomeDTO( new HomeDTO1() ); + userDTO.getHomeDTO().setAddressDTO( new AddressDTO1() ); + userDTO.getHomeDTO().getAddressDTO().setHouseNo( 5 ); + userDTO.setDetails( Arrays.asList( "green hair" ) ); + + converter.convert( customer, userDTO ); + + assertThat( userDTO.getHomeDTO() ).isNotNull(); + assertThat( userDTO.getHomeDTO().getAddressDTO() ).isNotNull(); + assertThat( userDTO.getHomeDTO().getAddressDTO().getHouseNo() ).isEqualTo( 5 ); + assertThat( userDTO.getDetails() ).isNotNull(); + assertThat( userDTO.getDetails() ).containsExactly( "green hair" ); + } + + @Test + public void testHierarchyIgnoreOnMapping() { + Customer customer = new Customer(); + customer.setAddress( null ); + + CustomerDTO customerDto = new CustomerDTO(); + customerDto.setAddress( new AddressDTO1() ); + customerDto.getAddress().setHouseNo( 5 ); + customerDto.setDetails( Arrays.asList( "green hair" ) ); + + converter.convert( customer, customerDto ); + + assertThat( customerDto.getAddress() ).isNotNull(); + assertThat( customerDto.getAddress().getHouseNo() ).isEqualTo( 5 ); + assertThat( customerDto.getDetails() ).isNotNull(); + assertThat( customerDto.getDetails() ).containsExactly( "green hair" ); + } + + @Test + public void testHierarchyIgnoreOnPropertyMappingMethod() { + Customer customer = new Customer(); + customer.setAddress( null ); + + CustomerDTO1 customerDto = new CustomerDTO1(); + customerDto.setAddress( new AddressDTO2() ); + customerDto.getAddress().setHouseNo( 5 ); + customerDto.setDetails( Arrays.asList( "green hair" ) ); + + converter.convert( customer, customerDto ); + + assertThat( customerDto.getAddress() ).isNotNull(); + assertThat( customerDto.getAddress().getHouseNo() ).isEqualTo( 5 ); + assertThat( customerDto.getDetails() ).isNotNull(); + assertThat( customerDto.getDetails() ).containsExactly( "green hair" ); + } + + @Test + public void testStrategyDefaultAppliedOnForgedMethod() { + + Customer customer = new Customer(); + customer.setAddress( null ); + + UserDTO userDTO = new UserDTO(); + userDTO.setHomeDTO( new HomeDTO() ); + userDTO.getHomeDTO().setAddressDTO( new AddressDTO() ); + userDTO.getHomeDTO().getAddressDTO().setHouseNo( 5 ); + userDTO.setDetails( Arrays.asList( "green hair" ) ); + + converter.convert( customer, userDTO ); + + assertThat( userDTO.getHomeDTO() ).isNotNull(); + assertThat( userDTO.getHomeDTO().getAddressDTO() ).isNotNull(); + assertThat( userDTO.getHomeDTO().getAddressDTO().getHouseNo() ).isNull(); + assertThat( userDTO.getDetails() ).isNotNull(); + assertThat( userDTO.getDetails() ).isEmpty(); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NumberFormatConversionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NumberFormatConversionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fb51ddf067acb0d8facd6ac59417c13fd4225293 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/NumberFormatConversionTest.java @@ -0,0 +1,106 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.conversion.numbers.Source; +import io.github.linpeilie.me.conversion.numbers.Target; +import java.math.BigDecimal; +import java.math.BigInteger; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class NumberFormatConversionTest { + + @Autowired + private Converter converter; + + @Test + public void shouldApplyStringConversions() { + Source source = new Source(); + source.setI(1); + source.setIi(2); + source.setD(3.0); + source.setDd(4.0); + source.setF(3.0f); + source.setFf(4.0f); + source.setL(5L); + source.setLl(6L); + source.setB((byte) 7); + source.setBb((byte) 8); + + source.setComplex1(345346.456756); + source.setComplex2(5007034.3); + + source.setBigDecimal1(new BigDecimal("987E-20")); + source.setBigInteger1(new BigInteger("1234567890000")); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getI()).isEqualTo("1.00"); + assertThat(target.getIi()).isEqualTo("2.00"); + assertThat(target.getD()).isEqualTo("3.00"); + assertThat(target.getDd()).isEqualTo("4.00"); + assertThat(target.getF()).isEqualTo("3.00"); + assertThat(target.getFf()).isEqualTo("4.00"); + assertThat(target.getL()).isEqualTo("5.00"); + assertThat(target.getLl()).isEqualTo("6.00"); + assertThat(target.getB()).isEqualTo("7.00"); + assertThat(target.getBb()).isEqualTo("8.00"); + + assertThat(target.getComplex1()).isEqualTo("345.35E3"); + assertThat(target.getComplex2()).isEqualTo("$5007034.30"); + + assertThat(target.getBigDecimal1()).isEqualTo("9.87E-18"); + assertThat(target.getBigInteger1()).isEqualTo("1.23456789E12"); + } + + @Test + public void shouldApplyReverseStringConversions() { + Target target = new Target(); + target.setI("1.00"); + target.setIi("2.00"); + target.setD("3.00"); + target.setDd("4.00"); + target.setF("3.00"); + target.setFf("4.00"); + target.setL("5.00"); + target.setLl("6.00"); + target.setB("7.00"); + target.setBb("8.00"); + + target.setComplex1("345.35E3"); + target.setComplex2("$5007034.30"); + + target.setBigDecimal1("9.87E-18"); + target.setBigInteger1("1.23456789E12"); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getI()).isEqualTo(1); + assertThat(source.getIi()).isEqualTo(Integer.valueOf(2)); + assertThat(source.getD()).isEqualTo(3.0); + assertThat(source.getDd()).isEqualTo(Double.valueOf(4.0)); + assertThat(source.getF()).isEqualTo(3.0f); + assertThat(source.getFf()).isEqualTo(Float.valueOf(4.0f)); + assertThat(source.getL()).isEqualTo(5L); + assertThat(source.getLl()).isEqualTo(Long.valueOf(6L)); + assertThat(source.getB()).isEqualTo((byte) 7); + assertThat(source.getBb()).isEqualTo((byte) 8); + + assertThat(source.getComplex1()).isEqualTo(345350.0); + assertThat(source.getComplex2()).isEqualTo(5007034.3); + + assertThat(source.getBigDecimal1()).isEqualTo(new BigDecimal("987E-20")); + assertThat(source.getBigInteger1()).isEqualTo(new BigInteger("1234567890000")); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/OrderingTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/OrderingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6401d3199bf18276dd6f0435c94ca330f7dd6e05 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/OrderingTest.java @@ -0,0 +1,51 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.dependency.Address; +import io.github.linpeilie.me.dependency.AddressDto; +import io.github.linpeilie.me.dependency.Person; +import io.github.linpeilie.me.dependency.PersonDto; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class OrderingTest { + + @Autowired + private Converter converter; + + @Test + public void shouldApplyChainOfDependencies() { + Address source = new Address(); + source.setFirstName("Bob"); + source.setMiddleName("J."); + source.setLastName("McRobb"); + + AddressDto target = converter.convert(source, AddressDto.class); + + assertThat(target).isNotNull(); + assertThat(target.getFullName()).isEqualTo("Bob J. McRobb"); + } + + @Test + public void shouldApplySeveralDependenciesConfiguredForOneProperty() { + Person source = new Person(); + source.setFirstName("Bob"); + source.setMiddleName("J."); + source.setLastName("McRobb"); + + PersonDto target = converter.convert(source, PersonDto.class); + + assertThat(target).isNotNull(); + assertThat(target.getFullName()).isEqualTo("Bob J. McRobb"); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/PresenceCheckTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/PresenceCheckTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d4dd7ec1ddae7f070d8664a21d72dcb6b629603e --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/PresenceCheckTest.java @@ -0,0 +1,40 @@ +package io.github.linpeilie; + +import io.github.linpeilie.me.source.nullvaluecheckstrategy.RockFestivalSource; +import io.github.linpeilie.me.source.nullvaluecheckstrategy.RockFestivalTarget; +import io.github.linpeilie.me.source.nullvaluecheckstrategy.RockFestivalTarget1; +import io.github.linpeilie.me.source.nullvaluecheckstrategy.Stage; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@SpringBootTest(classes = Application.class) +public class PresenceCheckTest { + + @Autowired + private Converter converter; + + @Test + public void testCallingMappingMethodWithNullSource() { + + RockFestivalSource source = new RockFestivalSource(); + RockFestivalTarget target = converter.convert(source, RockFestivalTarget.class); + assertThat(target.getStage()).isNull(); + + source.setArtistName("New Order"); + target = converter.convert(source, RockFestivalTarget.class); + assertThat(target.getStage()).isEqualTo(Stage.THE_BARN); + + } + + @Test + public void testCallingMappingMethodWithNullSourceOveridingConfig() { + + RockFestivalSource source = new RockFestivalSource(); + assertThatThrownBy(() -> converter.convert(source, RockFestivalTarget1.class)).isInstanceOf( + IllegalArgumentException.class); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/QuickStartTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/QuickStartTest.java index ee90bba0860dab5d6dca377da0d795156b0c9f95..d4d9e1c74cfe6ca7cf92be1d55b452a009781707 100644 --- a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/QuickStartTest.java +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/QuickStartTest.java @@ -1,8 +1,47 @@ package io.github.linpeilie; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; +import io.github.linpeilie.me.array.Scientist; +import io.github.linpeilie.me.array.ScientistDto; +import io.github.linpeilie.me.bool.Person; +import io.github.linpeilie.me.bool.PersonDto; +import io.github.linpeilie.me.bool.YesNo; +import io.github.linpeilie.me.builder.abstractBuilder.ImmutableProduct; +import io.github.linpeilie.me.builder.abstractBuilder.ProductDto; +import io.github.linpeilie.me.builder.abstractGenericTarget.ChildSource; +import io.github.linpeilie.me.builder.abstractGenericTarget.ImmutableChild; +import io.github.linpeilie.me.builder.abstractGenericTarget.ImmutableParent; +import io.github.linpeilie.me.builder.abstractGenericTarget.MutableParent; +import io.github.linpeilie.me.builder.abstractGenericTarget.Parent; +import io.github.linpeilie.me.builder.abstractGenericTarget.ParentSource; +import io.github.linpeilie.me.builder.factory.ImplicitPerson; +import io.github.linpeilie.me.callbacks.ongeneratedmethods.Address; +import io.github.linpeilie.me.callbacks.ongeneratedmethods.Company; +import io.github.linpeilie.me.callbacks.ongeneratedmethods.CompanyDto; +import io.github.linpeilie.me.callbacks.ongeneratedmethods.Employee; +import io.github.linpeilie.me.callbacks.typematching.CarDto; +import io.github.linpeilie.me.callbacks.typematching.CarEntity; +import io.github.linpeilie.me.callbacks.typematching.CarMapper; +import io.github.linpeilie.me.field_mapping.Customer; +import io.github.linpeilie.me.field_mapping.CustomerDto; +import io.github.linpeilie.me.field_mapping.OrderItem; +import io.github.linpeilie.me.field_mapping.OrderItemDto; +import io.github.linpeilie.me.iterable_to_non_iterable.Source; +import io.github.linpeilie.me.iterable_to_non_iterable.Target; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankDto; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankDto1; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankDto2; +import io.github.linpeilie.me.nested_bean_mappings.dto.FishTankWithNestedDocumentDto; +import io.github.linpeilie.me.nested_bean_mappings.model.Fish; +import io.github.linpeilie.me.nested_bean_mappings.model.FishTank; +import io.github.linpeilie.me.nested_bean_mappings.model.Interior; +import io.github.linpeilie.me.nested_bean_mappings.model.MaterialType; +import io.github.linpeilie.me.nested_bean_mappings.model.Ornament; +import io.github.linpeilie.me.nested_bean_mappings.model.WaterPlant; +import io.github.linpeilie.me.nested_bean_mappings.model.WaterQuality; +import io.github.linpeilie.me.nested_bean_mappings.model.WaterQualityReport; import io.github.linpeilie.model.Car; import io.github.linpeilie.model.EnglishRelease; import io.github.linpeilie.model.FrenchRelease; @@ -32,6 +71,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -40,7 +80,11 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest(classes = Application.class) public class QuickStartTest { @Autowired @@ -309,6 +353,440 @@ public class QuickStartTest { frenchRelease2.setTitle("Cent ans de solitude"); EnglishRelease englishRelease2 = converter.convert(frenchRelease2, EnglishRelease.class); Assert.equals(englishRelease2.getTitle(), "One Hundred Years of Solitude"); + + EnglishRelease englishRelease3 = new EnglishRelease(); + englishRelease3.setTitle("Default"); + FrenchRelease frenchRelease = converter.convert(englishRelease3, FrenchRelease.class); + System.out.println(frenchRelease); + } + + @Test + public void testMapDtoToEntity() { + + CustomerDto customerDto = new CustomerDto(); + customerDto.id = 10L; + customerDto.customerName = "Filip"; + OrderItemDto order1 = new OrderItemDto(); + order1.name = "Table"; + order1.quantity = 2L; + customerDto.orders = new ArrayList<>(Collections.singleton(order1)); + + Customer customer = converter.convert(customerDto, Customer.class); + + assertThat(customer.getId()).isEqualTo(10); + assertThat(customer.getName()).isEqualTo("Filip"); + assertThat(customer.getOrderItems()) + .extracting("name", "quantity") + .containsExactly(tuple("Table", 2L)); + } + + @Test + public void testEntityDtoToDto() { + + Customer customer = new Customer(); + customer.setId(10L); + customer.setName("Filip"); + OrderItem order1 = new OrderItem(); + order1.setName("Table"); + order1.setQuantity(2L); + customer.setOrderItems(Collections.singleton(order1)); + + CustomerDto customerDto = converter.convert(customer, CustomerDto.class); + + assertThat(customerDto.id).isEqualTo(10); + assertThat(customerDto.customerName).isEqualTo("Filip"); + assertThat(customerDto.orders) + .extracting("name", "quantity") + .containsExactly(tuple("Table", 2L)); + } + + @Test + public void testToTarget() { + + Source s = new Source(); + s.setMyIntegers(Arrays.asList(5, 3, 7)); + s.setMyStrings(Arrays.asList("five", "three", "seven")); + + Target t = converter.convert(s, Target.class); + assertEquals(new Integer(5), t.getMyInteger()); + assertEquals("seven", t.getMyString()); + } + + @Test + public void testToTargetWithConstant() { + Source s = new Source(); + Target t = converter.convert(s, Target.class); + System.out.println(t); + } + + @Test + public void shouldAutomapAndHandleSourceAndTargetPropertyNesting() { + + // -- prepare + FishTank source = createFishTank(); + + // -- action + FishTankDto target = converter.convert(source, FishTankDto.class); + + // -- result + assertThat(target.getName()).isEqualTo(source.getName()); + + // fish and fishDto can be automapped + assertThat(target.getFish()).isNotNull(); + assertThat(target.getFish().getKind()).isEqualTo(source.getFish().getType()); + assertThat(target.getFish().getName()).isNull(); + + // automapping takes care of mapping property "waterPlant". + assertThat(target.getPlant()).isNotNull(); + assertThat(target.getPlant().getKind()).isEqualTo(source.getPlant().getKind()); + + // ornament (nested asymetric source) + assertThat(target.getOrnament()).isNotNull(); + assertThat(target.getOrnament().getType()).isEqualTo(source.getInterior().getOrnament().getType()); + + // material (nested asymetric target) + assertThat(target.getMaterial()).isNotNull(); + assertThat(target.getMaterial().getManufacturer()).isNull(); + assertThat(target.getMaterial().getMaterialType()).isNotNull(); + assertThat(target.getMaterial().getMaterialType().getType()).isEqualTo(source.getMaterial().getType()); + + // first symetric then asymetric + assertThat(target.getQuality()).isNotNull(); + assertThat(target.getQuality().getReport()).isNotNull(); + assertThat(target.getQuality().getReport().getVerdict()) + .isEqualTo(source.getQuality().getReport().getVerdict()); + assertThat(target.getQuality().getReport().getOrganisation().getApproval()).isNull(); + assertThat(target.getQuality().getReport().getOrganisation()).isNotNull(); + assertThat(target.getQuality().getReport().getOrganisation().getName()) + .isEqualTo(source.getQuality().getReport().getOrganisationName()); + } + + @Test + public void shouldAutomapAndHandleSourceAndTargetPropertyNestingReverse() { + + // -- prepare + FishTank source = createFishTank(); + + // -- action + FishTankDto target = converter.convert(source, FishTankDto.class); + FishTank source2 = converter.convert(target, FishTank.class); + + // -- result + assertThat(source2.getName()).isEqualTo(source.getName()); + + // fish + assertThat(source2.getFish()).isNotNull(); + assertThat(source2.getFish().getType()).isEqualTo(source.getFish().getType()); + + // interior, designer will not be mapped (asymetric) to target. Here it shows. + assertThat(source2.getInterior()).isNotNull(); + assertThat(source2.getInterior().getDesigner()).isNull(); + assertThat(source2.getInterior().getOrnament()).isNotNull(); + assertThat(source2.getInterior().getOrnament().getType()) + .isEqualTo(source.getInterior().getOrnament().getType()); + + // material + assertThat(source2.getMaterial()).isNotNull(); + assertThat(source2.getMaterial().getType()).isEqualTo(source.getMaterial().getType()); + + // plant + assertThat(source2.getPlant().getKind()).isEqualTo(source.getPlant().getKind()); + + // quality + assertThat(source2.getQuality().getReport()).isNotNull(); + assertThat(source2.getQuality().getReport().getOrganisationName()) + .isEqualTo(source.getQuality().getReport().getOrganisationName()); + assertThat(source2.getQuality().getReport().getVerdict()) + .isEqualTo(source.getQuality().getReport().getVerdict()); + } + + @Test + public void shouldAutomapAndHandleSourceAndTargetPropertyNestingAndConstant() { + + // -- prepare + FishTank source = createFishTank(); + + // -- action + FishTankDto1 target = converter.convert(source, FishTankDto1.class); + + // -- result + + // fixed value + assertThat(target.getFish().getName()).isEqualTo("Nemo"); + + // automapping takes care of mapping property "waterPlant". + assertThat(target.getPlant()).isNotNull(); + assertThat(target.getPlant().getKind()).isEqualTo(source.getPlant().getKind()); + + // non-nested and constant + assertThat(target.getMaterial()).isNotNull(); + assertThat(target.getMaterial().getManufacturer()).isEqualTo("MMM"); + assertThat(target.getMaterial().getMaterialType()).isNotNull(); + assertThat(target.getMaterial().getMaterialType().getType()).isEqualTo(source.getMaterial().getType()); + + assertThat(target.getOrnament()).isNull(); + assertThat(target.getQuality()).isNull(); + + } + + @Test + public void shouldAutomapAndHandleSourceAndTargetPropertyNestingAndExpresion() { + + // -- prepare + FishTank source = createFishTank(); + + // -- action + FishTankDto2 target = converter.convert(source, FishTankDto2.class); + + // -- result + assertThat(target.getFish().getName()).isEqualTo("Jaws"); + + assertThat(target.getMaterial()).isNull(); + assertThat(target.getOrnament()).isNull(); + assertThat(target.getPlant()).isNull(); + + assertThat(target.getQuality()).isNotNull(); + assertThat(target.getQuality().getReport()).isNotNull(); + assertThat(target.getQuality().getReport().getVerdict()) + .isEqualTo(source.getQuality().getReport().getVerdict()); + assertThat(target.getQuality().getReport().getOrganisation()).isNotNull(); + assertThat(target.getQuality().getReport().getOrganisation().getApproval()).isNull(); + assertThat(target.getQuality().getReport().getOrganisation().getName()).isEqualTo("Dunno"); + } + + @Test + public void shouldAutomapIntermediateLevelAndMapConstant() { + + // -- prepare + FishTank source = createFishTank(); + + // -- action + FishTankWithNestedDocumentDto target = converter.convert(source, FishTankWithNestedDocumentDto.class); + + // -- result + assertThat(target.getFish().getName()).isEqualTo("Jaws"); + + assertThat(target.getMaterial()).isNull(); + assertThat(target.getOrnament()).isNull(); + assertThat(target.getPlant()).isNull(); + + assertThat(target.getQuality()).isNotNull(); + assertThat(target.getQuality().getDocument()).isNotNull(); + assertThat(target.getQuality().getDocument().getVerdict()) + .isEqualTo(source.getQuality().getReport().getVerdict()); + assertThat(target.getQuality().getDocument().getOrganisation()).isNotNull(); + assertThat(target.getQuality().getDocument().getOrganisation().getApproval()).isNull(); + assertThat(target.getQuality().getDocument().getOrganisation().getName()).isEqualTo("NoIdeaInc"); + } + + private FishTank createFishTank() { + FishTank fishTank = new FishTank(); + + Fish fish = new Fish(); + fish.setType("Carp"); + + WaterPlant waterplant = new WaterPlant(); + waterplant.setKind("Water Hyacinth"); + + Interior interior = new Interior(); + interior.setDesigner("MrVeryFamous"); + Ornament ornament = new Ornament(); + ornament.setType("castle"); + interior.setOrnament(ornament); + + WaterQuality quality = new WaterQuality(); + WaterQualityReport report = new WaterQualityReport(); + report.setVerdict("PASSED"); + report.setOrganisationName("ACME"); + quality.setReport(report); + + MaterialType materialType = new MaterialType(); + materialType.setType("myMaterialType"); + + fishTank.setName("MyLittleFishTank"); + fishTank.setFish(fish); + fishTank.setPlant(waterplant); + fishTank.setInterior(interior); + fishTank.setMaterial(materialType); + fishTank.setQuality(quality); + + return fishTank; + } + + @Test + public void shouldCopyArraysInBean() { + + Scientist source = new Scientist("Bob"); + source.setPublications(new String[] {"the Lancet", "Nature"}); + source.publicPublications = new String[] {"public the Lancet", "public Nature"}; + + ScientistDto dto = converter.convert(source, ScientistDto.class); + + assertThat(dto).isNotNull(); + assertThat(dto).isNotEqualTo(source); + assertThat(dto.getPublications()).containsOnly("the Lancet", "Nature"); + assertThat(dto.publicPublications).containsOnly("public the Lancet", "public Nature"); + } + + @Test + public void shouldForgeMappingForIntToString() { + + Scientist source = new Scientist("Bob"); + source.setPublicationYears(new String[] {"1993", "1997"}); + source.publicPublicationYears = new String[] {"1994", "1998"}; + + ScientistDto dto = converter.convert(source, ScientistDto.class); + + assertThat(dto).isNotNull(); + assertThat(dto.getPublicationYears()).containsOnly(1993, 1997); + assertThat(dto.publicPublicationYears).containsOnly(1994, 1998); + } + + @Test + public void shouldMapArrayToList() { + List dtos = + converter.convert(CollectionUtil.newArrayList(new Scientist("Bob"), new Scientist("Larry")), + ScientistDto.class); + + assertThat(dtos).isNotNull(); + assertThat(dtos).extracting("name").containsOnly("Bob", "Larry"); + } + + @Test + public void shouldMapBooleanPropertyWithIsPrefixedGetter() { + //given + Person person = new Person(); + person.setMarried(Boolean.TRUE); + + //when + PersonDto personDto = converter.convert(person, PersonDto.class); + + //then + assertThat(personDto.getMarried()).isEqualTo("true"); + } + + @Test + public void shouldMapBooleanPropertyPreferringGetPrefixedGetterOverIsPrefixedGetter() { + //given + Person person = new Person(); + person.setEngaged(Boolean.TRUE); + + //when + PersonDto personDto = converter.convert(person, PersonDto.class); + + //then + assertThat(personDto.getEngaged()).isEqualTo("true"); + } + + @Test + public void shouldMapBooleanPropertyWithPropertyMappingMethod() { + // given + Person person = new Person(); + person.setDivorced(new YesNo(true)); + person.setWidowed(new YesNo(true)); + + // when + PersonDto personDto = converter.convert(person, PersonDto.class); + + // then + assertThat(personDto.getDivorced()).isEqualTo("yes"); + assertThat(personDto.getWidowed()).isEqualTo(Boolean.TRUE); + } + + @Test + public void testThatAbstractBuilderMapsAllProperties() { + ImmutableProduct product = converter.convert(new ProductDto("router", 31), ImmutableProduct.class); + + assertThat(product.getPrice()).isEqualTo(31); + assertThat(product.getName()).isEqualTo("router"); + } + + @Test + public void testThatAbstractBuilderReverseMapsAllProperties() { + ProductDto product = converter.convert(ImmutableProduct.builder() + .price(31000) + .name("car") + .build(), ProductDto.class); + + assertThat(product.getPrice()).isEqualTo(31000); + assertThat(product.getName()).isEqualTo("car"); + } + + @Test + public void testAbstractTargetMapper() { + ParentSource parent = new ParentSource(); + parent.setCount(4); + parent.setChild(new ChildSource("Phineas")); + parent.setNonGenericChild(new ChildSource("Ferb")); + + // transform + Parent immutableParent = converter.convert(parent, ImmutableParent.class); + assertThat(immutableParent.getCount()).isEqualTo(4); + assertThat(immutableParent.getChild().getName()).isEqualTo("Phineas"); + assertThat(immutableParent.getNonGenericChild()) + .isNotNull() + .isInstanceOf(ImmutableChild.class); + assertThat(immutableParent.getNonGenericChild().getName()).isEqualTo("Ferb"); + + Parent mutableParent = converter.convert(parent, MutableParent.class); + + assertThat(mutableParent.getCount()).isEqualTo(4); + assertThat(mutableParent.getChild().getName()).isEqualTo("Phineas"); + assertThat(mutableParent.getNonGenericChild()) + .isNotNull() + .isInstanceOf(ImmutableChild.class); + assertThat(mutableParent.getNonGenericChild().getName()).isEqualTo("Ferb"); + + } + + @Test + public void shouldUseBuilderFactory() { + io.github.linpeilie.me.builder.factory.Person person = + converter.convert(new io.github.linpeilie.me.builder.factory.PersonDto("Filip"), + io.github.linpeilie.me.builder.factory.Person.class); + + assertThat(person.getName()).isEqualTo("Filip"); + assertThat(person.getSource()).isEqualTo("Factory with @ObjectFactory"); + } + + @Test + public void shouldUseImplicitBuilderFactory() { + ImplicitPerson person = + converter.convert(new io.github.linpeilie.me.builder.factory.PersonDto("Filip"), ImplicitPerson.class); + + assertThat(person.getName()).isEqualTo("Filip"); + assertThat(person.getSource()).isEqualTo("Implicit Factory"); + } + + @Test + public void testOngeneratedMethods() { + // setup + Address address = new Address(); + address.setAddressLine("RoadToNowhere;5"); + address.setTown("SmallTown"); + Employee employee = new Employee(); + employee.setAddress(address); + Company company = new Company(); + company.setEmployees(Arrays.asList(employee)); + + // test + CompanyDto companyDto = converter.convert(company, CompanyDto.class); + + // verify + assertThat(companyDto.getEmployees()).isNotEmpty(); + assertThat(companyDto.getEmployees().size()).isEqualTo(1); + assertThat(companyDto.getEmployees().get(0).getAddress()).isNotNull(); + assertThat(companyDto.getEmployees().get(0).getAddress().getHouseNumber()).isEqualTo(5); + assertThat(companyDto.getEmployees().get(0).getAddress().getStreet()).isEqualTo("RoadToNowhere"); + assertThat(companyDto.getEmployees().get(0).getAddress().getTown()).isEqualTo("SmallTown"); + } + + @Test + public void callbackMethodAreCalled() { + CarEntity carEntity = converter.convert(new CarDto(), CarEntity.class); + + assertThat(carEntity.getId()).isEqualTo(2); + assertThat(carEntity.getSeatCount()).isEqualTo(5); } } diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/SourceConstantsTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/SourceConstantsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..75bdd7380483c1e299a9384ed573626721001a17 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/SourceConstantsTest.java @@ -0,0 +1,61 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.source.constants.CountryEnum; +import io.github.linpeilie.me.source.constants.Source; +import io.github.linpeilie.me.source.constants.Target; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class SourceConstantsTest { + + @Autowired + private Converter converter; + + @Test + public void shouldMapSameSourcePropertyToSeveralTargetProperties() throws ParseException { + Source source = new Source(); + source.setPropertyThatShouldBeMapped("SomeProperty"); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getPropertyThatShouldBeMapped()).isEqualTo("SomeProperty"); + assertThat(target.getStringConstant()).isEqualTo("stringConstant"); + assertThat(target.getIntegerConstant()).isEqualTo(14); + assertThat(target.getLongWrapperConstant()).isEqualTo(new Long(3001L)); + assertThat(target.getDateConstant()).isEqualTo(getDate("dd-MM-yyyy", "09-01-2014")); + assertThat(target.getNameConstants()).isEqualTo(Arrays.asList("jack", "jill", "tom")); + assertThat(target.getCountry()).isEqualTo(CountryEnum.THE_NETHERLANDS); + } + + @Test + public void shouldMapTargetToSourceWithoutWhining() throws ParseException { + Target target = new Target(); + target.setPropertyThatShouldBeMapped("SomeProperty"); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(target.getPropertyThatShouldBeMapped()).isEqualTo("SomeProperty"); + } + + private Date getDate(String format, String date) throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + return dateFormat.parse(date); + } + +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/SourceToManyTargetPropertiesTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/SourceToManyTargetPropertiesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..07903f8a6b72feaecfa9f10ccec33e81ab7d86ad --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/SourceToManyTargetPropertiesTest.java @@ -0,0 +1,56 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.source.manytargetproperties.Source; +import io.github.linpeilie.me.source.manytargetproperties.Target; +import io.github.linpeilie.me.source.manytargetproperties.TimeAndFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class SourceToManyTargetPropertiesTest { + + @Autowired + private Converter converter; + + @Test + public void shouldMapSameSourcePropertyToSeveralTargetProperties() { + Source source = new Source(); + source.setName("Bob"); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getName1()).isEqualTo("Bob"); + assertThat(target.getName2()).isEqualTo("Bob"); + } + + @Test + public void shouldMapSameSourcePropertyToSeveralTargetPropertiesInvokingOtherMapper() throws ParseException { + Source source = new Source(); + String sourceFormat = "dd-MM-yyyy"; + SimpleDateFormat dateFormat = new SimpleDateFormat(sourceFormat); + Date sourceTime = dateFormat.parse("09-01-2014"); + TimeAndFormat sourceTimeAndFormat = new TimeAndFormat(); + sourceTimeAndFormat.setTfFormat(sourceFormat); + sourceTimeAndFormat.setTfTime(sourceTime); + source.setTimeAndFormat(sourceTimeAndFormat); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getFormat()).isEqualTo(sourceFormat); + assertThat(target.getTime()).isEqualTo(sourceTime); + } +} diff --git a/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/StringConversionTest.java b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/StringConversionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2a6ae77f2105f23a26958702f9852bb9c324b598 --- /dev/null +++ b/example/spring-boot-with-lombok/src/test/java/io/github/linpeilie/StringConversionTest.java @@ -0,0 +1,146 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ + +package io.github.linpeilie; + +import io.github.linpeilie.me.conversion.string.Source; +import io.github.linpeilie.me.conversion.string.Target; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class) +public class StringConversionTest { + + private static final String STRING_CONSTANT = "String constant"; + @Autowired + private Converter converter; + + @Test + public void shouldApplyStringConversions() { + Source source = new Source(); + source.setB((byte) 1); + source.setBb((byte) 2); + source.setS((short) 3); + source.setSs((short) 4); + source.setI(5); + source.setIi(6); + source.setL(7L); + source.setLl(8L); + source.setF(9f); + source.setFf(10f); + source.setD(11d); + source.setDd(12d); + source.setBool(true); + source.setBoolBool(Boolean.TRUE); + source.setC('G'); + source.setCc('H'); + source.setSb(new StringBuilder("SB")); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getB()).isEqualTo("1"); + assertThat(target.getBb()).isEqualTo("2"); + assertThat(target.getS()).isEqualTo("3"); + assertThat(target.getSs()).isEqualTo("4"); + assertThat(target.getI()).isEqualTo("5"); + assertThat(target.getIi()).isEqualTo("6"); + assertThat(target.getL()).isEqualTo("7"); + assertThat(target.getLl()).isEqualTo("8"); + assertThat(target.getF()).isEqualTo("9.0"); + assertThat(target.getFf()).isEqualTo("10.0"); + assertThat(target.getD()).isEqualTo("11.0"); + assertThat(target.getDd()).isEqualTo("12.0"); + assertThat(target.getBool()).isEqualTo("true"); + assertThat(target.getBoolBool()).isEqualTo("true"); + assertThat(target.getC()).isEqualTo("G"); + assertThat(target.getCc()).isEqualTo("H"); + assertThat(target.getSb()).isEqualTo("SB"); + } + + @Test + public void shouldNotApplyStringConversionsWhenNull() { + Source source = new Source(); + + Target target = converter.convert(source, Target.class); + + assertThat(target).isNotNull(); + assertThat(target.getB()).isEqualTo("0"); + assertThat(target.getBb()).isNull(); + assertThat(target.getS()).isEqualTo("0"); + assertThat(target.getSs()).isNull(); + assertThat(target.getI()).isEqualTo("0"); + assertThat(target.getIi()).isNull(); + assertThat(target.getL()).isEqualTo("0"); + assertThat(target.getLl()).isNull(); + assertThat(target.getF()).isEqualTo("0.0"); + assertThat(target.getFf()).isNull(); + assertThat(target.getD()).isEqualTo("0.0"); + assertThat(target.getDd()).isNull(); + assertThat(target.getBool()).isEqualTo("false"); + assertThat(target.getBoolBool()).isNull(); + assertThat(target.getC()).isEqualTo(String.valueOf('\u0000')); + assertThat(target.getCc()).isNull(); + assertThat(target.getSb()).isNull(); + } + + @Test + public void shouldApplyReverseStringConversions() { + Target target = new Target(); + target.setB("1"); + target.setBb("2"); + target.setS("3"); + target.setSs("4"); + target.setI("5"); + target.setIi("6"); + target.setL("7"); + target.setLl("8"); + target.setF("9.0"); + target.setFf("10.0"); + target.setD("11.0"); + target.setDd("12.0"); + target.setBool("true"); + target.setBoolBool("true"); + target.setC("G"); + target.setCc("H"); + target.setSb("SB"); + + Source source = converter.convert(target, Source.class); + + assertThat(source).isNotNull(); + assertThat(source.getB()).isEqualTo((byte) 1); + assertThat(source.getBb()).isEqualTo(Byte.valueOf((byte) 2)); + assertThat(source.getS()).isEqualTo((short) 3); + assertThat(source.getSs()).isEqualTo(Short.valueOf((short) 4)); + assertThat(source.getI()).isEqualTo(5); + assertThat(source.getIi()).isEqualTo(Integer.valueOf(6)); + assertThat(source.getL()).isEqualTo(7); + assertThat(source.getLl()).isEqualTo(Long.valueOf(8)); + assertThat(source.getF()).isEqualTo(9f); + assertThat(source.getFf()).isEqualTo(Float.valueOf(10f)); + assertThat(source.getD()).isEqualTo(11d); + assertThat(source.getDd()).isEqualTo(Double.valueOf(12d)); + assertThat(source.getBool()).isEqualTo(true); + assertThat(source.getBoolBool()).isEqualTo(true); + assertThat(source.getC()).isEqualTo('G'); + assertThat(source.getCc()).isEqualTo('H'); + assertThat(source.getSb().toString()).isEqualTo("SB"); + } + + @Test + public void stringShouldBeMappedToObjectByReference() { + Target target = new Target(); + target.setObject(STRING_CONSTANT); + + Source source = converter.convert(target, Source.class); + + // no conversion, no built-in method + assertThat(source.getObject()).isNotSameAs(STRING_CONSTANT); + } +} diff --git a/mapstruct-plus-processor/pom.xml b/mapstruct-plus-processor/pom.xml index e11702d49d68c7da22e132a203471aa4666696ab..66767447a82421e203aa2d5d0762a44678700cbd 100644 --- a/mapstruct-plus-processor/pom.xml +++ b/mapstruct-plus-processor/pom.xml @@ -31,6 +31,10 @@ org.mapstruct mapstruct-processor + + org.mapstruct.tools.gem + gem-api + @@ -43,7 +47,13 @@ ${maven.compiler.source} ${maven.compiler.target} UTF-8 - none + + + org.mapstruct.tools.gem + gem-processor + ${gem.version} + + diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java index 21b45ada6f88c7ef80102ea8b2913b8f83000266..c3e9e4abe320b0e95db8a86ff9b9d477d8e730c5 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java @@ -11,7 +11,7 @@ import com.squareup.javapoet.TypeSpec; import io.github.linpeilie.processor.metadata.AbstractAdapterMethodMetadata; import io.github.linpeilie.processor.metadata.AdapterMapMethodMetadata; import io.github.linpeilie.processor.metadata.AdapterMethodMetadata; -import io.github.linpeilie.processor.utils.ClassUtil; +import io.github.linpeilie.utils.ClassUtil; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index 4c320dd1adb80d629c7f606f5a0db43c2e5ae7c3..9d7150baf973134c3169dc687f9c951f83cdd5fe 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -5,14 +5,15 @@ import com.squareup.javapoet.TypeName; import io.github.linpeilie.ComponentModelConstant; import io.github.linpeilie.annotations.AutoEnumMapper; import io.github.linpeilie.annotations.AutoMapMapper; -import io.github.linpeilie.annotations.AutoMapper; -import io.github.linpeilie.annotations.AutoMappers; -import io.github.linpeilie.annotations.AutoMapping; -import io.github.linpeilie.annotations.AutoMappings; import io.github.linpeilie.annotations.ComponentModelConfig; -import io.github.linpeilie.annotations.MapperConfig; -import io.github.linpeilie.annotations.ReverseAutoMapping; -import io.github.linpeilie.annotations.ReverseAutoMappings; +import io.github.linpeilie.processor.gem.AutoMapperGem; +import io.github.linpeilie.processor.gem.AutoMappersGem; +import io.github.linpeilie.processor.gem.AutoMappingGem; +import io.github.linpeilie.processor.gem.AutoMappingsGem; +import io.github.linpeilie.processor.gem.BuilderGem; +import io.github.linpeilie.processor.gem.MapperConfigGem; +import io.github.linpeilie.processor.gem.ReverseAutoMappingGem; +import io.github.linpeilie.processor.gem.ReverseAutoMappingsGem; import io.github.linpeilie.processor.generator.AutoEnumMapperGenerator; import io.github.linpeilie.processor.generator.AutoMapperGenerator; import io.github.linpeilie.processor.generator.DefaultAdapterMapperGenerator; @@ -28,13 +29,13 @@ import io.github.linpeilie.processor.metadata.AutoMapMapperMetadata; import io.github.linpeilie.processor.metadata.AutoMapperMetadata; import io.github.linpeilie.processor.metadata.AutoMappingMetadata; import io.github.linpeilie.processor.utils.ExceptionUtils; +import io.github.linpeilie.processor.utils.MapperUtils; import io.github.linpeilie.processor.utils.ObjectUtils; import io.github.linpeilie.utils.CollectionUtils; import io.github.linpeilie.utils.StrUtil; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -44,6 +45,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import javax.annotation.processing.AbstractProcessor; @@ -67,11 +69,17 @@ import static io.github.linpeilie.processor.ProcessorOptions.ADAPTER_CLASS_NAME; import static io.github.linpeilie.processor.ProcessorOptions.ADAPTER_PACKAGE; import static io.github.linpeilie.processor.ProcessorOptions.BUILDER_BUILD_METHOD; import static io.github.linpeilie.processor.ProcessorOptions.BUILDER_DISABLE_BUILDER; +import static io.github.linpeilie.processor.ProcessorOptions.COLLECTION_MAPPING_STRATEGY; import static io.github.linpeilie.processor.ProcessorOptions.MAPPER_CONFIG_CLASS; import static io.github.linpeilie.processor.ProcessorOptions.MAPPER_PACKAGE; import static io.github.linpeilie.processor.ProcessorOptions.MAP_ADAPTER_CLASS_NAME; +import static io.github.linpeilie.processor.ProcessorOptions.NULL_VALUE_CHECK_STRATEGY; +import static io.github.linpeilie.processor.ProcessorOptions.NULL_VALUE_ITERABLE_MAPPING_STRATEGY; import static io.github.linpeilie.processor.ProcessorOptions.NULL_VALUE_MAPPING_STRATEGY; +import static io.github.linpeilie.processor.ProcessorOptions.NULL_VALUE_MAP_MAPPING_STRATEGY; import static io.github.linpeilie.processor.ProcessorOptions.NULL_VALUE_PROPERTY_MAPPING_STRATEGY; +import static io.github.linpeilie.processor.ProcessorOptions.SUPPRESS_TIMESTAMP_IN_GENERATED; +import static io.github.linpeilie.processor.ProcessorOptions.TYPE_CONVERSION_POLICY; import static io.github.linpeilie.processor.ProcessorOptions.UNMAPPED_SOURCE_POLICY; import static io.github.linpeilie.processor.ProcessorOptions.UNMAPPED_TARGET_POLICY; import static javax.tools.Diagnostic.Kind.ERROR; @@ -86,7 +94,9 @@ import static javax.tools.Diagnostic.Kind.ERROR; ContextConstants.Annotations.mapper}) @SupportedOptions({MAPPER_CONFIG_CLASS, MAPPER_PACKAGE, UNMAPPED_SOURCE_POLICY, UNMAPPED_TARGET_POLICY, NULL_VALUE_MAPPING_STRATEGY, NULL_VALUE_PROPERTY_MAPPING_STRATEGY, BUILDER_BUILD_METHOD, - BUILDER_DISABLE_BUILDER, ADAPTER_PACKAGE, ADAPTER_CLASS_NAME, MAP_ADAPTER_CLASS_NAME,}) + BUILDER_DISABLE_BUILDER, ADAPTER_PACKAGE, ADAPTER_CLASS_NAME, MAP_ADAPTER_CLASS_NAME, + TYPE_CONVERSION_POLICY, COLLECTION_MAPPING_STRATEGY, NULL_VALUE_ITERABLE_MAPPING_STRATEGY, + NULL_VALUE_MAP_MAPPING_STRATEGY, NULL_VALUE_CHECK_STRATEGY, SUPPRESS_TIMESTAMP_IN_GENERATED}) public class AutoMapperProcessor extends AbstractProcessor { private static final ClassName MAPPING_DEFAULT_TARGET = ClassName.get("io.github.linpeilie", "DefaultMapping"); @@ -344,9 +354,7 @@ public class AutoMapperProcessor extends AbstractProcessor { List uses = Collections.singletonList( ClassName.get(ContextConstants.MapObjectConvert.packageName, ContextConstants.MapObjectConvert.className)); - final AutoMapperMetadata autoMapperMetadata = new AutoMapMapperMetadata(); - autoMapperMetadata.setTargetClassName(target); - autoMapperMetadata.setSourceClassName(source); + final AutoMapperMetadata autoMapperMetadata = new AutoMapMapperMetadata(source, target); autoMapperMetadata.setUsesClassNameList(uses); autoMapperMetadata.setSuperClass( ClassName.get(ContextConstants.BaseMapMapper.packageName, ContextConstants.BaseMapMapper.className)); @@ -364,36 +372,55 @@ public class AutoMapperProcessor extends AbstractProcessor { false); } - private void loadMapperConfig(MapperConfig mapperConfig) { - if (mapperConfig == null) { + private void loadMapperConfig(MapperConfigGem mapperConfigGem) { + if (mapperConfigGem == null || !mapperConfigGem.isValid()) { return; } - AutoMapperProperties.setUnmappedSourcePolicy(mapperConfig.unmappedSourcePolicy()); - AutoMapperProperties.setUnmappedTargetPolicy(mapperConfig.unmappedTargetPolicy()); - AutoMapperProperties.setNullValueMappingStrategy(mapperConfig.nullValueMappingStrategy()); - AutoMapperProperties.setNullValuePropertyMappingStrategy(mapperConfig.nullValuePropertyMappingStrategy()); - AutoMapperProperties.setBuildMethod(mapperConfig.builder().buildMethod()); - AutoMapperProperties.setDisableBuilder(mapperConfig.builder().disableBuilder()); - if (StrUtil.isNotEmpty(mapperConfig.mapperPackage())) { - AutoMapperProperties.setMapperPackage(mapperConfig.mapperPackage()); + if (mapperConfigGem.mapperPackage().hasValue()) { + AutoMapperProperties.setMapperPackage(mapperConfigGem.mapperPackage().get()); } - if (StrUtil.isNotEmpty(mapperConfig.adapterPackage())) { - AutoMapperProperties.setAdapterPackage(mapperConfig.adapterPackage()); + AutoMapperProperties.setUnmappedSourcePolicy(mapperConfigGem.unmappedSourcePolicy().getValue()); + // 重定义 MapStruct 中 unmappedTargetPolicy 的默认值 WARN ---> IGNORE + AutoMapperProperties.setUnmappedTargetPolicy(mapperConfigGem.unmappedTargetPolicy().getValue()); + AutoMapperProperties.setTypeConversionPolicy(mapperConfigGem.typeConversionPolicy().getValue()); + AutoMapperProperties.setCollectionMappingStrategy(mapperConfigGem.collectionMappingStrategy().getValue()); + AutoMapperProperties.setNullValueMappingStrategy(mapperConfigGem.nullValueMappingStrategy().getValue()); + AutoMapperProperties.setNullValueIterableMappingStrategy( + mapperConfigGem.nullValueIterableMappingStrategy().getValue()); + AutoMapperProperties.setNullValueMapMappingStrategy(mapperConfigGem.nullValueMapMappingStrategy().getValue()); + AutoMapperProperties.setNullValuePropertyMappingStrategy( + mapperConfigGem.nullValuePropertyMappingStrategy().getValue()); + AutoMapperProperties.setNullValueCheckStrategy(mapperConfigGem.nullValueCheckStrategy().getValue()); + if (mapperConfigGem.mappingControl().hasValue()) { + AutoMapperProperties.setMappingControl(transToClassName(mapperConfigGem.mappingControl().get())); } - if (StrUtil.isNotEmpty(mapperConfig.adapterClassName())) { - AutoMapperProperties.setAdapterClassName(mapperConfig.adapterClassName()); + if (mapperConfigGem.unexpectedValueMappingException().hasValue()) { + AutoMapperProperties.setUnexpectedValueMappingException( + transToClassName(mapperConfigGem.unexpectedValueMappingException().get())); } - if (StrUtil.isNotEmpty(mapperConfig.mapAdapterClassName())) { - AutoMapperProperties.setMapAdapterClassName(mapperConfig.mapAdapterClassName()); + AutoMapperProperties.setSuppressTimestampInGenerated(mapperConfigGem.suppressTimestampInGenerated().getValue()); + BuilderGem builderGem = mapperConfigGem.builder().get(); + if (builderGem.buildMethod().hasValue()) { + AutoMapperProperties.setBuildMethod(builderGem.buildMethod().get()); } - if (StrUtil.isNotEmpty(mapperConfig.autoConfigPackage())) { - AutoMapperProperties.setAutoConfigPackage(mapperConfig.autoConfigPackage()); + AutoMapperProperties.setDisableBuilder(builderGem.disableBuilder().get()); + if (mapperConfigGem.adapterPackage().hasValue()) { + AutoMapperProperties.setAdapterPackage(mapperConfigGem.adapterPackage().get()); } - if (StrUtil.isNotEmpty(mapperConfig.autoMapperConfigClassName())) { - AutoMapperProperties.setAutoMapperConfigClassName(mapperConfig.autoMapperConfigClassName()); + if (mapperConfigGem.adapterClassName().hasValue()) { + AutoMapperProperties.setAdapterClassName(mapperConfigGem.adapterClassName().get()); } - if (StrUtil.isNotEmpty(mapperConfig.autoMapMapperConfigClassName())) { - AutoMapperProperties.setAutoMapMapperConfigClassName(mapperConfig.autoMapMapperConfigClassName()); + if (mapperConfigGem.mapAdapterClassName().hasValue()) { + AutoMapperProperties.setMapAdapterClassName(mapperConfigGem.mapAdapterClassName().get()); + } + if (mapperConfigGem.autoConfigPackage().hasValue()) { + AutoMapperProperties.setAutoConfigPackage(mapperConfigGem.autoConfigPackage().get()); + } + if (mapperConfigGem.autoMapperConfigClassName().hasValue()) { + AutoMapperProperties.setAutoMapperConfigClassName(mapperConfigGem.autoMapperConfigClassName().get()); + } + if (mapperConfigGem.autoMapMapperConfigClassName().hasValue()) { + AutoMapperProperties.setAutoMapMapperConfigClassName(mapperConfigGem.autoMapMapperConfigClassName().get()); } } @@ -405,7 +432,7 @@ public class AutoMapperProcessor extends AbstractProcessor { if (CollectionUtils.isNotEmpty(typeElements)) { messager.printMessage(Diagnostic.Kind.NOTE, "The previous Mapper Config Class was read , class name : " + typeElements.get(0)); - loadMapperConfig(typeElements.get(0).getAnnotation(MapperConfig.class)); + loadMapperConfig(MapperConfigGem.instanceOn(typeElements.get(0))); } // annotation --> MapperConfig @@ -415,7 +442,7 @@ public class AutoMapperProcessor extends AbstractProcessor { final Optional mapperConfigOptional = roundEnv.getElementsAnnotatedWith(mapperConfigAnnotation).stream().findFirst(); if (mapperConfigOptional.isPresent()) { - loadMapperConfig(mapperConfigOptional.get().getAnnotation(MapperConfig.class)); + loadMapperConfig(MapperConfigGem.instanceOn(mapperConfigOptional.get())); // record buildCollator.writeTypeElements(Collections.singletonList((TypeElement) mapperConfigOptional.get())); } @@ -426,7 +453,7 @@ public class AutoMapperProcessor extends AbstractProcessor { if (StrUtil.isNotEmpty(mapperConfigClass)) { final TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(mapperConfigClass); if (typeElement != null) { - loadMapperConfig(typeElement.getAnnotation(MapperConfig.class)); + loadMapperConfig(MapperConfigGem.instanceOn(typeElement)); } } @@ -490,8 +517,8 @@ public class AutoMapperProcessor extends AbstractProcessor { boolean defineReverseMapping = CollectionUtils.isNotEmpty(autoMapperMetadata.getFieldReverseMappingList()); final AutoMapperMetadata reverseMapperMetadata = reverseMapper(autoMapperMetadata); if (defineReverseMapping) { - addMapper(reverseMapperMetadata); - } else if (!mapperSet.add(reverseMapperMetadata.mapperName())) { + addMapper(reverseMapperMetadata, true); + } else if (!addMapper(reverseMapperMetadata, false)) { return; } reverseMapperMetadataList.add(reverseMapperMetadata); @@ -552,34 +579,39 @@ public class AutoMapperProcessor extends AbstractProcessor { reverseMapperMetadata.setSuperClass( ClassName.get(ContextConstants.BaseMapper.packageName, ContextConstants.BaseMapper.className)); } - if (CollectionUtils.isNotEmpty(autoMapperMetadata.getFieldReverseMappingList())) { - reverseMapperMetadata.setFieldMappingList(autoMapperMetadata.getFieldReverseMappingList()); - } else { - // 需要继承的属性 - final List fieldMetadataList = - autoMapperMetadata.getFieldMappingList().stream().map(fieldMapping -> { - final AutoMappingMetadata autoMappingMetadata = new AutoMappingMetadata(); - autoMappingMetadata.setSource(fieldMapping.getTarget()); - autoMappingMetadata.setTarget(fieldMapping.getSource()); - return autoMappingMetadata; - }).collect(Collectors.toList()); - reverseMapperMetadata.setFieldMappingList(fieldMetadataList); - } + reverseMapperMetadata.setUnmappedSourcePolicy(autoMapperMetadata.getUnmappedSourcePolicy()); + reverseMapperMetadata.setUnmappedTargetPolicy(autoMapperMetadata.getUnmappedTargetPolicy()); + reverseMapperMetadata.setTypeConversionPolicy(autoMapperMetadata.getTypeConversionPolicy()); + reverseMapperMetadata.setCollectionMappingStrategy(autoMapperMetadata.getCollectionMappingStrategy()); + reverseMapperMetadata.setNullValueMappingStrategy(autoMapperMetadata.getNullValueMappingStrategy()); + reverseMapperMetadata.setNullValueIterableMappingStrategy( + autoMapperMetadata.getNullValueIterableMappingStrategy()); + reverseMapperMetadata.setNullValuePropertyMappingStrategy( + autoMapperMetadata.getNullValuePropertyMappingStrategy()); + reverseMapperMetadata.setNullValueCheckStrategy(autoMapperMetadata.getNullValueCheckStrategy()); + reverseMapperMetadata.setMappingControl(autoMapperMetadata.getMappingControl()); + reverseMapperMetadata.setMapperNameSuffix(autoMapperMetadata.getMapperNameSuffix()); + + List fieldReverseMappingList = autoMapperMetadata.getFieldReverseMappingList(); + if (CollectionUtils.isEmpty(fieldReverseMappingList)) { + // 默认的规则 + Map autoMappingMap = + autoMapperMetadata.getFieldMappingList().stream() + .filter(AutoMappingMetadata::getReverseConvertGenerate) + .map(fieldMapping -> { + final AutoMappingMetadata autoMappingMetadata = new AutoMappingMetadata(); + autoMappingMetadata.setSource(fieldMapping.getTarget()); + autoMappingMetadata.setTarget(fieldMapping.getSource()); + return autoMappingMetadata; + }).collect(Collectors.toMap(AutoMappingMetadata::getTarget, Function.identity(), (a, b) -> a)); + fieldReverseMappingList = new ArrayList<>(autoMappingMap.values()); + } + reverseMapperMetadata.setFieldMappingList(fieldReverseMappingList); return reverseMapperMetadata; } private void writeAutoMapperClassFile(AutoMapperMetadata metadata) { - String mapperPackage = metadata.mapperPackage(); - String mapperClassName = metadata.mapperName(); - try (final Writer writer = processingEnv.getFiler() - .createSourceFile(mapperPackage + "." + mapperClassName) - .openWriter()) { - mapperGenerator.write(metadata, processingEnv, writer); - } catch (IOException e) { - processingEnv.getMessager() - .printMessage(ERROR, - "Error while opening " + metadata.mapperName() + " output file: " + e.getMessage()); - } + mapperGenerator.write(metadata, processingEnv); } private void addAdapterMethod(AutoMapperMetadata metadata) { @@ -599,10 +631,8 @@ public class AutoMapperProcessor extends AbstractProcessor { } private AutoMapperMetadata initAutoMapperMetadata(ClassName source, ClassName target, boolean cycleAvoiding) { - AutoMapperMetadata metadata = new AutoMapperMetadata(); + AutoMapperMetadata metadata = new AutoMapperMetadata(source, target); - metadata.setSourceClassName(source); - metadata.setTargetClassName(target); metadata.setSuperGenerics(new ClassName[] {source, target}); ClassName mapStructConfigClass; if (cycleAvoiding) { @@ -617,26 +647,70 @@ public class AutoMapperProcessor extends AbstractProcessor { } private List buildAutoMapperMetadataByAutoMappers(final Element ele) { - final AutoMappers autoMappers = ele.getAnnotation(AutoMappers.class); - if (autoMappers == null) { + AutoMappersGem autoMappersGem = AutoMappersGem.instanceOn(ele); + if (autoMappersGem == null || !autoMappersGem.isValid()) { return null; } + Set targetClassNames = new HashSet<>(); - return Arrays.stream(autoMappers.value()).filter(autoMapper -> { - ClassName className = transToClassName(autoMapper::target); - if (className == null) { - return false; - } - return targetClassNames.add(className.reflectionName()); - }).map(autoMapper -> buildAutoMapperMetadata(autoMapper, ele)).collect(Collectors.toList()); + + return autoMappersGem.value().getValue().stream().filter(autoMapperGem -> { + if (autoMapperGem == null || !autoMapperGem.isValid()) { + return false; + } + TypeMirror target = autoMapperGem.target().getValue(); + return targetClassNames.add(target.toString()); + }).map(autoMapperGem -> buildAutoMapperMetadata(autoMapperGem, ele)) + .collect(Collectors.toList()); } private AutoMapperMetadata buildAutoMapperMetadata(final Element ele) { - AutoMapper autoMapperAnnotation = ele.getAnnotation(AutoMapper.class); - if (autoMapperAnnotation == null) { + AutoMapperGem autoMapperGem = AutoMapperGem.instanceOn(ele); + if (autoMapperGem == null || !autoMapperGem.isValid()) { return null; } - return buildAutoMapperMetadata(autoMapperAnnotation, ele); + + return buildAutoMapperMetadata(autoMapperGem, ele); + } + + private List matchTargetFieldMapping(List autoMappingMetadataList, + ClassName target) { + // 先删除非当面目标类或父类的 + autoMappingMetadataList.removeIf(mappingMetadata -> !isTargetFieldMapping(target, mappingMetadata)); + // 适配目标属性同时配置了目标类及目标类父类的场景 + Map> targetFieldAutoMappingMap = autoMappingMetadataList.stream() + .collect(Collectors.groupingBy(AutoMappingMetadata::getTarget)); + + List result = new ArrayList<>(); + + targetFieldAutoMappingMap.forEach((key, list) -> { + // 只有一个场景 + if (list.size() == 1) { + result.add(list.get(0)); + return; + } + // 有多个时,先匹配目标类型 + ClassName targetClassName = target; + while (targetClassName != null) { + ClassName finalTargetClassName = targetClassName; + List matchedList = list.stream() + .filter(mappingMetadata -> mappingMetadata.getTargetClass() + .reflectionName() + .equals(finalTargetClassName.reflectionName())) + .collect(Collectors.toList()); + if (!matchedList.isEmpty()) { + result.addAll(matchedList); + return; + } + targetClassName = getSuperClass(classNameToTypeElement(targetClassName)) + .map(ClassName::get) + .orElse(null); + } + // 如果没有匹配到,则添加所有的 + result.addAll(list); + }); + + return result; } private boolean isTargetFieldMapping(ClassName target, AutoMappingMetadata mappingMetadata) { @@ -666,29 +740,36 @@ public class AutoMapperProcessor extends AbstractProcessor { return Optional.of((TypeElement) processingEnv.getTypeUtils().asElement(superclass)); } - private AutoMapperMetadata buildAutoMapperMetadata(final AutoMapper autoMapper, final Element ele) { + private AutoMapperMetadata buildAutoMapperMetadata(final AutoMapperGem autoMapperGem, final Element ele) { ClassName source = ClassName.get((TypeElement) ele); - ClassName target = transToClassName(autoMapper::target); + ClassName target = (ClassName) ClassName.get(autoMapperGem.target().getValue()); if (target == null) { return null; } - List uses = transToClassNameList(autoMapper::uses); - final List importsClassNameList = transToClassNameList(autoMapper::imports); - List autoMappingMetadataList = buildFieldMappingMetadata((TypeElement) ele); - autoMappingMetadataList.removeIf(mappingMetadata -> !isTargetFieldMapping(target, mappingMetadata)); - List reverseMappingMetadataList = buildFieldReverseMappingMetadata((TypeElement) ele); - reverseMappingMetadataList.removeIf(mappingMetadata -> !isTargetFieldMapping(target, mappingMetadata)); + List autoMappingMetadataList = + matchTargetFieldMapping(buildFieldMappingMetadata((TypeElement) ele), target); - AutoMapperMetadata metadata = initAutoMapperMetadata(source, target, autoMapper.cycleAvoiding()); + List reverseMappingMetadataList = + matchTargetFieldMapping(buildFieldReverseMappingMetadata((TypeElement) ele), target); + + AutoMapperMetadata metadata = initAutoMapperMetadata(source, target, autoMapperGem.cycleAvoiding().get()); + + List usesClassNameList = transToClassNameList(autoMapperGem.uses().get()); + List useEnumClassNameList = transToClassNameList(autoMapperGem.useEnums().get()).stream() + .map(enumClass -> ClassName.get(MapperUtils.getMapperPackage(enumClass.packageName()), + MapperUtils.getEnumMapperClassName(enumClass.simpleName()))) + .collect(Collectors.toList()); - metadata.setUsesClassNameList(uses); - metadata.setImportsClassNameList(importsClassNameList); + usesClassNameList.addAll(useEnumClassNameList); + + metadata.setUsesClassNameList(usesClassNameList); + metadata.setImportsClassNameList(transToClassNameList(autoMapperGem.imports().get())); metadata.setFieldMappingList(autoMappingMetadataList); metadata.setFieldReverseMappingList(reverseMappingMetadataList); - metadata.setConvertGenerate(autoMapper.convertGenerate()); - metadata.setReverseConvertGenerate(autoMapper.reverseConvertGenerate()); - metadata.setCycleAvoiding(autoMapper.cycleAvoiding()); + metadata.setConvertGenerate(autoMapperGem.convertGenerate().get()); + metadata.setReverseConvertGenerate(autoMapperGem.reverseConvertGenerate().get()); + metadata.setCycleAvoiding(autoMapperGem.cycleAvoiding().get()); if (metadata.isCycleAvoiding()) { metadata.setSuperClass(ClassName.get(ContextConstants.BaseCycleAvoidingMapper.packageName, ContextConstants.BaseCycleAvoidingMapper.className)); @@ -696,8 +777,21 @@ public class AutoMapperProcessor extends AbstractProcessor { metadata.setSuperClass( ClassName.get(ContextConstants.BaseMapper.packageName, ContextConstants.BaseMapper.className)); } + metadata.setUnmappedSourcePolicy(autoMapperGem.unmappedSourcePolicy().getValue()); + metadata.setUnmappedTargetPolicy(autoMapperGem.unmappedTargetPolicy().getValue()); + metadata.setTypeConversionPolicy(autoMapperGem.typeConversionPolicy().getValue()); + metadata.setCollectionMappingStrategy(autoMapperGem.collectionMappingStrategy().getValue()); + metadata.setNullValueMappingStrategy(autoMapperGem.nullValueMappingStrategy().getValue()); + metadata.setNullValueIterableMappingStrategy(autoMapperGem.nullValueIterableMappingStrategy().getValue()); + metadata.setNullValuePropertyMappingStrategy(autoMapperGem.nullValuePropertyMappingStrategy().getValue()); + metadata.setNullValueCheckStrategy(autoMapperGem.nullValueCheckStrategy().getValue()); + metadata.setMappingControl(transToClassName(autoMapperGem.mappingControl().getValue())); + if (StrUtil.isNotEmpty(autoMapperGem.mapperName().getValue())) { + metadata.setMapperName(autoMapperGem.mapperName().getValue()); + } + metadata.setMapperNameSuffix(autoMapperGem.mapperNameSuffix().getValue()); - addMapper(metadata); + addMapper(metadata, true); return metadata; } @@ -711,15 +805,13 @@ public class AutoMapperProcessor extends AbstractProcessor { if (field.getKind() != ElementKind.FIELD && field.getKind() != ElementKind.METHOD) { continue; } - ReverseAutoMapping reverseAutoMapping = field.getAnnotation(ReverseAutoMapping.class); - if (reverseAutoMapping != null) { - list.add(buildAutoMappingMetadata(reverseAutoMapping, field)); + ReverseAutoMappingGem reverseAutoMappingGem = ReverseAutoMappingGem.instanceOn(field); + if (reverseAutoMappingGem != null && reverseAutoMappingGem.isValid()) { + list.add(buildAutoMappingMetadata(reverseAutoMappingGem, field)); } - ReverseAutoMappings reverseAutoMappings = field.getAnnotation(ReverseAutoMappings.class); - if (reverseAutoMappings != null) { - for (ReverseAutoMapping mapping : reverseAutoMappings.value()) { - list.add(buildAutoMappingMetadata(mapping, field)); - } + ReverseAutoMappingsGem reverseAutoMappingsGem = ReverseAutoMappingsGem.instanceOn(field); + if (reverseAutoMappingsGem != null && reverseAutoMappingsGem.isValid()) { + reverseAutoMappingsGem.value().get().forEach(a -> buildAutoMappingMetadata(a, field)); } } @@ -730,44 +822,57 @@ public class AutoMapperProcessor extends AbstractProcessor { return list; } - private AutoMappingMetadata buildAutoMappingMetadata(ReverseAutoMapping reverseAutoMapping, Element ele) { - ClassName targetClass = transToClassName(reverseAutoMapping::targetClass); + private AutoMappingMetadata buildAutoMappingMetadata(ReverseAutoMappingGem reverseAutoMappingGem, Element ele) { + ClassName targetClass = transToClassName(reverseAutoMappingGem.targetClass().get()); if (targetClass == null) { return null; } AutoMappingMetadata metadata = new AutoMappingMetadata(); - if (StrUtil.isNotEmpty(reverseAutoMapping.source())) { - metadata.setSource(reverseAutoMapping.source()); + if (StrUtil.isNotEmpty(reverseAutoMappingGem.source().get())) { + metadata.setSource(reverseAutoMappingGem.source().get()); } else { metadata.setSource(ele.getSimpleName().toString()); } - if (StrUtil.isNotEmpty(reverseAutoMapping.target())) { - metadata.setTarget(reverseAutoMapping.target()); + if (StrUtil.isNotEmpty(reverseAutoMappingGem.target().get())) { + metadata.setTarget(reverseAutoMappingGem.target().get()); } else { metadata.setTarget(ele.getSimpleName().toString()); } metadata.setTargetClass(targetClass); - metadata.setDefaultValue(reverseAutoMapping.defaultValue()); - metadata.setIgnore(reverseAutoMapping.ignore()); - metadata.setExpression(reverseAutoMapping.expression()); - metadata.setDefaultExpression(reverseAutoMapping.defaultExpression()); - metadata.setConditionExpression(reverseAutoMapping.conditionExpression()); - metadata.setDateFormat(reverseAutoMapping.dateFormat()); - metadata.setNumberFormat(reverseAutoMapping.numberFormat()); - metadata.setQualifiedByName(reverseAutoMapping.qualifiedByName()); - metadata.setConditionQualifiedByName(reverseAutoMapping.conditionQualifiedByName()); - metadata.setDependsOn(reverseAutoMapping.dependsOn()); + metadata.setDefaultValue(reverseAutoMappingGem.defaultValue().getValue()); + metadata.setIgnore(reverseAutoMappingGem.ignore().getValue()); + metadata.setExpression(reverseAutoMappingGem.expression().getValue()); + metadata.setDefaultExpression(reverseAutoMappingGem.defaultExpression().getValue()); + metadata.setConditionExpression(reverseAutoMappingGem.conditionExpression().getValue()); + metadata.setDateFormat(reverseAutoMappingGem.dateFormat().getValue()); + metadata.setNumberFormat(reverseAutoMappingGem.numberFormat().getValue()); + metadata.setQualifiedByName(reverseAutoMappingGem.qualifiedByName().getValue()); + metadata.setConditionQualifiedByName(reverseAutoMappingGem.conditionQualifiedByName().getValue()); + metadata.setDependsOn(reverseAutoMappingGem.dependsOn().getValue()); + metadata.setConstant(reverseAutoMappingGem.constant().getValue()); + metadata.setQualifiedBy(transToClassNameList(reverseAutoMappingGem.qualifiedBy().getValue())); + metadata.setNullValueCheckStrategy(reverseAutoMappingGem.nullValueCheckStrategy().getValue()); + metadata.setNullValuePropertyMappingStrategy( + reverseAutoMappingGem.nullValuePropertyMappingStrategy().getValue()); + metadata.setMappingControl(transToClassName(reverseAutoMappingGem.mappingControl().getValue())); + return metadata; } - private void addMapper(AutoMapperMetadata metadata) { - if (!mapperSet.add(metadata.mapperName())) { - throw new DuplicateMapperException("An exception occurred to generate " + metadata.mapperName() + - ", check the mapping configuration for " + - metadata.getSourceClassName().reflectionName() + " or " + - metadata.getTargetClassName().reflectionName()); + private boolean addMapper(AutoMapperMetadata metadata, boolean throwsException) { + boolean addSuccess = mapperSet.add( + metadata.getSourceClassName().reflectionName() + "To" + metadata.getTargetClassName().reflectionName()); + if (throwsException) { + + if (!addSuccess) { + throw new DuplicateMapperException("An exception occurred to generate " + metadata.mapperName() + + ", check the mapping configuration for " + + metadata.getSourceClassName().reflectionName() + " or " + + metadata.getTargetClassName().reflectionName()); + } } + return addSuccess; } private List buildFieldMappingMetadata(final TypeElement autoMapperEle) { @@ -781,15 +886,13 @@ public class AutoMapperProcessor extends AbstractProcessor { if (ele.getKind() != ElementKind.FIELD && ele.getKind() != ElementKind.METHOD) { continue; } - AutoMapping autoMapping = ele.getAnnotation(AutoMapping.class); - if (autoMapping != null) { - list.add(buildAutoMappingMetadata(autoMapping, ele)); + AutoMappingGem autoMappingGem = AutoMappingGem.instanceOn(ele); + if (autoMappingGem != null && autoMappingGem.isValid()) { + list.add(buildAutoMappingMetadata(autoMappingGem, ele)); } - final AutoMappings autoMappings = ele.getAnnotation(AutoMappings.class); - if (autoMappings != null) { - for (AutoMapping autoMappingEle : autoMappings.value()) { - list.add(buildAutoMappingMetadata(autoMappingEle, ele)); - } + AutoMappingsGem autoMappingsGem = AutoMappingsGem.instanceOn(ele); + if (autoMappingsGem != null && autoMappingsGem.isValid()) { + autoMappingsGem.value().get().forEach(a -> list.add(buildAutoMappingMetadata(a, ele))); } } @@ -800,8 +903,8 @@ public class AutoMapperProcessor extends AbstractProcessor { return list; } - private AutoMappingMetadata buildAutoMappingMetadata(AutoMapping autoMapping, Element ele) { - ClassName targetClass = transToClassName(autoMapping::targetClass); + private AutoMappingMetadata buildAutoMappingMetadata(AutoMappingGem autoMappingGem, Element ele) { + ClassName targetClass = transToClassName(autoMappingGem.targetClass().get()); if (targetClass == null) { return null; } @@ -813,27 +916,33 @@ public class AutoMapperProcessor extends AbstractProcessor { elementName = ObjectUtils.defaultIfNull(StrUtil.getGeneralField(elementName), elementName); } - if (StrUtil.isNotEmpty(autoMapping.source())) { - metadata.setSource(autoMapping.source()); + if (StrUtil.isNotEmpty(autoMappingGem.source().get())) { + metadata.setSource(autoMappingGem.source().get()); } else { metadata.setSource(elementName); } - if (StrUtil.isNotEmpty(autoMapping.target())) { - metadata.setTarget(autoMapping.target()); + if (StrUtil.isNotEmpty(autoMappingGem.target().get())) { + metadata.setTarget(autoMappingGem.target().get()); } else { metadata.setTarget(elementName); } metadata.setTargetClass(targetClass); - metadata.setDefaultValue(autoMapping.defaultValue()); - metadata.setIgnore(autoMapping.ignore()); - metadata.setExpression(autoMapping.expression()); - metadata.setDefaultExpression(autoMapping.defaultExpression()); - metadata.setConditionExpression(autoMapping.conditionExpression()); - metadata.setDateFormat(autoMapping.dateFormat()); - metadata.setNumberFormat(autoMapping.numberFormat()); - metadata.setQualifiedByName(autoMapping.qualifiedByName()); - metadata.setConditionQualifiedByName(autoMapping.conditionQualifiedByName()); - metadata.setDependsOn(autoMapping.dependsOn()); + metadata.setReverseConvertGenerate(autoMappingGem.reverseConvertGenerate().get()); + metadata.setDefaultValue(autoMappingGem.defaultValue().getValue()); + metadata.setIgnore(autoMappingGem.ignore().getValue()); + metadata.setExpression(autoMappingGem.expression().getValue()); + metadata.setDefaultExpression(autoMappingGem.defaultExpression().getValue()); + metadata.setConditionExpression(autoMappingGem.conditionExpression().getValue()); + metadata.setDateFormat(autoMappingGem.dateFormat().getValue()); + metadata.setNumberFormat(autoMappingGem.numberFormat().getValue()); + metadata.setQualifiedByName(autoMappingGem.qualifiedByName().getValue()); + metadata.setConditionQualifiedByName(autoMappingGem.conditionQualifiedByName().getValue()); + metadata.setDependsOn(autoMappingGem.dependsOn().getValue()); + metadata.setConstant(autoMappingGem.constant().getValue()); + metadata.setQualifiedBy(transToClassNameList(autoMappingGem.qualifiedBy().getValue())); + metadata.setNullValueCheckStrategy(autoMappingGem.nullValueCheckStrategy().getValue()); + metadata.setNullValuePropertyMappingStrategy(autoMappingGem.nullValuePropertyMappingStrategy().getValue()); + metadata.setMappingControl(transToClassName(autoMappingGem.mappingControl().getValue())); return metadata; } @@ -862,6 +971,22 @@ public class AutoMapperProcessor extends AbstractProcessor { .collect(Collectors.toList()); } + private List transToClassNameList(List typeMirrors) { + if (typeMirrors == null) { + return new ArrayList<>(); + } + return typeMirrors.stream() + .map(this::transToClassName) + .collect(Collectors.toList()); + } + + private ClassName transToClassName(TypeMirror typeMirror) { + if (typeMirror == null) { + return null; + } + return (ClassName) ClassName.get(typeMirror); + } + private TypeElement classNameToTypeElement(ClassName className) { String classNameString = className.toString(); return processingEnv.getElementUtils().getTypeElement(classNameString); diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java index aa98fd124b0e7affdb6d71f7f57b00624bf13696..ddb68fea9fd44b2e955e35415d884847d29af761 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java @@ -1,5 +1,8 @@ package io.github.linpeilie.processor; +import com.squareup.javapoet.ClassName; +import io.github.linpeilie.processor.utils.FileUtils; +import io.github.linpeilie.processor.utils.IncrementMarkUtils; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.NullValuePropertyMappingStrategy; import org.mapstruct.ReportingPolicy; @@ -10,13 +13,29 @@ public class AutoMapperProperties { private static String componentModel = ContextConstants.ComponentModelConfig.defaultComponentModel; - private static ReportingPolicy unmappedSourcePolicy = ReportingPolicy.IGNORE; + private static String unmappedSourcePolicy; - private static ReportingPolicy unmappedTargetPolicy = ReportingPolicy.IGNORE; + private static String unmappedTargetPolicy; - private static NullValueMappingStrategy nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL; + private static String typeConversionPolicy; - private static NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_NULL; + private static String collectionMappingStrategy; + + private static String nullValueMappingStrategy; + + private static String nullValueIterableMappingStrategy; + + private static String nullValueMapMappingStrategy; + + private static String nullValuePropertyMappingStrategy; + + private static String nullValueCheckStrategy; + + private static ClassName mappingControl; + + private static ClassName unexpectedValueMappingException; + + private static Boolean suppressTimestampInGenerated; private static String buildMethod = "build"; @@ -34,117 +53,154 @@ public class AutoMapperProperties { private static String autoMapMapperConfigClassName = ContextConstants.AutoConfig.autoMapMapperConfigClassName; - /* ******************** getter/setter ******************** */ - - public static String getMapperPackage() { - return mapperPackage; + static { + // load increment mark + Integer mark = IncrementMarkUtils.incrementAndGet(); + adapterClassName = adapterClassName + "$" + mark; + mapAdapterClassName = mapAdapterClassName + "$" + mark; + autoMapperConfigClassName = autoMapperConfigClassName + "$" + mark; + autoMapMapperConfigClassName = autoMapMapperConfigClassName + "$" + mark; } - public static String getAdapterPackage() { - return adapterPackage; + public static String getConfigClassName() { + return autoMapperConfigClassName; } - public static void setAdapterPackage(final String adapterPackage) { - AutoMapperProperties.adapterPackage = adapterPackage; + public static String getMapConfigClassName() { + return autoMapMapperConfigClassName; } - public static String getAdapterClassName() { - return adapterClassName; + public static String getConfigPackage() { + return autoConfigPackage; } public static String getCycleAvoidingAdapterClassName() { return getAdapterClassName() + "ForCycleAvoiding"; } - public static void setAdapterClassName(final String adapterClassName) { - AutoMapperProperties.adapterClassName = adapterClassName; + public static String getCycleAvoidingConfigClassName() { + return getConfigClassName() + "ForCycleAvoiding"; } - public static String getMapAdapterClassName() { - return mapAdapterClassName; + /* ******************** getter/setter ******************** */ + + public static String getMapperPackage() { + return mapperPackage; } - public static void setMapAdapterClassName(final String mapAdapterClassName) { - AutoMapperProperties.mapAdapterClassName = mapAdapterClassName; + public static void setMapperPackage(String mapperPackage) { + AutoMapperProperties.mapperPackage = mapperPackage; } - public static String getConfigPackage() { - return autoConfigPackage; + public static String getComponentModel() { + return componentModel; } - public static void setAutoConfigPackage(String autoConfigPackage) { - AutoMapperProperties.autoConfigPackage = autoConfigPackage; + public static void setComponentModel(String componentModel) { + AutoMapperProperties.componentModel = componentModel; } - public static String getConfigClassName() { - return autoMapperConfigClassName; + public static String getUnmappedSourcePolicy() { + return unmappedSourcePolicy; } - public static String getCycleAvoidingConfigClassName() { - return getConfigClassName() + "ForCycleAvoiding"; + public static void setUnmappedSourcePolicy(String unmappedSourcePolicy) { + AutoMapperProperties.unmappedSourcePolicy = unmappedSourcePolicy; } - public static void setAutoMapperConfigClassName(String autoMapperConfigClassName) { - AutoMapperProperties.autoMapperConfigClassName = autoMapperConfigClassName; + public static String getUnmappedTargetPolicy() { + return unmappedTargetPolicy; } - public static String getMapConfigClassName() { - return autoMapMapperConfigClassName; + public static void setUnmappedTargetPolicy(String unmappedTargetPolicy) { + AutoMapperProperties.unmappedTargetPolicy = unmappedTargetPolicy; } - public static void setAutoMapMapperConfigClassName(String autoMapMapperConfigClassName) { - AutoMapperProperties.autoMapMapperConfigClassName = autoMapMapperConfigClassName; + public static String getTypeConversionPolicy() { + return typeConversionPolicy; } - public static String getComponentModel() { - return componentModel; + public static void setTypeConversionPolicy(String typeConversionPolicy) { + AutoMapperProperties.typeConversionPolicy = typeConversionPolicy; } - public static void setMapperPackage(final String mapperPackage) { - AutoMapperProperties.mapperPackage = mapperPackage; + public static String getCollectionMappingStrategy() { + return collectionMappingStrategy; } - public static void setComponentModel(final String componentModel) { - AutoMapperProperties.componentModel = componentModel; + public static void setCollectionMappingStrategy(String collectionMappingStrategy) { + AutoMapperProperties.collectionMappingStrategy = collectionMappingStrategy; } - public static ReportingPolicy getUnmappedSourcePolicy() { - return unmappedSourcePolicy; + public static String getNullValueMappingStrategy() { + return nullValueMappingStrategy; } - public static void setUnmappedSourcePolicy(final ReportingPolicy unmappedSourcePolicy) { - AutoMapperProperties.unmappedSourcePolicy = unmappedSourcePolicy; + public static void setNullValueMappingStrategy(String nullValueMappingStrategy) { + AutoMapperProperties.nullValueMappingStrategy = nullValueMappingStrategy; } - public static ReportingPolicy getUnmappedTargetPolicy() { - return unmappedTargetPolicy; + public static String getNullValueIterableMappingStrategy() { + return nullValueIterableMappingStrategy; } - public static void setUnmappedTargetPolicy(final ReportingPolicy unmappedTargetPolicy) { - AutoMapperProperties.unmappedTargetPolicy = unmappedTargetPolicy; + public static void setNullValueIterableMappingStrategy(String nullValueIterableMappingStrategy) { + AutoMapperProperties.nullValueIterableMappingStrategy = nullValueIterableMappingStrategy; } - public static NullValueMappingStrategy getNullValueMappingStrategy() { - return nullValueMappingStrategy; + public static String getNullValueMapMappingStrategy() { + return nullValueMapMappingStrategy; } - public static void setNullValueMappingStrategy(NullValueMappingStrategy nullValueMappingStrategy) { - AutoMapperProperties.nullValueMappingStrategy = nullValueMappingStrategy; + public static void setNullValueMapMappingStrategy(String nullValueMapMappingStrategy) { + AutoMapperProperties.nullValueMapMappingStrategy = nullValueMapMappingStrategy; } - public static NullValuePropertyMappingStrategy getNullValuePropertyMappingStrategy() { + public static String getNullValuePropertyMappingStrategy() { return nullValuePropertyMappingStrategy; } - public static void setNullValuePropertyMappingStrategy(NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy) { + public static void setNullValuePropertyMappingStrategy(String nullValuePropertyMappingStrategy) { AutoMapperProperties.nullValuePropertyMappingStrategy = nullValuePropertyMappingStrategy; } + public static String getNullValueCheckStrategy() { + return nullValueCheckStrategy; + } + + public static void setNullValueCheckStrategy(String nullValueCheckStrategy) { + AutoMapperProperties.nullValueCheckStrategy = nullValueCheckStrategy; + } + + public static ClassName getMappingControl() { + return mappingControl; + } + + public static void setMappingControl(ClassName mappingControl) { + AutoMapperProperties.mappingControl = mappingControl; + } + + public static ClassName getUnexpectedValueMappingException() { + return unexpectedValueMappingException; + } + + public static void setUnexpectedValueMappingException(ClassName unexpectedValueMappingException) { + AutoMapperProperties.unexpectedValueMappingException = unexpectedValueMappingException; + } + + public static Boolean getSuppressTimestampInGenerated() { + return suppressTimestampInGenerated; + } + + public static void setSuppressTimestampInGenerated(Boolean suppressTimestampInGenerated) { + AutoMapperProperties.suppressTimestampInGenerated = suppressTimestampInGenerated; + } + public static String getBuildMethod() { return buildMethod; } - public static void setBuildMethod(final String buildMethod) { + public static void setBuildMethod(String buildMethod) { AutoMapperProperties.buildMethod = buildMethod; } @@ -152,7 +208,55 @@ public class AutoMapperProperties { return disableBuilder; } - public static void setDisableBuilder(final boolean disableBuilder) { + public static void setDisableBuilder(boolean disableBuilder) { AutoMapperProperties.disableBuilder = disableBuilder; } + + public static String getAdapterPackage() { + return adapterPackage; + } + + public static void setAdapterPackage(String adapterPackage) { + AutoMapperProperties.adapterPackage = adapterPackage; + } + + public static String getAdapterClassName() { + return adapterClassName; + } + + public static void setAdapterClassName(String adapterClassName) { + AutoMapperProperties.adapterClassName = adapterClassName; + } + + public static String getMapAdapterClassName() { + return mapAdapterClassName; + } + + public static void setMapAdapterClassName(String mapAdapterClassName) { + AutoMapperProperties.mapAdapterClassName = mapAdapterClassName; + } + + public static String getAutoConfigPackage() { + return autoConfigPackage; + } + + public static void setAutoConfigPackage(String autoConfigPackage) { + AutoMapperProperties.autoConfigPackage = autoConfigPackage; + } + + public static String getAutoMapperConfigClassName() { + return autoMapperConfigClassName; + } + + public static void setAutoMapperConfigClassName(String autoMapperConfigClassName) { + AutoMapperProperties.autoMapperConfigClassName = autoMapperConfigClassName; + } + + public static String getAutoMapMapperConfigClassName() { + return autoMapMapperConfigClassName; + } + + public static void setAutoMapMapperConfigClassName(String autoMapMapperConfigClassName) { + AutoMapperProperties.autoMapMapperConfigClassName = autoMapMapperConfigClassName; + } } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/BuildCollator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/BuildCollator.java index 03c0cb52dc4bad4a3675cd5dffc141dfe0b367d8..8f2f222d8833f8c28b126b8ac4b6d587fffc1a8a 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/BuildCollator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/BuildCollator.java @@ -1,5 +1,7 @@ package io.github.linpeilie.processor; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.TypeName; import io.github.linpeilie.processor.utils.FileUtils; import io.github.linpeilie.utils.CollectionUtils; import java.io.File; @@ -101,4 +103,13 @@ public class BuildCollator { write(new HashSet<>(lines)); } + public void appendNonexistentTypes(Collection typeNames) { + List lines = loadRecords(); + typeNames.forEach(ele -> { + String classQualifiedName = ele.reflectionName(); + lines.add(classQualifiedName); + }); + write(new HashSet<>(lines)); + } + } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java index 4c6fcc0b7be2c7ae874ca43c0d0b5a119e932291..7344696cb4873b586c0d69d398ff7f02e0fba36e 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java @@ -1,5 +1,7 @@ package io.github.linpeilie.processor; +import io.github.linpeilie.DefaultMapping; +import java.io.File; import org.mapstruct.MappingConstants; /** @@ -37,6 +39,10 @@ public interface ContextConstants { String className = "Mapper"; } + interface AutoMapping { + String qualifiedClassName = "io.github.linpeilie.annotations.AutoMapping"; + } + interface AutoMapper { String qualifiedClassName = "io.github.linpeilie.annotations.AutoMapper"; } @@ -92,6 +98,11 @@ public interface ContextConstants { String autoMappers = "autoMappers"; String autoMapMappers = "autoMapMappers"; String enumMappers = "enumMappers"; + String uses = "uses"; + } + + interface AutoIncrementFile { + String file = System.getProperty("user.home") + File.separator + ".msp" + File.separator + "incrementMark"; } interface Map { @@ -109,4 +120,45 @@ public interface ContextConstants { String className = "DoIgnore"; } + interface MappingControl { + String packageName = "org.mapstruct.control"; + String className = "MappingControl"; + String qualifiedName = packageName + "." + className; + } + + interface NullValueCheckStrategy { + String packageName = "org.mapstruct"; + String className = "NullValueCheckStrategy"; + } + + interface NullValuePropertyMappingStrategy { + String packageName = "org.mapstruct"; + String className = "NullValuePropertyMappingStrategy"; + } + + interface ReportingPolicy { + String packageName = "org.mapstruct"; + String className = "ReportingPolicy"; + } + + interface CollectionMappingStrategy { + String packageName = "org.mapstruct"; + String className = "CollectionMappingStrategy"; + } + + interface NullValueMappingStrategy { + String packageName = "org.mapstruct"; + String className = "NullValueMappingStrategy"; + } + + interface MappingInheritanceStrategy { + String packageName = "org.mapstruct"; + String className = "MappingInheritanceStrategy"; + } + + interface InjectionStrategy { + String packageName = "org.mapstruct"; + String className = "InjectionStrategy"; + } + } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ProcessorOptions.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ProcessorOptions.java index 9451c99011f458d23cc643b79529d14a19f789c4..577cddf00b69eff0143bfbc8b2a11c33184ad44b 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ProcessorOptions.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ProcessorOptions.java @@ -1,11 +1,9 @@ package io.github.linpeilie.processor; +import io.github.linpeilie.utils.StrUtil; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; -import org.mapstruct.NullValueMappingStrategy; -import org.mapstruct.NullValuePropertyMappingStrategy; -import org.mapstruct.ReportingPolicy; public class ProcessorOptions { @@ -19,10 +17,22 @@ public class ProcessorOptions { public static final String UNMAPPED_TARGET_POLICY = "mapstruct.plus.unmappedTargetPolicy"; + public static final String TYPE_CONVERSION_POLICY = "mapstruct.plus.typeConversionPolicy"; + + public static final String COLLECTION_MAPPING_STRATEGY = "mapstruct.plus.collectionMappingStrategy"; + public static final String NULL_VALUE_MAPPING_STRATEGY = "mapstruct.plus.nullValueMappingStrategy"; + public static final String NULL_VALUE_ITERABLE_MAPPING_STRATEGY = "mapstruct.plus.nullValueIterableMappingStrategy"; + + public static final String NULL_VALUE_MAP_MAPPING_STRATEGY = "mapstruct.plus.nullValueMapMappingStrategy"; + public static final String NULL_VALUE_PROPERTY_MAPPING_STRATEGY = "mapstruct.plus.nullValuePropertyMappingStrategy"; + public static final String NULL_VALUE_CHECK_STRATEGY = "mapstruct.plus.nullValueCheckStrategy"; + + public static final String SUPPRESS_TIMESTAMP_IN_GENERATED = "mapstruct.plus.suppressTimestampInGenerated"; + public static final String BUILDER_BUILD_METHOD = "mapstruct.plus.builder.buildMethod"; public static final String BUILDER_DISABLE_BUILDER = "mapstruct.plus.builder.disableBuilder"; @@ -45,14 +55,20 @@ public class ProcessorOptions { consumerMap.put(DEFAULT_COMPONENT_MODEL, AutoMapperProperties::setComponentModel); consumerMap.put(MAPPER_PACKAGE, AutoMapperProperties::setMapperPackage); - consumerMap.put(UNMAPPED_SOURCE_POLICY, value -> AutoMapperProperties.setUnmappedSourcePolicy(ReportingPolicy.valueOf(value))); - consumerMap.put(UNMAPPED_TARGET_POLICY, value -> AutoMapperProperties.setUnmappedTargetPolicy(ReportingPolicy.valueOf(value))); - consumerMap.put(NULL_VALUE_MAPPING_STRATEGY, - value -> AutoMapperProperties.setNullValueMappingStrategy(NullValueMappingStrategy.valueOf(value))); - consumerMap.put(NULL_VALUE_PROPERTY_MAPPING_STRATEGY, - value -> AutoMapperProperties.setNullValuePropertyMappingStrategy( - NullValuePropertyMappingStrategy.valueOf(value) - )); + consumerMap.put(UNMAPPED_SOURCE_POLICY, AutoMapperProperties::setUnmappedSourcePolicy); + consumerMap.put(UNMAPPED_TARGET_POLICY, AutoMapperProperties::setUnmappedTargetPolicy); + consumerMap.put(TYPE_CONVERSION_POLICY, AutoMapperProperties::setTypeConversionPolicy); + consumerMap.put(COLLECTION_MAPPING_STRATEGY, AutoMapperProperties::setCollectionMappingStrategy); + consumerMap.put(NULL_VALUE_MAPPING_STRATEGY, AutoMapperProperties::setNullValueMappingStrategy); + consumerMap.put(NULL_VALUE_ITERABLE_MAPPING_STRATEGY, AutoMapperProperties::setNullValueIterableMappingStrategy); + consumerMap.put(NULL_VALUE_MAP_MAPPING_STRATEGY, AutoMapperProperties::setNullValueMapMappingStrategy); + consumerMap.put(NULL_VALUE_PROPERTY_MAPPING_STRATEGY, AutoMapperProperties::setNullValuePropertyMappingStrategy); + consumerMap.put(NULL_VALUE_CHECK_STRATEGY, AutoMapperProperties::setNullValueCheckStrategy); + consumerMap.put(SUPPRESS_TIMESTAMP_IN_GENERATED, value -> { + if (StrUtil.isNotEmpty(value)) { + AutoMapperProperties.setSuppressTimestampInGenerated(Boolean.parseBoolean(value)); + } + }); consumerMap.put(BUILDER_BUILD_METHOD, AutoMapperProperties::setBuildMethod); consumerMap.put(BUILDER_DISABLE_BUILDER, value -> AutoMapperProperties.setDisableBuilder(Boolean.parseBoolean(value))); diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/gem/GemGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/gem/GemGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..d97a5d642bfcf12cb143953f1098a89245da3b7c --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/gem/GemGenerator.java @@ -0,0 +1,22 @@ +package io.github.linpeilie.processor.gem; + +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMappers; +import io.github.linpeilie.annotations.AutoMapping; +import io.github.linpeilie.annotations.AutoMappings; +import io.github.linpeilie.annotations.MapperConfig; +import io.github.linpeilie.annotations.ReverseAutoMapping; +import io.github.linpeilie.annotations.ReverseAutoMappings; +import org.mapstruct.Builder; +import org.mapstruct.tools.gem.GemDefinition; + +@GemDefinition(AutoMapper.class) +@GemDefinition(AutoMappers.class) +@GemDefinition(AutoMapping.class) +@GemDefinition(AutoMappings.class) +@GemDefinition(MapperConfig.class) +@GemDefinition(ReverseAutoMapping.class) +@GemDefinition(ReverseAutoMappings.class) +@GemDefinition(Builder.class) +public class GemGenerator { +} diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java index 2902e4ad863a5920cb7ce4241d9e7555f183c68b..19deb351b0aa4a44b5235945771195f08c90a454 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java @@ -11,15 +11,14 @@ import com.squareup.javapoet.TypeSpec; import io.github.linpeilie.processor.ContextConstants; import io.github.linpeilie.processor.metadata.AutoMapperMetadata; import io.github.linpeilie.processor.metadata.AutoMappingMetadata; -import io.github.linpeilie.utils.ArrayUtil; import io.github.linpeilie.utils.CollectionUtils; -import io.github.linpeilie.utils.StrUtil; import java.io.IOException; -import java.io.UncheckedIOException; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import javax.annotation.processing.ProcessingEnvironment; @@ -27,40 +26,67 @@ import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import static javax.tools.Diagnostic.Kind.ERROR; + public class AutoMapperGenerator { public static final String CONVERT_METHOD_NAME = "convert"; - public void write(AutoMapperMetadata metadata, final ProcessingEnvironment processingEnv, Writer writer) { - try { - JavaFile.builder(metadata.mapperPackage(), createTypeSpec(processingEnv, metadata)).build().writeTo(writer); + private static final Map AUTO_MAPPER_INDEX = new HashMap<>(); + + public void write(AutoMapperMetadata metadata, ProcessingEnvironment processingEnv) { + String mapperPackage = metadata.mapperPackage(); + + /* + 当前处理方式,本地使用 IDEA 开发时,当修改 Source/Target 类时,可能还会出现类名冲突的问题, + 当出现该问题时,需要执行 clean 把之前构建的类清掉。 + */ + String mapperName = metadata.mapperName(); + // 同名类时,增加后缀 + Integer index = AUTO_MAPPER_INDEX.getOrDefault(mapperName, 0); + if (index > 0) { + mapperName = mapperName + "__" + index; + } + AUTO_MAPPER_INDEX.put(metadata.mapperName(), ++index); + + try (final Writer writer = processingEnv.getFiler() + .createSourceFile(mapperPackage + "." + mapperName) + .openWriter()) { + JavaFile.builder(metadata.mapperPackage(), createTypeSpec(processingEnv, metadata, mapperName)) + .build() + .writeTo(writer); } catch (IOException e) { - throw new UncheckedIOException(e); + processingEnv.getMessager() + .printMessage(ERROR, + "Error while opening " + metadata.mapperName() + " output file: " + e.getMessage()); } } - private TypeSpec createTypeSpec(ProcessingEnvironment processingEnv, AutoMapperMetadata metadata) { + private TypeSpec createTypeSpec(ProcessingEnvironment processingEnv, + AutoMapperMetadata metadata, + String mapperName) { ParameterizedTypeName converterName = ParameterizedTypeName.get(metadata.getSuperClass(), metadata.getSuperGenerics()); final ClassName targetClassName = metadata.getTargetClassName(); - TypeSpec.Builder builder = TypeSpec.interfaceBuilder(metadata.mapperName()) + TypeSpec.Builder builder = TypeSpec.interfaceBuilder(mapperName) .addSuperinterface(converterName) .addModifiers(Modifier.PUBLIC) .addAnnotation(buildGeneratedMapperAnnotationSpec(metadata)); - final ParameterSpec source = ParameterSpec.builder(metadata.getSourceClassName(), "source").build(); - final ParameterSpec target = ParameterSpec.builder(targetClassName, "target") + ParameterSpec source = ParameterSpec.builder(metadata.getSourceClassName(), "source").build(); + ParameterSpec target = ParameterSpec.builder(targetClassName, "target") .addAnnotation(AnnotationSpec.builder(ClassName.get("org.mapstruct", "MappingTarget")).build()) .build(); - final ParameterSpec context = + ParameterSpec context = ParameterSpec.builder(ClassName.get("io.github.linpeilie", "CycleAvoidingMappingContext"), "context") .addAnnotation(ClassName.get("org.mapstruct", "Context")) .build(); if (metadata.getFieldMappingList() != null && !metadata.getFieldMappingList().isEmpty()) { builder.addMethod(addConvertMethodSpec( - metadata.isCycleAvoiding() ? CollectionUtils.newArrayList(source, context) : Collections.singletonList(source), + metadata.isCycleAvoiding() ? CollectionUtils.newArrayList(source, context) : Collections.singletonList( + source), metadata.getFieldMappingList(), targetClassName, CONVERT_METHOD_NAME)); @@ -126,46 +152,86 @@ public class AutoMapperGenerator { private List buildMappingAnnotations(final List autoMappingMetadataList) { return autoMappingMetadataList.stream().map(autoMappingMetadata -> { final AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassName.get("org.mapstruct", "Mapping")) - .addMember("target", CodeBlock.builder().add("$S", autoMappingMetadata.getTarget()).build()) - .addMember("ignore", CodeBlock.builder().add(String.valueOf(autoMappingMetadata.isIgnore())).build()); - if (StrUtil.isNotEmpty(autoMappingMetadata.getDateFormat())) { + .addMember("target", CodeBlock.builder().add("$S", autoMappingMetadata.getTarget()).build()); + if (autoMappingMetadata.getIgnore() != null) { + builder.addMember("ignore", + CodeBlock.builder().add(String.valueOf(autoMappingMetadata.getIgnore())).build()); + } + if (autoMappingMetadata.getDateFormat() != null) { builder.addMember("dateFormat", CodeBlock.builder().add("$S", autoMappingMetadata.getDateFormat()).build()); } - if (StrUtil.isNotEmpty(autoMappingMetadata.getNumberFormat())) { + if (autoMappingMetadata.getNumberFormat() != null) { builder.addMember("numberFormat", CodeBlock.builder().add("$S", autoMappingMetadata.getNumberFormat()).build()); } - if (StrUtil.isNotEmpty(autoMappingMetadata.getDefaultValue())) { + if (autoMappingMetadata.getDefaultValue() != null) { builder.addMember("defaultValue", CodeBlock.builder().add("$S", autoMappingMetadata.getDefaultValue()).build()); } - if (StrUtil.isNotEmpty(autoMappingMetadata.getExpression())) { + if (autoMappingMetadata.getExpression() != null) { builder.addMember("expression", CodeBlock.builder().add("$S", autoMappingMetadata.getExpression()).build()); + } else if (autoMappingMetadata.getConstant() != null) { + builder.addMember("constant", CodeBlock.builder().add("$S", autoMappingMetadata.getConstant()).build()); } else { builder.addMember("source", CodeBlock.builder().add("$S", autoMappingMetadata.getSource()).build()); } - if (StrUtil.isNotEmpty(autoMappingMetadata.getDefaultExpression())) { + if (autoMappingMetadata.getDefaultExpression() != null) { builder.addMember("defaultExpression", CodeBlock.builder().add("$S", autoMappingMetadata.getDefaultExpression()).build()); } - if (StrUtil.isNotEmpty(autoMappingMetadata.getConditionExpression())) { + if (autoMappingMetadata.getConditionExpression() != null) { builder.addMember("conditionExpression", CodeBlock.builder().add("$S", autoMappingMetadata.getConditionExpression()).build()); } - if (ArrayUtil.isNotEmpty(autoMappingMetadata.getQualifiedByName())) { - builder.addMember("qualifiedByName", CodeBlock.builder().add("$L", - "{" + ArrayUtil.join(autoMappingMetadata.getQualifiedByName(), ",", "\"", "\"") + "}").build()); + if (autoMappingMetadata.getQualifiedByName() != null) { + builder.addMember("qualifiedByName", CodeBlock.builder() + .add("$L", + "{" + CollectionUtils.join(autoMappingMetadata.getQualifiedByName(), ",", "\"", "\"") + "}") + .build()); } - if (ArrayUtil.isNotEmpty(autoMappingMetadata.getConditionQualifiedByName())) { - builder.addMember("conditionQualifiedByName", CodeBlock.builder().add("$L", - "{" + ArrayUtil.join(autoMappingMetadata.getConditionQualifiedByName(), ",", "\"", "\"") + "}").build()); + if (autoMappingMetadata.getConditionQualifiedByName() != null) { + builder.addMember("conditionQualifiedByName", CodeBlock.builder() + .add("$L", + "{" + CollectionUtils.join(autoMappingMetadata.getConditionQualifiedByName(), ",", "\"", "\"") + + "}") + .build()); } - if (ArrayUtil.isNotEmpty(autoMappingMetadata.getDependsOn())) { + if (autoMappingMetadata.getDependsOn() != null) { builder.addMember("dependsOn", CodeBlock.builder().add("$L", - "{" + ArrayUtil.join(autoMappingMetadata.getDependsOn(), ",", "\"", "\"") + "}").build()); + "{" + CollectionUtils.join(autoMappingMetadata.getDependsOn(), ",", "\"", "\"") + "}").build()); + } + if (CollectionUtils.isNotEmpty(autoMappingMetadata.getQualifiedBy())) { + CodeBlock.Builder qualifiedCodeBlockBuilder = CodeBlock.builder().add("{"); + for (int i = 0; i < autoMappingMetadata.getQualifiedBy().size(); i++) { + qualifiedCodeBlockBuilder.add("$T.class", autoMappingMetadata.getQualifiedBy().get(i)); + if (i != autoMappingMetadata.getQualifiedBy().size() - 1) { + qualifiedCodeBlockBuilder.add(","); + } + } + qualifiedCodeBlockBuilder.add("}"); + builder.addMember("qualifiedBy", qualifiedCodeBlockBuilder.build()); + } + if (autoMappingMetadata.getNullValueCheckStrategy() != null) { + CodeBlock nullValueCheckStrategyCodeBlock = CodeBlock.builder() + .add("$T.$L", ClassName.get(ContextConstants.NullValueCheckStrategy.packageName, + ContextConstants.NullValueCheckStrategy.className), + autoMappingMetadata.getNullValueCheckStrategy()).build(); + builder.addMember("nullValueCheckStrategy", nullValueCheckStrategyCodeBlock); } + if (autoMappingMetadata.getNullValuePropertyMappingStrategy() != null) { + CodeBlock nullValuePropertyMappingStrategy = CodeBlock.builder() + .add("$T.$L", ClassName.get(ContextConstants.NullValuePropertyMappingStrategy.packageName, + ContextConstants.NullValuePropertyMappingStrategy.className), + autoMappingMetadata.getNullValuePropertyMappingStrategy()).build(); + builder.addMember("nullValuePropertyMappingStrategy", nullValuePropertyMappingStrategy); + } + if (autoMappingMetadata.getMappingControl() != null) { + builder.addMember("mappingControl", + CodeBlock.builder().add("$T.class", autoMappingMetadata.getMappingControl()).build()); + } + return builder.build(); }).collect(Collectors.toList()); } @@ -208,6 +274,92 @@ public class AutoMapperGenerator { .addMember("config", configCodeBlock) .addMember("uses", usesCodeBlock) .addMember("imports", importsCodeBlock); + + // unmappedSourcePolicy + if (metadata.getUnmappedSourcePolicy() != null) { + builder.addMember("unmappedSourcePolicy", CodeBlock.builder() + .add("$T.$L", ClassName.get(ContextConstants.ReportingPolicy.packageName, + ContextConstants.ReportingPolicy.className), + metadata.getUnmappedSourcePolicy()) + .build()); + } + + // unmappedTargetPolicy + if (metadata.getUnmappedTargetPolicy() != null) { + builder.addMember("unmappedTargetPolicy", CodeBlock.builder() + .add("$T.$L", + ClassName.get(ContextConstants.ReportingPolicy.packageName, + ContextConstants.ReportingPolicy.className), + metadata.getUnmappedTargetPolicy()) + .build()); + } + + // typeConversionPolicy + if (metadata.getTypeConversionPolicy() != null) { + builder.addMember("typeConversionPolicy", CodeBlock.builder() + .add("$T.$L", + ClassName.get(ContextConstants.ReportingPolicy.packageName, + ContextConstants.ReportingPolicy.className), + metadata.getTypeConversionPolicy()) + .build()); + } + + // collectionMappingStrategy + if (metadata.getCollectionMappingStrategy() != null) { + builder.addMember("collectionMappingStrategy", CodeBlock.builder() + .add("$T.$L", + ClassName.get(ContextConstants.CollectionMappingStrategy.packageName, + ContextConstants.CollectionMappingStrategy.className), + metadata.getCollectionMappingStrategy()) + .build()); + } + + // nullValueMappingStrategy + if (metadata.getNullValueMappingStrategy() != null) { + builder.addMember("nullValueMappingStrategy", CodeBlock.builder() + .add("$T.$L", + ClassName.get(ContextConstants.NullValueMappingStrategy.packageName, + ContextConstants.NullValueMappingStrategy.className), + metadata.getNullValueMappingStrategy()) + .build()); + } + + // nullValueIterableMappingStrategy + if (metadata.getNullValueIterableMappingStrategy() != null) { + builder.addMember("nullValueIterableMappingStrategy", CodeBlock.builder() + .add("$T.$L", + ClassName.get(ContextConstants.NullValueMappingStrategy.packageName, + ContextConstants.NullValueMappingStrategy.className), + metadata.getNullValueIterableMappingStrategy()) + .build()); + } + + // nullValuePropertyMappingStrategy + if (metadata.getNullValuePropertyMappingStrategy() != null) { + builder.addMember("nullValuePropertyMappingStrategy", CodeBlock.builder() + .add("$T.$L", + ClassName.get(ContextConstants.NullValuePropertyMappingStrategy.packageName, + ContextConstants.NullValuePropertyMappingStrategy.className), + metadata.getNullValuePropertyMappingStrategy()) + .build()); + } + + // nullValueCheckStrategy + if (metadata.getNullValueCheckStrategy() != null) { + builder.addMember("nullValueCheckStrategy", CodeBlock.builder() + .add("$T.$L", + ClassName.get(ContextConstants.NullValueCheckStrategy.packageName, + ContextConstants.NullValueCheckStrategy.className), + metadata.getNullValueCheckStrategy()) + .build()); + } + + // mappingControl + if (metadata.getMappingControl() != null) { + builder.addMember("mappingControl", + CodeBlock.builder().add("$T.class", metadata.getMappingControl()).build()); + } + return builder.build(); } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/MapperConfigGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/MapperConfigGenerator.java index 8dc5a9a199c328e738f715271cd82268dd050f9c..4601ada33a68a4638edc0274b0f082850b841b08 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/MapperConfigGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/MapperConfigGenerator.java @@ -69,6 +69,22 @@ public class MapperConfigGenerator { builder.addMember("unmappedTargetPolicy", unmappedTargetPolicyCodeBlock); } + // typeConversionPolicy + if (AutoMapperProperties.getTypeConversionPolicy() != null) { + CodeBlock typeConversionCodeBlock = CodeBlock.builder().add("$T.$L", + ClassName.get("org.mapstruct", "ReportingPolicy"), + AutoMapperProperties.getTypeConversionPolicy()).build(); + builder.addMember("typeConversionPolicy", typeConversionCodeBlock); + } + + // collectionMappingStrategy + if (AutoMapperProperties.getCollectionMappingStrategy() != null) { + CodeBlock collectionMappingStrategyCodeBlock = CodeBlock.builder().add("$T.$L", + ClassName.get("org.mapstruct", "CollectionMappingStrategy"), + AutoMapperProperties.getCollectionMappingStrategy()).build(); + builder.addMember("collectionMappingStrategy", collectionMappingStrategyCodeBlock); + } + // nullValueMappingStrategy if (AutoMapperProperties.getNullValueMappingStrategy() != null) { CodeBlock nullValueMappingStrategyCodeBlock = CodeBlock.builder().add("$T.$L", @@ -77,6 +93,22 @@ public class MapperConfigGenerator { builder.addMember("nullValueMappingStrategy", nullValueMappingStrategyCodeBlock); } + // nullValueIterableMappingStrategy + if (AutoMapperProperties.getNullValueIterableMappingStrategy() != null) { + CodeBlock nullValueIterableMappingStrategyCodeBlock = CodeBlock.builder().add("$T.$L", + ClassName.get("org.mapstruct", "NullValueIterableMappingStrategy"), + AutoMapperProperties.getNullValueIterableMappingStrategy()).build(); + builder.addMember("nullValueIterableMappingStrategy", nullValueIterableMappingStrategyCodeBlock); + } + + // nullValueMapMappingStrategy + if (AutoMapperProperties.getNullValueMapMappingStrategy() != null) { + CodeBlock nullValueMapMappingStrategyCodeBlock = CodeBlock.builder().add("$T.$L", + ClassName.get("org.mapstruct", "NullValueMapMappingStrategy"), + AutoMapperProperties.getNullValueMapMappingStrategy()).build(); + builder.addMember("nullValueMapMappingStrategy", nullValueMapMappingStrategyCodeBlock); + } + // nullValuePropertyMappingStrategy if (AutoMapperProperties.getNullValuePropertyMappingStrategy() != null) { CodeBlock nullValuePropertyMappingStrategyCodeBlock = CodeBlock.builder().add("$T.$L", @@ -85,6 +117,34 @@ public class MapperConfigGenerator { builder.addMember("nullValuePropertyMappingStrategy", nullValuePropertyMappingStrategyCodeBlock); } + // nullValueCheckStrategy + if (AutoMapperProperties.getNullValueCheckStrategy() != null) { + CodeBlock nullValueCheckStrategyCodeBlock = CodeBlock.builder().add("$T.$L", + ClassName.get("org.mapstruct", "NullValueCheckStrategy"), + AutoMapperProperties.getNullValueCheckStrategy()).build(); + builder.addMember("nullValueCheckStrategy", nullValueCheckStrategyCodeBlock); + } + + // mappingControl + if (AutoMapperProperties.getMappingControl() != null) { + CodeBlock mappingControlCodeBlock = CodeBlock.builder().add("$T.class", + AutoMapperProperties.getMappingControl()).build(); + builder.addMember("mappingControl", mappingControlCodeBlock); + } + + // unexpectedValueMappingException + if (AutoMapperProperties.getUnexpectedValueMappingException() != null) { + CodeBlock unexpectedValueMappingExceptionCodeBlock = CodeBlock.builder().add("$T.class", + AutoMapperProperties.getUnexpectedValueMappingException()).build(); + builder.addMember("unexpectedValueMappingException", unexpectedValueMappingExceptionCodeBlock); + } + + // suppressTimestampInGenerated + if (AutoMapperProperties.getSuppressTimestampInGenerated() != null) { + builder.addMember("suppressTimestampInGenerated", CodeBlock.builder() + .add(String.valueOf(AutoMapperProperties.getSuppressTimestampInGenerated())).build()); + } + // builder CodeBlock builderCodeBlock = CodeBlock.builder() .add("@$T(buildMethod = $S, disableBuilder = $L)", ClassName.get("org.mapstruct", "Builder"), diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AbstractMapperMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AbstractMapperMetadata.java index 1ef5515a61a44168d08219553ee836600839c3e2..b36a6056807a0dcd3fcd797ec855c27e98ec064d 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AbstractMapperMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AbstractMapperMetadata.java @@ -2,6 +2,7 @@ package io.github.linpeilie.processor.metadata; import com.squareup.javapoet.ClassName; import io.github.linpeilie.processor.AutoMapperProperties; +import io.github.linpeilie.processor.utils.MapperUtils; import io.github.linpeilie.utils.StrUtil; public abstract class AbstractMapperMetadata { @@ -9,8 +10,7 @@ public abstract class AbstractMapperMetadata { protected ClassName sourceClassName; public String mapperPackage() { - return StrUtil.isNotEmpty(AutoMapperProperties.getMapperPackage()) - ? AutoMapperProperties.getMapperPackage() : sourceClassName.packageName(); + return MapperUtils.getMapperPackage(sourceClassName.packageName()); } public abstract String mapperName(); diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AdapterMethodMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AdapterMethodMetadata.java index bd6f9e598c9a7fa78fdfdc43d6974fa905c24ef5..678840657c7e3bb536812e1664affcaad043d17b 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AdapterMethodMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AdapterMethodMetadata.java @@ -1,7 +1,7 @@ package io.github.linpeilie.processor.metadata; import com.squareup.javapoet.ClassName; -import io.github.linpeilie.processor.utils.ClassUtil; +import io.github.linpeilie.utils.ClassUtil; public class AdapterMethodMetadata extends AbstractAdapterMethodMetadata { @@ -22,7 +22,7 @@ public class AdapterMethodMetadata extends AbstractAdapterMethodMetadata { public String getMethodName() { String source = ClassUtil.simplifyQualifiedName(this.source.toString()); source = source.substring(0, 1).toLowerCase() + source.substring(1); - return source + "To" + target.simpleName(); + return source + "To" + ClassUtil.simplifyQualifiedName(this.target.toString()); } public ClassName getTarget() { diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoEnumMapperMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoEnumMapperMetadata.java index e60265056b1d0b5eefa6b857de2a045fa3480709..55e8df4b1aa317c31b5854fa3c95c05c2b1699c5 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoEnumMapperMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoEnumMapperMetadata.java @@ -1,7 +1,7 @@ package io.github.linpeilie.processor.metadata; -import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeName; +import io.github.linpeilie.processor.utils.MapperUtils; public class AutoEnumMapperMetadata extends AbstractMapperMetadata { @@ -27,7 +27,7 @@ public class AutoEnumMapperMetadata extends AbstractMapperMetadata { @Override public String mapperName() { - return sourceClassName.simpleName() + "Mapper"; + return MapperUtils.getEnumMapperClassName(sourceClassName.simpleName()); } public String toEnumMethodName() { diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapMapperMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapMapperMetadata.java index 5438689ed026f61f5acd1d6947aed26957700e55..36a55ab43b9341a255885e0577d8fefaee93002d 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapMapperMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapMapperMetadata.java @@ -1,10 +1,16 @@ package io.github.linpeilie.processor.metadata; +import com.squareup.javapoet.ClassName; import io.github.linpeilie.processor.AutoMapperProperties; import io.github.linpeilie.utils.StrUtil; public class AutoMapMapperMetadata extends AutoMapperMetadata { + public AutoMapMapperMetadata(ClassName sourceClassName, + ClassName targetClassName) { + super(sourceClassName, targetClassName); + } + @Override public String mapperPackage() { return StrUtil.isNotEmpty( diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java index 30ace3e507466b9999ba7bf91db4899958abb7f5..34c65325bf9714e2fc3f3b7cae46992ce1cba6a5 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java @@ -1,14 +1,30 @@ package io.github.linpeilie.processor.metadata; import com.squareup.javapoet.ClassName; +import io.github.linpeilie.processor.utils.MapperUtils; +import io.github.linpeilie.utils.StrUtil; import java.util.List; +import org.mapstruct.NullValueMappingStrategy; +import org.mapstruct.SubclassExhaustiveStrategy; public class AutoMapperMetadata extends AbstractMapperMetadata { + public AutoMapperMetadata(ClassName sourceClassName, ClassName targetClassName) { + this.sourceClassName = sourceClassName; + this.targetClassName = targetClassName; + this.mapperName = MapperUtils.getMapperClassName(sourceClassName.reflectionName(), targetClassName.reflectionName()); + } + + private String mapperName; + + private String mapperNameSuffix; + private ClassName targetClassName; private List usesClassNameList; + private List useEnumClassNameList; + private List importsClassNameList; private List fieldMappingList; @@ -27,8 +43,52 @@ public class AutoMapperMetadata extends AbstractMapperMetadata { private boolean cycleAvoiding; + private String unmappedSourcePolicy; + + private String unmappedTargetPolicy; + + private String typeConversionPolicy; + + private String collectionMappingStrategy; + + private String nullValueMappingStrategy; + + private String nullValueIterableMappingStrategy; + + private NullValueMappingStrategy nullValueMapMappingStrategy; + + private String nullValuePropertyMappingStrategy; + + private String nullValueCheckStrategy; + + private SubclassExhaustiveStrategy subclassExhaustiveStrategy; + + private ClassName mappingControl; + + public String qualifiedMapperName() { + return mapperPackage() + "." + mapperName(); + } + + /*************** getter/setter ***************/ + public String mapperName() { - return sourceClassName.simpleName() + "To" + targetClassName.simpleName() + "Mapper"; + return StrUtil.isNotEmpty(this.mapperNameSuffix) ? this.mapperName + this.mapperNameSuffix : this.mapperName; + } + + public void setMapperName(String mapperName) { + this.mapperName = mapperName; + } + + public String getMapperName() { + return mapperName; + } + + public String getMapperNameSuffix() { + return mapperNameSuffix; + } + + public void setMapperNameSuffix(String mapperNameSuffix) { + this.mapperNameSuffix = mapperNameSuffix; } public ClassName getTargetClassName() { @@ -49,6 +109,14 @@ public class AutoMapperMetadata extends AbstractMapperMetadata { return this; } + public List getUseEnumClassNameList() { + return useEnumClassNameList; + } + + public void setUseEnumClassNameList(List useEnumClassNameList) { + this.useEnumClassNameList = useEnumClassNameList; + } + public List getImportsClassNameList() { return importsClassNameList; } @@ -121,4 +189,92 @@ public class AutoMapperMetadata extends AbstractMapperMetadata { public void setCycleAvoiding(boolean cycleAvoiding) { this.cycleAvoiding = cycleAvoiding; } + + public String getUnmappedSourcePolicy() { + return unmappedSourcePolicy; + } + + public void setUnmappedSourcePolicy(String unmappedSourcePolicy) { + this.unmappedSourcePolicy = unmappedSourcePolicy; + } + + public String getUnmappedTargetPolicy() { + return unmappedTargetPolicy; + } + + public void setUnmappedTargetPolicy(String unmappedTargetPolicy) { + this.unmappedTargetPolicy = unmappedTargetPolicy; + } + + public String getTypeConversionPolicy() { + return typeConversionPolicy; + } + + public void setTypeConversionPolicy(String typeConversionPolicy) { + this.typeConversionPolicy = typeConversionPolicy; + } + + public String getCollectionMappingStrategy() { + return collectionMappingStrategy; + } + + public void setCollectionMappingStrategy(String collectionMappingStrategy) { + this.collectionMappingStrategy = collectionMappingStrategy; + } + + public String getNullValueMappingStrategy() { + return nullValueMappingStrategy; + } + + public void setNullValueMappingStrategy(String nullValueMappingStrategy) { + this.nullValueMappingStrategy = nullValueMappingStrategy; + } + + public String getNullValueIterableMappingStrategy() { + return nullValueIterableMappingStrategy; + } + + public void setNullValueIterableMappingStrategy(String nullValueIterableMappingStrategy) { + this.nullValueIterableMappingStrategy = nullValueIterableMappingStrategy; + } + + public NullValueMappingStrategy getNullValueMapMappingStrategy() { + return nullValueMapMappingStrategy; + } + + public void setNullValueMapMappingStrategy(NullValueMappingStrategy nullValueMapMappingStrategy) { + this.nullValueMapMappingStrategy = nullValueMapMappingStrategy; + } + + public String getNullValuePropertyMappingStrategy() { + return nullValuePropertyMappingStrategy; + } + + public void setNullValuePropertyMappingStrategy(String nullValuePropertyMappingStrategy) { + this.nullValuePropertyMappingStrategy = nullValuePropertyMappingStrategy; + } + + public String getNullValueCheckStrategy() { + return nullValueCheckStrategy; + } + + public void setNullValueCheckStrategy(String nullValueCheckStrategy) { + this.nullValueCheckStrategy = nullValueCheckStrategy; + } + + public SubclassExhaustiveStrategy getSubclassExhaustiveStrategy() { + return subclassExhaustiveStrategy; + } + + public void setSubclassExhaustiveStrategy(SubclassExhaustiveStrategy subclassExhaustiveStrategy) { + this.subclassExhaustiveStrategy = subclassExhaustiveStrategy; + } + + public ClassName getMappingControl() { + return mappingControl; + } + + public void setMappingControl(ClassName mappingControl) { + this.mappingControl = mappingControl; + } } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMappingMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMappingMetadata.java index dbf89448752a2c20daf0d38d88dc1d7966abcc4b..1fb66a5b32c825e20ece426032188fb2658a2b00 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMappingMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMappingMetadata.java @@ -1,34 +1,50 @@ package io.github.linpeilie.processor.metadata; import com.squareup.javapoet.ClassName; +import io.github.linpeilie.processor.ContextConstants; +import java.util.ArrayList; +import java.util.List; public class AutoMappingMetadata { private ClassName targetClass; - private String target = ""; + private boolean reverseConvertGenerate; - private String source = ""; + private String target; - private String dateFormat = ""; + private String source; - private String numberFormat = ""; + private String dateFormat; - private String expression = ""; + private String numberFormat; - private String defaultExpression = ""; + private String expression; - private String conditionExpression = ""; + private String defaultExpression; - private boolean ignore = false; + private String conditionExpression; - private String defaultValue = ""; + private Boolean ignore; - String[] qualifiedByName = {}; + private String defaultValue; - String[] conditionQualifiedByName = {}; + private List qualifiedByName; - String[] dependsOn = {}; + private List conditionQualifiedByName; + + private List dependsOn; + + private String constant; + + private List qualifiedBy; + + private String nullValueCheckStrategy; + + private String nullValuePropertyMappingStrategy; + + private ClassName mappingControl; + /*********** getter/setter ************/ public ClassName getTargetClass() { return targetClass; @@ -38,6 +54,14 @@ public class AutoMappingMetadata { this.targetClass = targetClass; } + public boolean getReverseConvertGenerate() { + return reverseConvertGenerate; + } + + public void setReverseConvertGenerate(boolean reverseConvertGenerate) { + this.reverseConvertGenerate = reverseConvertGenerate; + } + public String getTarget() { return target; } @@ -78,11 +102,7 @@ public class AutoMappingMetadata { this.expression = expression; } - public boolean isIgnore() { - return ignore; - } - - public void setIgnore(final boolean ignore) { + public void setIgnore(final Boolean ignore) { this.ignore = ignore; } @@ -110,27 +130,71 @@ public class AutoMappingMetadata { this.conditionExpression = conditionExpression; } - public String[] getQualifiedByName() { + public String getConstant() { + return constant; + } + + public void setConstant(String constant) { + this.constant = constant; + } + + public List getQualifiedBy() { + return qualifiedBy; + } + + public void setQualifiedBy(List qualifiedBy) { + this.qualifiedBy = qualifiedBy; + } + + public Boolean getIgnore() { + return ignore; + } + + public List getQualifiedByName() { return qualifiedByName; } - public void setQualifiedByName(String[] qualifiedByName) { + public void setQualifiedByName(List qualifiedByName) { this.qualifiedByName = qualifiedByName; } - public String[] getConditionQualifiedByName() { + public List getConditionQualifiedByName() { return conditionQualifiedByName; } - public void setConditionQualifiedByName(String[] conditionQualifiedByName) { + public void setConditionQualifiedByName(List conditionQualifiedByName) { this.conditionQualifiedByName = conditionQualifiedByName; } - public String[] getDependsOn() { + public List getDependsOn() { return dependsOn; } - public void setDependsOn(String[] dependsOn) { + public void setDependsOn(List dependsOn) { this.dependsOn = dependsOn; } + + public String getNullValueCheckStrategy() { + return nullValueCheckStrategy; + } + + public void setNullValueCheckStrategy(String nullValueCheckStrategy) { + this.nullValueCheckStrategy = nullValueCheckStrategy; + } + + public String getNullValuePropertyMappingStrategy() { + return nullValuePropertyMappingStrategy; + } + + public void setNullValuePropertyMappingStrategy(String nullValuePropertyMappingStrategy) { + this.nullValuePropertyMappingStrategy = nullValuePropertyMappingStrategy; + } + + public ClassName getMappingControl() { + return mappingControl; + } + + public void setMappingControl(ClassName mappingControl) { + this.mappingControl = mappingControl; + } } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/IncrementMarkUtils.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/IncrementMarkUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..f3145688bfc2f426a3fbb6db3d3c746a5291d304 --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/IncrementMarkUtils.java @@ -0,0 +1,66 @@ +package io.github.linpeilie.processor.utils; + +import io.github.linpeilie.processor.ContextConstants; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.io.UncheckedIOException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; + +public class IncrementMarkUtils { + + public static Integer incrementAndGet() { + int mark = 0; + RandomAccessFile randomAccessFile = null; + FileChannel channel = null; + FileLock lock = null; + try { + File file = FileUtils.touch(new File(ContextConstants.AutoIncrementFile.file)); + + randomAccessFile = new RandomAccessFile(file, "rw"); + + channel = randomAccessFile.getChannel(); + + // 获取文件锁 + lock = channel.lock(); + + String line = randomAccessFile.readLine(); + if (line != null && !line.isEmpty()) { + mark = Integer.parseInt(line); + mark ++; + } + + randomAccessFile.setLength(0); + randomAccessFile.seek(0); + randomAccessFile.writeBytes(String.valueOf(mark)); + + return mark; + } catch (IOException e) { + throw new UncheckedIOException(e); + } finally { + if (lock != null && lock.isValid()) { + try { + lock.release(); + } catch (IOException e) { + // ignore + } + } + if (channel != null) { + try { + channel.close(); + } catch (IOException e) { + // ignore + } + } + if (randomAccessFile != null) { + try { + randomAccessFile.close(); + } catch (IOException e) { + // ignore + } + } + } + } + +} diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/MapperUtils.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/MapperUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..eaa9e4acc7972546757cca6e8c125c25295bd14c --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/MapperUtils.java @@ -0,0 +1,27 @@ +package io.github.linpeilie.processor.utils; + +import io.github.linpeilie.processor.AutoMapperProperties; +import io.github.linpeilie.utils.StrUtil; + +public class MapperUtils { + + public static String getMapperClassName(String sourceQualifiedClassName, String targetQualifiedClassName) { + String[] sourceQualifiedClassNames = sourceQualifiedClassName.split("\\."); + String[] targetQualifiedClassNames = targetQualifiedClassName.split("\\."); + String mapperClassName = sourceQualifiedClassNames[sourceQualifiedClassNames.length - 1] + + "To" + + targetQualifiedClassNames[targetQualifiedClassNames.length - 1]; + return mapperClassName.substring(0, 1).toUpperCase() + mapperClassName.substring(1) + "Mapper"; + } + + public static String getEnumMapperClassName(String sourceSimpleName) { + return sourceSimpleName + "Mapper"; + } + + public static String getMapperPackage(String sourcePackage) { + return StrUtil.isNotEmpty(AutoMapperProperties.getMapperPackage()) + ? AutoMapperProperties.getMapperPackage() : sourcePackage; + + } + +} diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/DefaultConverterFactory.java b/mapstruct-plus/src/main/java/io/github/linpeilie/DefaultConverterFactory.java index bf2d043bae704914009b8685a210f056fe7f0c86..e7b53dbaf536ff248aca79be43100c0f612c9dd6 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/DefaultConverterFactory.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/DefaultConverterFactory.java @@ -1,32 +1,31 @@ package io.github.linpeilie; -import io.github.linpeilie.annotations.MapperConfig; import java.io.File; import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import org.mapstruct.factory.Mappers; public class DefaultConverterFactory extends AbstractCachedConverterFactory { - private String basePackage; + private static final Map> baseMappers = new HashMap<>(); - public DefaultConverterFactory() { - this(""); - } + private static final Map> baseMapMappers = new HashMap<>(); - public DefaultConverterFactory(final String basePackage) { - this.basePackage = basePackage; - // load mapper package - if (basePackage == null || basePackage.isEmpty()) { - loadBasePackage(); - } + public DefaultConverterFactory() { + loadMappers(); } - private void loadBasePackage() { + private void loadMappers() { final ClassLoader classLoader = this.getClass().getClassLoader(); final Enumeration resources; try { @@ -42,16 +41,56 @@ public class DefaultConverterFactory extends AbstractCachedConverterFactory { } } - classes.stream().filter(clazz -> clazz.isAnnotationPresent(MapperConfig.class)).findFirst().ifPresent(clazz -> { - final MapperConfig mapperConfig = clazz.getAnnotation(MapperConfig.class); - basePackage = mapperConfig.mapperPackage(); + classes.forEach(clazz -> { + // BaseMapper + boolean isBaseMapperImplemented = isInterfaceImplemented(clazz, BaseMapper.class); + if (isBaseMapperImplemented) { + List baseMapperGenericTypes = getInterfaceGenericType(clazz, BaseMapper.class); + if (baseMapperGenericTypes.size() == 2) { + Type source = baseMapperGenericTypes.get(0); + Type target = baseMapperGenericTypes.get(1); + + baseMappers.put(getMapperName(source.getTypeName(), target.getTypeName()), clazz); + } + } + // BaseMapMapper + boolean isBaseMapMapperImplemented = isInterfaceImplemented(clazz, BaseMapMapper.class); + if (isBaseMapMapperImplemented) { + List baseMapMapperGenericTypes = getInterfaceGenericType(clazz, BaseMapMapper.class); + if (baseMapMapperGenericTypes.size() == 1) { + Type source = baseMapMapperGenericTypes.get(0); + baseMapMappers.put(source.getTypeName(), clazz); + } + } }); } + private String getMapperName(String sourceQualifiedName, String targetQualifiedName) { + return sourceQualifiedName.replaceAll("\\.", "_") + "To_" + targetQualifiedName.replaceAll("\\.", "_"); + } + + private boolean isInterfaceImplemented(Class clazz, Class interfaceClass) { + List> interfaces = Arrays.asList(clazz.getInterfaces()); + return interfaces.contains(interfaceClass); + } + + private List getInterfaceGenericType(Class clazz, Class interfaceClass) { + Type[] genericInterfaces = clazz.getGenericInterfaces(); + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericInterface; + if (parameterizedType.getRawType().equals(interfaceClass)) { + return Arrays.asList(parameterizedType.getActualTypeArguments()); + } + } + } + return Collections.emptyList(); + } + private void loadClasses(String root, - final String path, - final List> classes, - final ClassLoader classLoader) { + final String path, + final List> classes, + final ClassLoader classLoader) { final File file = new File(path); if (root == null) { root = file.getPath(); @@ -79,39 +118,23 @@ public class DefaultConverterFactory extends AbstractCachedConverterFactory { } } - private String getMapperClassName(Class source, Class target) { - return source.getSimpleName() + "To" + target.getSimpleName() + "Mapper"; - } - - private String getMapMapperClassName(Class source) { - return "MapTo" + source.getSimpleName() + "Mapper"; - } - - private String getMapperPackage(Class sourceType) { - return basePackage != null && !basePackage.isEmpty() ? basePackage - : sourceType.getPackage().getName(); - } - @Override @SuppressWarnings("unchecked") public BaseMapper findMapper(final Class sourceType, final Class targetType) { - final String mapperClassName = getMapperClassName(sourceType, targetType); - try { - final Class mapperClass = Class.forName(getMapperPackage(sourceType) + "." + mapperClassName); - return (BaseMapper) Mappers.getMapper(mapperClass); - } catch (ClassNotFoundException e) { + String mapperClassName = getMapperName(sourceType.getName(), targetType.getName()); + Class baseMapperClass = baseMappers.get(mapperClassName); + if (baseMapperClass == null) { return null; } + return (BaseMapper) Mappers.getMapper(baseMapperClass); } @Override protected BaseMapMapper findMapMapper(final Class source) { - final String mapperClassName = getMapMapperClassName(source); - try { - final Class mapperClass = Class.forName(getMapperPackage(source) + "." + mapperClassName); - return (BaseMapMapper) Mappers.getMapper(mapperClass); - } catch (ClassNotFoundException e) { + Class mapMapperClass = baseMapMappers.get(source.getName()); + if (mapMapperClass == null) { return null; } + return (BaseMapMapper) Mappers.getMapper(mapMapperClass); } } diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapper.java b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapper.java index fc2b90c41c3d6d2a50c52937f8879d1b2d683e90..6f0dec87aff55b14967d64080f5a9207cb9eb983 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapper.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapper.java @@ -1,9 +1,22 @@ package io.github.linpeilie.annotations; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.mapstruct.BeanMapping; +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.IterableMapping; +import org.mapstruct.MapperConfig; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.NullValueMappingStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.ReportingPolicy; +import org.mapstruct.control.MappingControl; + +import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION; /** * @author linpl @@ -16,6 +29,11 @@ public @interface AutoMapper { Class[] uses() default {}; + /** + * 转换需要依赖的枚举,依赖的枚举,需要被 AutoEnumMapper 所注解 + */ + Class[] useEnums() default {}; + Class[] imports() default {}; /** @@ -25,6 +43,16 @@ public @interface AutoMapper { */ boolean convertGenerate() default true; + /** + * 生成的 Mapper 接口名称 + */ + String mapperName() default ""; + + /** + * 生成的 Mapper 接口名称后缀,生成的反向转换接口同时生效 + */ + String mapperNameSuffix() default ""; + /** * 是否生成反向转换的接口 * @@ -42,4 +70,114 @@ public @interface AutoMapper { */ boolean cycleAvoiding() default false; + /** + * How unmapped properties of the source type of a mapping should be + * reported. The method overrides an unmappedSourcePolicy set in a central + * configuration + * + * @since 1.4.1 + * + * @return The reporting policy for unmapped source properties. + */ + ReportingPolicy unmappedSourcePolicy() default ReportingPolicy.IGNORE; + + /** + * How unmapped properties of the target type of a mapping should be + * reported. The method overrides an unmappedTargetPolicy set in a central + * configuration + * + * @since 1.4.1 + * + * @return The reporting policy for unmapped target properties. + */ + ReportingPolicy unmappedTargetPolicy() default ReportingPolicy.WARN; + + /** + * How lossy (narrowing) conversion, for instance long to integer should be + * reported. The method overrides an typeConversionPolicy set in a central + * configuration + * + * @since 1.4.1 + * + * @return The reporting policy for unmapped target properties. + */ + ReportingPolicy typeConversionPolicy() default ReportingPolicy.IGNORE; + + /** + * The strategy to be applied when propagating the value of collection-typed properties. By default, only JavaBeans + * accessor methods (setters or getters) will be used, but it is also possible to invoke a corresponding adder + * method for each element of the source collection (e.g. {@code orderDto.addOrderLine()}). + *

+ * Any setting given for this attribute will take precedence over {@link org.mapstruct.MapperConfig#collectionMappingStrategy()}, + * if present. + * + * @since 1.4.1 + * + * @return The strategy applied when propagating the value of collection-typed properties. + */ + CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.ACCESSOR_ONLY; + + /** + * The strategy to be applied when {@code null} is passed as source argument value to the methods of this mapper. + * If no strategy is configured, the strategy given via {@link MapperConfig#nullValueMappingStrategy()} will be + * applied, using {@link NullValueMappingStrategy#RETURN_NULL} by default. + * + * @since 1.4.1 + * + * @return The strategy to be applied when {@code null} is passed as source value to the methods of this mapper. + */ + NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; + + /** + * The strategy to be applied when {@code null} is passed as source argument value to an {@link IterableMapping} of + * this mapper. If unset, the strategy set with {@link #nullValueMappingStrategy()} will be applied. If neither + * strategy is configured, the strategy given via {@link MapperConfig#nullValueIterableMappingStrategy()} will be + * applied, using {@link NullValueMappingStrategy#RETURN_NULL} by default. + * + * @since 1.4.1 + * + * @return The strategy to be applied when {@code null} is passed as source value to an {@link IterableMapping} of + * this mapper. + */ + NullValueMappingStrategy nullValueIterableMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; + + + /** + * The strategy to be applied when a source bean property is {@code null} or not present. If no strategy is + * configured, the strategy given via {@link MapperConfig#nullValuePropertyMappingStrategy()} will be applied, + * {@link NullValuePropertyMappingStrategy#SET_TO_NULL} will be used by default. + * + * @since 1.4.1 + * + * @return The strategy to be applied when {@code null} is passed as source property value or the source property + * is not present. + */ + NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() default + NullValuePropertyMappingStrategy.SET_TO_NULL; + + /** + * Determines when to include a null check on the source property value of a bean mapping. + * + * Can be overridden by the one on {@link MapperConfig}, {@link BeanMapping} or {@link Mapping}. + * + * @since 1.4.1 + * + * @return strategy how to do null checking + */ + NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION; + + /** + * Allows detailed control over the mapping process. + * + * @return the mapping control + * + * @since 1.4.1 + * + * @see org.mapstruct.control.DeepClone + * @see org.mapstruct.control.NoComplexMapping + * @see org.mapstruct.control.MappingControl + */ + Class mappingControl() default MappingControl.class; + + } diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapping.java b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapping.java index 1a84fcf8170b17d136bc86632bbf10285f4199ec..873c22e0d2b6c363b705b41817f8be9e76ee1f49 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapping.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/AutoMapping.java @@ -1,12 +1,22 @@ package io.github.linpeilie.annotations; import io.github.linpeilie.DefaultMapping; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.mapstruct.BeanMapping; import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.MapperConfig; import org.mapstruct.Named; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.Qualifier; +import org.mapstruct.control.MappingControl; + +import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION; @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.CLASS) @@ -14,6 +24,13 @@ public @interface AutoMapping { Class targetClass() default DefaultMapping.class; + /** + * 是否生成反向转换的逻辑 + * + * @return true : 生成反向转换的逻辑 false : 不生成反向转换的逻辑 + */ + boolean reverseConvertGenerate() default true; + /** * 来源,默认取当前字段名称 * - 可以是当前类中的属性名 @@ -28,6 +45,11 @@ public @interface AutoMapping { String numberFormat() default ""; + /** + * @since 1.4.1 + */ + String constant() default ""; + String expression() default ""; String defaultExpression() default ""; @@ -42,6 +64,25 @@ public @interface AutoMapping { */ String defaultValue() default ""; + /** + * A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple + * mapping methods (hand written or generated) qualify and thus would result in an 'Ambiguous mapping methods found' + * error. A qualifier is a custom annotation and can be placed on a hand written mapper class or a method. + *

+ * Note that {@link #defaultValue()} usage will also be converted using this qualifier. + * + * qualifier 可以置顶限定符来帮助选择合适的转换方法。qualifier 是一个自定义的注解,可以标注在 mapper 类或者方法上。 + *

+ * Note that {@link #defaultValue()} usage will also be converted using this qualifier. + *

+ * + * @since 1.4.1 + * + * @return the qualifiers + * @see Qualifier + */ + Class[] qualifiedBy() default { }; + /** * String-based form of qualifiers; When looking for a suitable mapping method for a given property, MapStruct will * only consider those methods carrying directly or indirectly (i.e. on the class-level) a {@link Named} annotation @@ -53,9 +94,10 @@ public @interface AutoMapping { *

* Note that {@link #defaultValue()} usage will also be converted using this qualifier. * + * @since 1.4.0 + * * @return One or more qualifier name(s) * @see Named - * @since 1.4.0 */ String[] qualifiedByName() default {}; @@ -72,11 +114,11 @@ public @interface AutoMapping { * number of qualifiers as no custom annotation types are needed. *

* + * @since 1.4.0 * * @return One or more qualifier name(s) * @see #qualifiedByName() * @see Named - * @since 1.4.0 */ String[] conditionQualifiedByName() default {}; @@ -87,9 +129,52 @@ public @interface AutoMapping { *

* An error will be raised in case a cycle in the dependency relationships is detected. * - * @return the dependencies of the mapped property * @since 1.4.0 + * + * @return the dependencies of the mapped property */ String[] dependsOn() default {}; + + /** + * Determines when to include a null check on the source property value of a bean mapping. + * + * Can be overridden by the one on {@link org.mapstruct.MapperConfig}, {@link Mapper} or {@link BeanMapping}. + * + * @since 1.4.1 + * + * @return strategy how to do null checking + */ + NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION; + + /** + * The strategy to be applied when the source property is {@code null} or not present. If no strategy is configured, + * the strategy given via {@link MapperConfig#nullValuePropertyMappingStrategy()}, + * {@link BeanMapping#nullValuePropertyMappingStrategy()} or + * {@link Mapper#nullValuePropertyMappingStrategy()} will be applied. + * + * {@link NullValuePropertyMappingStrategy#SET_TO_NULL} will be used by default. + * + * @since 1.4.1 + * + * @return The strategy to be applied when {@code null} is passed as source property value or the source property + * is not present. + */ + NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() + default NullValuePropertyMappingStrategy.SET_TO_NULL; + + /** + * Allows detailed control over the mapping process. + * + * @return the mapping control + * + * @since 1.4.1 + * + * @see org.mapstruct.control.DeepClone + * @see org.mapstruct.control.NoComplexMapping + * @see org.mapstruct.control.MappingControl + */ + Class mappingControl() default MappingControl.class; + + } diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/MapperConfig.java b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/MapperConfig.java index 9b5cd792527660079380040a1ce392860d641872..0c53bfa7f11f6139d8e4ca45ccada9b86a585202 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/MapperConfig.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/MapperConfig.java @@ -1,13 +1,24 @@ package io.github.linpeilie.annotations; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.mapstruct.BeanMapping; import org.mapstruct.Builder; +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.IterableMapping; +import org.mapstruct.MapMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.NullValuePropertyMappingStrategy; import org.mapstruct.ReportingPolicy; +import org.mapstruct.control.MappingControl; + +import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION; /** * 在一个类或者接口上添加该注释,作为自动生成 Mapper 的配置类。在一个模块中,只能有一个有该注释的类。 @@ -38,18 +49,119 @@ public @interface MapperConfig { */ ReportingPolicy unmappedTargetPolicy() default ReportingPolicy.IGNORE; + /** + * How lossy (narrowing) conversion, for instance: long to integer should be + * reported. + * + * @since 1.4.1 + * + * @return The reporting policy for type conversion. + */ + ReportingPolicy typeConversionPolicy() default ReportingPolicy.IGNORE; + + /** + * The strategy to be applied when propagating the value of collection-typed properties. By default, only JavaBeans + * accessor methods (setters or getters) will be used, but it is also possible to invoke a corresponding adder + * method for each element of the source collection (e.g. {@code orderDto.addOrderLine()}). + * + * @since 1.4.1 + * + * @return The strategy applied when propagating the value of collection-typed properties. + */ + CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.ACCESSOR_ONLY; + /** * 空对象的映射策略,默认返回 null * @return {@link NullValueMappingStrategy} */ NullValueMappingStrategy nullValueMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; + /** + * The strategy to be applied when {@code null} is passed as source argument value to an {@link IterableMapping}. + * If no strategy is configured, the strategy given via {@link #nullValueMappingStrategy()} will be applied, using + * {@link NullValueMappingStrategy#RETURN_NULL} by default. + * + * @since 1.4.1 + * + * @return The strategy to be applied when {@code null} is passed as source value to an {@link IterableMapping}. + */ + NullValueMappingStrategy nullValueIterableMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; + + /** + * The strategy to be applied when {@code null} is passed as source argument value to a {@link MapMapping}. + * If no strategy is configured, the strategy given via {@link #nullValueMappingStrategy()} will be applied, using + * {@link NullValueMappingStrategy#RETURN_NULL} by default. + * + * @since 1.4.1 + * + * @return The strategy to be applied when {@code null} is passed as source value to a {@link MapMapping}. + */ + NullValueMappingStrategy nullValueMapMappingStrategy() default NullValueMappingStrategy.RETURN_NULL; + /** * 当属性值为 null 时应对的策略,默认设置为 null * @return {@link NullValuePropertyMappingStrategy} */ NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() default NullValuePropertyMappingStrategy.SET_TO_NULL; + /** + * Determines when to include a null check on the source property value of a bean mapping. + * + * Can be overridden by the one on {@link Mapper}, {@link BeanMapping} or {@link Mapping}. + * + * @since 1.4.1 + * + * @return strategy how to do null checking + */ + NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION; + + /** + * Allows detailed control over the mapping process. + * + * @return the mapping control + * + * @since 1.4.1 + * + * @see org.mapstruct.control.DeepClone + * @see org.mapstruct.control.NoComplexMapping + * @see org.mapstruct.control.MappingControl + */ + Class mappingControl() default MappingControl.class; + + /** + * Exception that should be thrown by the generated code if no mapping matches for enums. + * If no exception is configured, {@link IllegalArgumentException} will be used by default. + * + *

+ * Note: + *

    + *
  • + * The defined exception should at least have a constructor with a {@link String} parameter. + *
  • + *
  • + * If the defined exception is a checked exception then the enum mapping methods should have that exception + * in the throws clause. + *
  • + *
+ * + * @since 1.4.1 + * + * @return the exception that should be used in the generated code + */ + Class unexpectedValueMappingException() default IllegalArgumentException.class; + + /** + * Flag indicating whether the addition of a time stamp in the {@code @Generated} annotation should be suppressed. + * i.e. not be added. + * + * The method overrides the flag set through an annotation processor option. + * + * @since 1.4.1 + * + * @return whether the addition of a timestamp should be suppressed + */ + boolean suppressTimestampInGenerated() default false; + /** * 构造者模式配置,由于 mapstruct 和 lombok 和 builder 一起使用时,会丢失父类属性,这里默认改为关闭 * @return {@link Builder} diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ReverseAutoMapping.java b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ReverseAutoMapping.java index f913226183cc225d0050fbb09e074bfbab5a85e8..4883055234895ada99ba19d3ceccbc6881a4884a 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ReverseAutoMapping.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ReverseAutoMapping.java @@ -1,12 +1,22 @@ package io.github.linpeilie.annotations; import io.github.linpeilie.DefaultMapping; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.mapstruct.BeanMapping; import org.mapstruct.Condition; +import org.mapstruct.Mapper; +import org.mapstruct.MapperConfig; import org.mapstruct.Named; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.Qualifier; +import org.mapstruct.control.MappingControl; + +import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION; /** * 由目标类生成当前类的配置 @@ -27,33 +37,25 @@ import org.mapstruct.Named; @Retention(RetentionPolicy.CLASS) public @interface ReverseAutoMapping { + Class targetClass() default DefaultMapping.class; /** * 来源,默认取当前字段名称 - *
  • 可以是当前类中的属性名
  • - *
  • 也可以是属性名.属性名,例如:address.city.name
- * 这里的来源,指的是目标类中的字段信息 - * - * @return 目标类中的属性 + * - 可以是当前类中的属性名 + * - 也可以是属性名.属性名,例如:address.city.name + * @return 当前类中的属性 */ String source() default ""; - /** - * 目标属性,默认取当前字段名称 - *
    - *
  • 可以是当前类中的属性名
  • - *
  • 也可以是属性名.属性名,例如:address.city.name
  • - *
- * - * @return 当前类中的属性 - */ String target() default ""; String dateFormat() default ""; String numberFormat() default ""; + String constant() default ""; + String expression() default ""; String defaultExpression() default ""; @@ -64,11 +66,29 @@ public @interface ReverseAutoMapping { /** * 默认值 - * - * @return 当来源属性为null时,所设置的默认值 + * @return 当源属性为null时,设置的默认值 */ String defaultValue() default ""; + /** + * A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple + * mapping methods (hand written or generated) qualify and thus would result in an 'Ambiguous mapping methods found' + * error. A qualifier is a custom annotation and can be placed on a hand written mapper class or a method. + *

+ * Note that {@link #defaultValue()} usage will also be converted using this qualifier. + * + * qualifier 可以置顶限定符来帮助选择合适的转换方法。qualifier 是一个自定义的注解,可以标注在 mapper 类或者方法上。 + *

+ * Note that {@link #defaultValue()} usage will also be converted using this qualifier. + *

+ * + * @since 1.4.1 + * + * @return the qualifiers + * @see Qualifier + */ + Class[] qualifiedBy() default { }; + /** * String-based form of qualifiers; When looking for a suitable mapping method for a given property, MapStruct will * only consider those methods carrying directly or indirectly (i.e. on the class-level) a {@link Named} annotation @@ -80,9 +100,10 @@ public @interface ReverseAutoMapping { *

* Note that {@link #defaultValue()} usage will also be converted using this qualifier. * + * @since 1.4.0 + * * @return One or more qualifier name(s) * @see Named - * @since 1.4.0 */ String[] qualifiedByName() default {}; @@ -99,11 +120,11 @@ public @interface ReverseAutoMapping { * number of qualifiers as no custom annotation types are needed. *

* + * @since 1.4.0 * * @return One or more qualifier name(s) * @see #qualifiedByName() * @see Named - * @since 1.4.0 */ String[] conditionQualifiedByName() default {}; @@ -114,9 +135,51 @@ public @interface ReverseAutoMapping { *

* An error will be raised in case a cycle in the dependency relationships is detected. * - * @return the dependencies of the mapped property * @since 1.4.0 + * + * @return the dependencies of the mapped property */ String[] dependsOn() default {}; + + /** + * Determines when to include a null check on the source property value of a bean mapping. + * + * Can be overridden by the one on {@link org.mapstruct.MapperConfig}, {@link Mapper} or {@link BeanMapping}. + * + * @since 1.4.1 + * + * @return strategy how to do null checking + */ + NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION; + + /** + * The strategy to be applied when the source property is {@code null} or not present. If no strategy is configured, + * the strategy given via {@link MapperConfig#nullValuePropertyMappingStrategy()}, + * {@link BeanMapping#nullValuePropertyMappingStrategy()} or + * {@link Mapper#nullValuePropertyMappingStrategy()} will be applied. + * + * {@link NullValuePropertyMappingStrategy#SET_TO_NULL} will be used by default. + * + * @since 1.4.1 + * + * @return The strategy to be applied when {@code null} is passed as source property value or the source property + * is not present. + */ + NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() + default NullValuePropertyMappingStrategy.SET_TO_NULL; + + /** + * Allows detailed control over the mapping process. + * + * @return the mapping control + * + * @since 1.4.1 + * + * @see org.mapstruct.control.DeepClone + * @see org.mapstruct.control.NoComplexMapping + * @see org.mapstruct.control.MappingControl + */ + Class mappingControl() default MappingControl.class; + } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/ClassUtil.java b/mapstruct-plus/src/main/java/io/github/linpeilie/utils/ClassUtil.java similarity index 84% rename from mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/ClassUtil.java rename to mapstruct-plus/src/main/java/io/github/linpeilie/utils/ClassUtil.java index 7aa0d2bacfe84f94dec179aa0c55ac4b0dc8d4e7..80085fb36dc84d75f9834a1d29f61be26ba14da6 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/utils/ClassUtil.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/utils/ClassUtil.java @@ -1,4 +1,4 @@ -package io.github.linpeilie.processor.utils; +package io.github.linpeilie.utils; public class ClassUtil { @@ -9,6 +9,9 @@ public class ClassUtil { */ public static String simplifyQualifiedName(String qualifiedName) { String[] arr = qualifiedName.split("\\."); + if (arr.length == 1) { + return arr[0]; + } StringBuilder sb = new StringBuilder(); for (int i = 0; i < arr.length; i++) { if (i == arr.length - 1) { diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/utils/CollectionUtils.java b/mapstruct-plus/src/main/java/io/github/linpeilie/utils/CollectionUtils.java index 857c0f1381276969f9b9a991f6dac5e21de0eead..711d4fb7ca87439c769a3b07303c26de409897e2 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/utils/CollectionUtils.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/utils/CollectionUtils.java @@ -6,6 +6,7 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; public class CollectionUtils { @@ -26,4 +27,11 @@ public class CollectionUtils { return arrayList; } + public static String join(List list, CharSequence delimiter, String prefix, String suffix) { + if (list == null) { + return null; + } + return list.stream().map(str -> prefix + str + suffix).collect(Collectors.joining(delimiter)); + } + } diff --git a/package.json b/package.json index c0f3f70cca5cc1bf6e4ae91b8ba71e8e0e776d01..734528765b5bea81357e71a41307e570b24092ff 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,11 @@ "docs:clean-dev": "vuepress dev docs --clean-cache" }, "dependencies": { - "vue": "3.3.11", - "vuepress": "2.0.0-rc.0", - "vuepress-plugin-umami-analytics": "^1.7.0", - "vuepress-theme-reco": "2.0.0-rc.1" + "vue": "^3.4.27", + "vuepress": "2.0.0-rc.12", + "vuepress-theme-reco": "2.0.0-rc.14", + "@vuepress/bundler-vite": "2.0.0-rc.12", + "@vuepress/bundler-webpack": "2.0.0-rc.12", + "@vuepress/plugin-sitemap": "2.0.0-rc.12" } } diff --git a/pom.xml b/pom.xml index ca1de3a0e39d8e69a2b4e48d3855d6128c33cdcf..adbf46240b2ea5e0aee895a74048b65881c32bfe 100644 --- a/pom.xml +++ b/pom.xml @@ -18,11 +18,12 @@ - 1.4.0 + 1.4.1 8 8 UTF-8 1.5.5.Final + 1.0.0.Alpha3 5.8.26 https://github.com/linpeilie/mapstruct-plus.git @@ -69,6 +70,11 @@ hutool-core ${hutool.version} + + org.mapstruct.tools.gem + gem-api + ${gem.version} +