mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
Compare commits
216 Commits
1.5.5.Fina
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
e4bc1cdf1e | ||
|
c90c93630e | ||
|
f4d1818171 | ||
|
d68819a233 | ||
|
46ce011e4b | ||
|
9847eaf195 | ||
|
ce84c81de2 | ||
|
bff88297e3 | ||
|
8fc97f5f62 | ||
|
5464c3cff8 | ||
|
6b6600c370 | ||
|
0badba7003 | ||
|
3a5c70224d | ||
|
42c87d1da9 | ||
|
05f27e96e2 | ||
|
6e6fd01a2e | ||
|
fce73aee6a | ||
|
2fb5776350 | ||
|
602e29083f | ||
|
2c84d04463 | ||
|
668eeb5de1 | ||
|
d5f825193c | ||
|
39551242d7 | ||
|
c08ba4ca7e | ||
|
57d4f88a48 | ||
|
e0a7d3d0e6 | ||
|
8f96291911 | ||
|
4812d2b030 | ||
|
f98a742f98 | ||
|
084cf3abc1 | ||
|
f3d2b2e65b | ||
|
737af6b50a | ||
|
bee983cd3c | ||
|
8de18e5a65 | ||
|
0df3f6af95 | ||
|
5bf2b152af | ||
|
b4e25e49de | ||
|
772fae4c77 | ||
|
efdf435770 | ||
|
c2bd847599 | ||
|
21fdaa0f82 | ||
|
32f1fea7b5 | ||
|
26c5bcd923 | ||
|
4e0d73db1d | ||
|
212607b447 | ||
|
4fd22d6b26 | ||
|
a3b4139070 | ||
|
c74e62a94c | ||
|
10d69878a1 | ||
|
c36f9ae5d1 | ||
|
3011dd77d7 | ||
|
4c1df35ba6 | ||
|
2686e852b6 | ||
|
12c9c6c1f0 | ||
|
796dd94674 | ||
|
5232df2707 | ||
|
4d9894ba25 | ||
|
23f4802374 | ||
|
1e89d7497b | ||
|
c6010c917a | ||
|
58dcb9d813 | ||
|
c89b616f8c | ||
|
6c8a2e184b | ||
|
60cd0a4420 | ||
|
b452d7f2c8 | ||
|
96d0698417 | ||
|
38ec5c5335 | ||
|
81ca739040 | ||
|
0f24633d04 | ||
|
6365a606c1 | ||
|
6ef64ea3aa | ||
|
bbb9bb403c | ||
|
5ce9c537e9 | ||
|
e2edb1a086 | ||
|
3047760fd0 | ||
|
df49ce5ff9 | ||
|
66f4288842 | ||
|
52877d36c2 | ||
|
eef3bdfca4 | ||
|
8fa2f40944 | ||
|
037da5a1e1 | ||
|
69371708ee | ||
|
babb9dedd9 | ||
|
baa02bf377 | ||
|
8a679b325d | ||
|
21a8b88a0f | ||
|
8e53b4181f | ||
|
9a5e6b1892 | ||
|
b33942a010 | ||
|
0a2a0aa526 | ||
|
0a935c67a7 | ||
|
5fbd36c443 | ||
|
8e66445fe9 | ||
|
e815e3cb1e | ||
|
2c12e75bfc | ||
|
c374b5267f | ||
|
bb1cd63485 | ||
|
ca1fd0d85d | ||
|
8191c850e0 | ||
|
0a43bc088f | ||
|
90a3ce0b46 | ||
|
6830258f77 | ||
|
6322138028 | ||
|
60f162ca88 | ||
|
6cb126cd7c | ||
|
7e6fee8714 | ||
|
6d99f7b8f3 | ||
|
fa857e9ff4 | ||
|
930f5709b6 | ||
|
2bb2aefed8 | ||
|
2af291ce2f | ||
|
04deac2b3a | ||
|
0ac0c42dbc | ||
|
79f01e2de0 | ||
|
b77d321ffb | ||
|
5d39314bd2 | ||
|
c59eca2a77 | ||
|
97c389d58b | ||
|
032ee4d77a | ||
|
f61a3acec3 | ||
|
ea997f83ce | ||
|
8cc2bdd092 | ||
|
721288140a | ||
|
812faeef51 | ||
|
b2dc64136d | ||
|
279ab22482 | ||
|
28d827a724 | ||
|
0460c373c0 | ||
|
230e84efd1 | ||
|
4abf2d4202 | ||
|
53c73324ff | ||
|
04434af17a | ||
|
1b1325da6d | ||
|
86919c637f | ||
|
d075d9a5b6 | ||
|
62d1bd3490 | ||
|
c2eed45df1 | ||
|
51f4e7eba9 | ||
|
84c443df9c | ||
|
6d205e5bc4 | ||
|
7c90592d05 | ||
|
efaa67aadf | ||
|
a89c34f00c | ||
|
d0e4c48228 | ||
|
bc5a877121 | ||
|
be94569791 | ||
|
f3dac94701 | ||
|
4843123e6e | ||
|
a8df94cc20 | ||
|
970984785d | ||
|
d3b4a168b7 | ||
|
931591a385 | ||
|
2f78d3f4e2 | ||
|
1ab5db6a27 | ||
|
86a668661a | ||
|
1bc3436c5c | ||
|
979b35a2f4 | ||
|
e69843f46e | ||
|
c6ea69eaf9 | ||
|
d10d48ccff | ||
|
b1034e6703 | ||
|
9adcb06c34 | ||
|
00f891be58 | ||
|
3c81d36810 | ||
|
162fdb44f4 | ||
|
03563d8ffe | ||
|
6e9fa87ba9 | ||
|
2be1f306a1 | ||
|
62c7ce1cdf | ||
|
89db26a1af | ||
|
a7ba12676d | ||
|
fd27380185 | ||
|
82b19b0d8a | ||
|
8894cd5935 | ||
|
16e3ceadec | ||
|
93f7c3b8ea | ||
|
6a394ad466 | ||
|
bb099a55ee | ||
|
81b2f70dac | ||
|
a5d3542c24 | ||
|
481ab36ca3 | ||
|
3a325ea66b | ||
|
266c5fa41c | ||
|
411cc24dac | ||
|
90a487ac06 | ||
|
af1eab0ece | ||
|
608d476ed2 | ||
|
e979f506fa | ||
|
73e8fd6152 | ||
|
811cd569bb | ||
|
8d670e7db7 | ||
|
d593afed69 | ||
|
97c6755288 | ||
|
bbf63ae177 | ||
|
21069e5a2e | ||
|
68571de01b | ||
|
3cc2aa7675 | ||
|
ac356cab25 | ||
|
4708f4b2aa | ||
|
4fa66229d9 | ||
|
3f798744ac | ||
|
853e7b27df | ||
|
42500ca755 | ||
|
71b1a7b8a2 | ||
|
b24e831cf0 | ||
|
237543c47c | ||
|
fd4a2548b3 | ||
|
874bf1fd2c | ||
|
ef4c26b075 | ||
|
3e0c62ac36 | ||
|
4118a44630 | ||
|
54321d6e66 | ||
|
46900cabde | ||
|
17997ef617 | ||
|
849085e026 | ||
|
8fa286fe4c |
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github: mapstruct
|
||||||
|
open_collective: mapstruct
|
45
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
45
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: Create a report and help us improve
|
||||||
|
labels: ["bug"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Please fill in all required fields with as many details as possible.
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: |
|
||||||
|
Describe what you were expecting MapStruct to do
|
||||||
|
placeholder: |
|
||||||
|
Here you can also add the generated code that you would like MapStruct to generate
|
||||||
|
- type: textarea
|
||||||
|
id: actual
|
||||||
|
attributes:
|
||||||
|
label: Actual behavior
|
||||||
|
description: |
|
||||||
|
Describe what you observed MapStruct did instead
|
||||||
|
placeholder: |
|
||||||
|
Here you can also add the generated code that MapStruct generated
|
||||||
|
- type: textarea
|
||||||
|
id: steps
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce the problem
|
||||||
|
description: |
|
||||||
|
- Share your mapping configuration
|
||||||
|
- An [MCVE (Minimal Complete Verifiable Example)](https://stackoverflow.com/help/minimal-reproducible-example) can be helpful to provide a complete reproduction case
|
||||||
|
placeholder: |
|
||||||
|
Share your MapStruct configuration
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: mapstruct-version
|
||||||
|
attributes:
|
||||||
|
label: MapStruct Version
|
||||||
|
description: |
|
||||||
|
Which MapStruct version did you use?
|
||||||
|
Note: While you can obviously continue using older versions of MapStruct, it may well be that your bug is already fixed. If you're using an older version, please also try to reproduce the bug in the latest version of MapStruct before reporting it.
|
||||||
|
placeholder: ex. MapStruct 1.5.2
|
||||||
|
validations:
|
||||||
|
required: true
|
16
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
16
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
contact_links:
|
||||||
|
- name: MapStruct Discussions
|
||||||
|
url: https://github.com/mapstruct/mapstruct/discussions
|
||||||
|
about: Please use the MapStruct GitHub Discussions for open ended discussions and to reach out to the community.
|
||||||
|
- name: Stack Overflow
|
||||||
|
url: https://stackoverflow.com/questions/tagged/mapstruct
|
||||||
|
about: For questions about how to use MapStruct, consider asking your question on Stack Overflow, tagged [mapstruct].
|
||||||
|
- name: Documentation
|
||||||
|
url: https://mapstruct.org/documentation/stable/reference/html/
|
||||||
|
about: The MapStruct reference documentation.
|
||||||
|
- name: Gitter Chat
|
||||||
|
url: https://gitter.im/mapstruct/mapstruct-users
|
||||||
|
about: For realtime communication with the MapStruct community, consider writing in our Gitter chat room.
|
||||||
|
- name: MapStruct Examples
|
||||||
|
url: https://github.com/mapstruct/mapstruct-examples
|
||||||
|
about: Some examples of what can be achieved with MapStruct. (contributions are always welcome)
|
43
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
43
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: Suggest an idea
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Please describe the use-case you have. This will better help us understand the context in which you're looking for a new feature.
|
||||||
|
- type: textarea
|
||||||
|
id: use-case
|
||||||
|
attributes:
|
||||||
|
label: Use case
|
||||||
|
description: |
|
||||||
|
Please describe the use-case you have. This will better help us understand the context in which you're looking for a new feature.
|
||||||
|
placeholder: Describe the use-case here
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Generated Code
|
||||||
|
description: |
|
||||||
|
Please describe the possible generated code you'd like to see in MapStruct generate.
|
||||||
|
Please note, it's not always easy to describe a good solution. Describing the use-case above is much more important to us.
|
||||||
|
placeholder: Describe the possible solution here.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: workarounds
|
||||||
|
attributes:
|
||||||
|
label: Possible workarounds
|
||||||
|
description: |
|
||||||
|
Please describe the possible workarounds you've implemented to work around the lacking functionality.
|
||||||
|
placeholder: Describe the possible workarounds here.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: mapstruct-version
|
||||||
|
attributes:
|
||||||
|
label: MapStruct Version
|
||||||
|
description: What MapStruct version and edition did you try?
|
||||||
|
placeholder: ex. MapStruct 1.5.2
|
||||||
|
validations:
|
||||||
|
required: false
|
82
.github/scripts/update-website.sh
vendored
Normal file
82
.github/scripts/update-website.sh
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright MapStruct Authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
# env vars:
|
||||||
|
# VERSION
|
||||||
|
# GH_BOT_EMAIL
|
||||||
|
|
||||||
|
# This script has been inspired by the JReleaser update-website.sh (https://github.com/jreleaser/jreleaser/blob/main/.github/scripts/update-website.sh)
|
||||||
|
set -e
|
||||||
|
|
||||||
|
function computePlainVersion() {
|
||||||
|
echo $1 | sed 's/\([[:digit:]]*\)\.\([[:digit:]]*\)\.\([[:digit:]]*\).*/\1.\2.\3/'
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeMajorMinorVersion() {
|
||||||
|
echo $1 | sed 's/\([[:digit:]]*\)\.\([[:digit:]]*\).*/\1.\2/'
|
||||||
|
}
|
||||||
|
|
||||||
|
function isStable() {
|
||||||
|
local PLAIN_VERSION=$(computePlainVersion $1)
|
||||||
|
if [ "${PLAIN_VERSION}" == "$1" ]; then
|
||||||
|
echo "yes"
|
||||||
|
else
|
||||||
|
echo "no"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
STABLE=$(isStable $VERSION)
|
||||||
|
MAJOR_MINOR_VERSION=$(computeMajorMinorVersion $VERSION)
|
||||||
|
|
||||||
|
DEV_VERSION=`grep devVersion config.toml | sed 's/.*"\(.*\)"/\1/'`
|
||||||
|
MAJOR_MINOR_DEV_VERSION=$(computeMajorMinorVersion $DEV_VERSION)
|
||||||
|
STABLE_VERSION=`grep stableVersion config.toml | sed 's/.*"\(.*\)"/\1/'`
|
||||||
|
MAJOR_MINOR_STABLE_VERSION=$(computeMajorMinorVersion $STABLE_VERSION)
|
||||||
|
|
||||||
|
echo "📝 Updating versions"
|
||||||
|
|
||||||
|
SEDOPTION="-i"
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
SEDOPTION="-i ''"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed $SEDOPTION -e "s/^devVersion = \"\(.*\)\"/devVersion = \"${VERSION}\"/g" config.toml
|
||||||
|
|
||||||
|
if [ "${STABLE}" == "yes" ]; then
|
||||||
|
sed $SEDOPTION -e "s/^stableVersion = \"\(.*\)\"/stableVersion = \"${VERSION}\"/g" config.toml
|
||||||
|
if [ "${MAJOR_MINOR_STABLE_VERSION}" != ${MAJOR_MINOR_VERSION} ]; then
|
||||||
|
echo "📝 Updating new stable version"
|
||||||
|
# This means that we have a new stable version and we need to change the order of the releases.
|
||||||
|
sed $SEDOPTION -e "s/^order = \(.*\)/order = 500/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||||
|
NEXT_STABLE_ORDER=$((`ls -1 data/releases | wc -l` - 2))
|
||||||
|
sed $SEDOPTION -e "s/^order = \(.*\)/order = ${NEXT_STABLE_ORDER}/g" data/releases/${MAJOR_MINOR_STABLE_VERSION}.toml
|
||||||
|
git add data/releases/${MAJOR_MINOR_STABLE_VERSION}.toml
|
||||||
|
fi
|
||||||
|
elif [ "${MAJOR_MINOR_DEV_VERSION}" != "${MAJOR_MINOR_VERSION}" ]; then
|
||||||
|
echo "📝 Updating new dev version"
|
||||||
|
# This means that we are updating for a new dev version, but the last dev version is not the one that we are doing.
|
||||||
|
# Therefore, we need to update add the new data configuration
|
||||||
|
cp data/releases/${MAJOR_MINOR_DEV_VERSION}.toml data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||||
|
sed $SEDOPTION -e "s/^order = \(.*\)/order = 1000/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed $SEDOPTION -e "s/^name = \"\(.*\)\"/name = \"${VERSION}\"/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||||
|
sed $SEDOPTION -e "s/^releaseDate = \(.*\)/releaseDate = $(date +%F)/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||||
|
git add data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||||
|
git add config.toml
|
||||||
|
|
||||||
|
echo "📝 Updating distribution resources"
|
||||||
|
tar -xf tmp/mapstruct-${VERSION}-dist.tar.gz --directory tmp
|
||||||
|
rm -rf static/documentation/${MAJOR_MINOR_VERSION}
|
||||||
|
cp -R tmp/mapstruct-${VERSION}/docs static/documentation/${MAJOR_MINOR_VERSION}
|
||||||
|
mv static/documentation/${MAJOR_MINOR_VERSION}/reference/html/mapstruct-reference-guide.html static/documentation/${MAJOR_MINOR_VERSION}/reference/html/index.html
|
||||||
|
git add static/documentation/${MAJOR_MINOR_VERSION}
|
||||||
|
|
||||||
|
git config --global user.email "${GH_BOT_EMAIL}"
|
||||||
|
git config --global user.name "GitHub Action"
|
||||||
|
git commit -a -m "Releasing version ${VERSION}"
|
||||||
|
git push
|
14
.github/workflows/java-ea.yml
vendored
14
.github/workflows/java-ea.yml
vendored
@ -7,19 +7,15 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test_jdk_ea:
|
test_jdk_ea:
|
||||||
strategy:
|
name: 'Linux JDK EA'
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
java: [19-ea]
|
|
||||||
name: 'Linux JDK ${{ matrix.java }}'
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout'
|
- name: 'Checkout'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: 'Set up JDK'
|
- name: 'Set up JDK'
|
||||||
uses: actions/setup-java@v3
|
uses: oracle-actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
website: jdk.java.net
|
||||||
java-version: ${{ matrix.java }}
|
release: EA
|
||||||
- name: 'Test'
|
- name: 'Test'
|
||||||
run: ./mvnw ${MAVEN_ARGS} -Djacoco.skip=true install -DskipDistribution=true
|
run: ./mvnw ${MAVEN_ARGS} -Djacoco.skip=true install -DskipDistribution=true
|
||||||
|
20
.github/workflows/macos.yml
vendored
Normal file
20
.github/workflows/macos.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: Mac OS CI
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
env:
|
||||||
|
MAVEN_ARGS: -V -B --no-transfer-progress -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false -Dmaven.wagon.httpconnectionManager.ttlSeconds=120
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
mac:
|
||||||
|
name: 'Mac OS'
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: 'Set up JDK 21'
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
|
java-version: 21
|
||||||
|
- name: 'Test'
|
||||||
|
run: ./mvnw ${MAVEN_ARGS} install
|
71
.github/workflows/main.yml
vendored
71
.github/workflows/main.yml
vendored
@ -12,80 +12,49 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
java: [13, 17, 18]
|
java: [21]
|
||||||
name: 'Linux JDK ${{ matrix.java }}'
|
name: 'Linux JDK ${{ matrix.java }}'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout'
|
- name: 'Checkout'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: 'Set up JDK'
|
- name: 'Set up JDK'
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
- name: 'Test'
|
- name: 'Test'
|
||||||
run: ./mvnw ${MAVEN_ARGS} -Djacoco.skip=true install -DskipDistribution=true
|
run: ./mvnw ${MAVEN_ARGS} -Djacoco.skip=${{ matrix.java != 21 }} install -DskipDistribution=${{ matrix.java != 21 }}
|
||||||
linux:
|
|
||||||
name: 'Linux JDK 11'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: 'Checkout'
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: 'Set up JDK 11'
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
|
||||||
- name: 'Test'
|
|
||||||
run: ./mvnw ${MAVEN_ARGS} install
|
|
||||||
- name: 'Generate coverage report'
|
- name: 'Generate coverage report'
|
||||||
|
if: matrix.java == 21
|
||||||
run: ./mvnw jacoco:report
|
run: ./mvnw jacoco:report
|
||||||
- name: 'Upload coverage to Codecov'
|
- name: 'Upload coverage to Codecov'
|
||||||
|
if: matrix.java == 21
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v2
|
||||||
- name: 'Publish Snapshots'
|
- name: 'Publish Snapshots'
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'mapstruct/mapstruct'
|
if: matrix.java == 21 && github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'mapstruct/mapstruct'
|
||||||
run: ./mvnw -s etc/ci-settings.xml -DskipTests=true -DskipDistribution=true deploy
|
run: ./mvnw -s etc/ci-settings.xml -DskipTests=true -DskipDistribution=true deploy
|
||||||
linux-jdk-8:
|
integration_test_jdk:
|
||||||
name: 'Linux JDK 8'
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
java: [ 8, 11, 17 ]
|
||||||
|
name: 'Linux JDK ${{ matrix.java }}'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout'
|
- name: 'Checkout'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: 'Set up JDK 11 for building everything'
|
- name: 'Set up JDK 21 for building everything'
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 11
|
java-version: 21
|
||||||
- name: 'Install Processor'
|
- name: 'Install Processor'
|
||||||
run: ./mvnw ${MAVEN_ARGS} -DskipTests install -pl processor -am
|
run: ./mvnw ${MAVEN_ARGS} -DskipTests install -pl processor -am
|
||||||
- name: 'Set up JDK 8 for running integration tests'
|
- name: 'Set up JDK ${{ matrix.java }} for running integration tests'
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: 8
|
java-version: ${{ matrix.java }}
|
||||||
- name: 'Run integration tests'
|
- name: 'Run integration tests'
|
||||||
run: ./mvnw ${MAVEN_ARGS} verify -pl integrationtest
|
run: ./mvnw ${MAVEN_ARGS} verify -pl integrationtest
|
||||||
windows:
|
|
||||||
name: 'Windows'
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: 'Set up JDK 11'
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
|
||||||
- name: 'Test'
|
|
||||||
run: ./mvnw %MAVEN_ARGS% install
|
|
||||||
mac:
|
|
||||||
name: 'Mac OS'
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: 'Set up JDK 11'
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 11
|
|
||||||
- name: 'Test'
|
|
||||||
run: ./mvnw ${MAVEN_ARGS} install
|
|
||||||
|
117
.github/workflows/release.yml
vendored
Normal file
117
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: 'Release version'
|
||||||
|
required: true
|
||||||
|
next:
|
||||||
|
description: 'Next version'
|
||||||
|
required: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
# This job has been inspired by the moditect release (https://github.com/moditect/moditect/blob/main/.github/workflows/release.yml)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: 21
|
||||||
|
distribution: 'zulu'
|
||||||
|
cache: maven
|
||||||
|
|
||||||
|
- name: Set release version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
RELEASE_VERSION=${{ github.event.inputs.version }}
|
||||||
|
NEXT_VERSION=${{ github.event.inputs.next }}
|
||||||
|
PLAIN_VERSION=`echo ${RELEASE_VERSION} | awk 'match($0, /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)/) { print substr($0, RSTART, RLENGTH); }'`
|
||||||
|
COMPUTED_NEXT_VERSION="${PLAIN_VERSION}-SNAPSHOT"
|
||||||
|
if [ -z $NEXT_VERSION ]
|
||||||
|
then
|
||||||
|
NEXT_VERSION=$COMPUTED_NEXT_VERSION
|
||||||
|
fi
|
||||||
|
./mvnw -ntp -B versions:set versions:commit -DnewVersion=$RELEASE_VERSION -pl :mapstruct-parent -DgenerateBackupPoms=false
|
||||||
|
git config --global user.email "${{ vars.GH_BOT_EMAIL }}"
|
||||||
|
git config --global user.name "GitHub Action"
|
||||||
|
git commit -a -m "Releasing version $RELEASE_VERSION"
|
||||||
|
git push
|
||||||
|
echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV
|
||||||
|
echo "NEXT_VERSION=$NEXT_VERSION" >> $GITHUB_ENV
|
||||||
|
echo "PLAIN_VERSION=$PLAIN_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Stage
|
||||||
|
run: |
|
||||||
|
export GPG_TTY=$(tty)
|
||||||
|
./mvnw -ntp -B --file pom.xml \
|
||||||
|
-Dmaven.site.skip=true -Drelease=true -Ppublication,stage
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
env:
|
||||||
|
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
JRELEASER_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.GPG_PUBLIC_KEY }}
|
||||||
|
JRELEASER_GPG_SECRET_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
JRELEASER_NEXUS2_MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
|
JRELEASER_NEXUS2_MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
./mvnw -ntp -B --file pom.xml -pl :mapstruct-parent -Pjreleaser jreleaser:release
|
||||||
|
|
||||||
|
- name: JReleaser output
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: jreleaser-release
|
||||||
|
path: |
|
||||||
|
parent/target/jreleaser/trace.log
|
||||||
|
parent/target/jreleaser/output.properties
|
||||||
|
|
||||||
|
- name: Reset NEXT_RELEASE_CHANGELOG.md
|
||||||
|
run: |
|
||||||
|
echo -e "### Features\n\n### Enhancements\n\n### Bugs\n\n### Documentation\n\n### Build\n" > NEXT_RELEASE_CHANGELOG.md
|
||||||
|
|
||||||
|
- name: Set next version
|
||||||
|
run: |
|
||||||
|
./mvnw -ntp -B versions:set versions:commit -DnewVersion=${{ env.NEXT_VERSION }} -pl :mapstruct-parent -DgenerateBackupPoms=false
|
||||||
|
sed -i -e "s@project.build.outputTimestamp>.*</project.build.outputTimestamp@project.build.outputTimestamp>\${git.commit.author.time}</project.build.outputTimestamp@g" parent/pom.xml
|
||||||
|
git config --global user.email "${{ vars.GH_BOT_EMAIL }}"
|
||||||
|
git config --global user.name "GitHub Action"
|
||||||
|
git commit -a -m "Next version ${{ env.NEXT_VERSION }}"
|
||||||
|
git push
|
||||||
|
|
||||||
|
update-website:
|
||||||
|
# This job has been inspired by the JReleaser update-website job (https://github.com/jreleaser/jreleaser/blob/main/.github/workflows/release.yml)
|
||||||
|
name: Update Website
|
||||||
|
needs: [release]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: mapstruct/mapstruct.org
|
||||||
|
ref: main
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ secrets.GIT_WEBSITE_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Download assets
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -sL https://raw.githubusercontent.com/mapstruct/mapstruct/main/.github/scripts/update-website.sh --output update-website.sh --create-dirs --output-dir tmp
|
||||||
|
curl -sL "https://github.com/mapstruct/mapstruct/releases/download/${VERSION}/mapstruct-${VERSION}-dist.tar.gz" --output mapstruct-${VERSION}-dist.tar.gz --create-dirs --output-dir tmp
|
||||||
|
env:
|
||||||
|
VERSION: ${{ github.event.inputs.version }}
|
||||||
|
|
||||||
|
- name: Commit
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
VERSION: ${{ github.event.inputs.version }}
|
||||||
|
GH_BOT_EMAIL: ${{ vars.GH_BOT_EMAIL }}
|
||||||
|
run: |
|
||||||
|
chmod +x tmp/update-website.sh
|
||||||
|
tmp/update-website.sh
|
20
.github/workflows/windows.yml
vendored
Normal file
20
.github/workflows/windows.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: Windows CI
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
env:
|
||||||
|
MAVEN_ARGS: -V -B --no-transfer-progress -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false -Dmaven.wagon.httpconnectionManager.ttlSeconds=120
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
windows:
|
||||||
|
name: 'Windows'
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: 'Set up JDK 21'
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
|
java-version: 21
|
||||||
|
- name: 'Test'
|
||||||
|
run: ./mvnw %MAVEN_ARGS% install
|
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2007-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
import java.net.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.channels.*;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class MavenWrapperDownloader {
|
|
||||||
|
|
||||||
private static final String WRAPPER_VERSION = "0.5.6";
|
|
||||||
/**
|
|
||||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
|
||||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
|
||||||
* use instead of the default one.
|
|
||||||
*/
|
|
||||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
|
||||||
".mvn/wrapper/maven-wrapper.properties";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path where the maven-wrapper.jar will be saved to.
|
|
||||||
*/
|
|
||||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
|
||||||
".mvn/wrapper/maven-wrapper.jar";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the property which should be used to override the default download url for the wrapper.
|
|
||||||
*/
|
|
||||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
|
||||||
|
|
||||||
public static void main(String args[]) {
|
|
||||||
System.out.println("- Downloader started");
|
|
||||||
File baseDirectory = new File(args[0]);
|
|
||||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
|
||||||
|
|
||||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
|
||||||
// wrapperUrl parameter.
|
|
||||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
|
||||||
String url = DEFAULT_DOWNLOAD_URL;
|
|
||||||
if(mavenWrapperPropertyFile.exists()) {
|
|
||||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
|
||||||
try {
|
|
||||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
|
||||||
Properties mavenWrapperProperties = new Properties();
|
|
||||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
|
||||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if(mavenWrapperPropertyFileInputStream != null) {
|
|
||||||
mavenWrapperPropertyFileInputStream.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Ignore ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("- Downloading from: " + url);
|
|
||||||
|
|
||||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
|
||||||
if(!outputFile.getParentFile().exists()) {
|
|
||||||
if(!outputFile.getParentFile().mkdirs()) {
|
|
||||||
System.out.println(
|
|
||||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
|
||||||
try {
|
|
||||||
downloadFileFromURL(url, outputFile);
|
|
||||||
System.out.println("Done");
|
|
||||||
System.exit(0);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
System.out.println("- Error downloading");
|
|
||||||
e.printStackTrace();
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
|
||||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
|
||||||
String username = System.getenv("MVNW_USERNAME");
|
|
||||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
|
||||||
Authenticator.setDefault(new Authenticator() {
|
|
||||||
@Override
|
|
||||||
protected PasswordAuthentication getPasswordAuthentication() {
|
|
||||||
return new PasswordAuthentication(username, password);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
URL website = new URL(urlString);
|
|
||||||
ReadableByteChannel rbc;
|
|
||||||
rbc = Channels.newChannel(website.openStream());
|
|
||||||
FileOutputStream fos = new FileOutputStream(destination);
|
|
||||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
|
||||||
fos.close();
|
|
||||||
rbc.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Binary file not shown.
21
.mvn/wrapper/maven-wrapper.properties
vendored
21
.mvn/wrapper/maven-wrapper.properties
vendored
@ -1,2 +1,19 @@
|
|||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
wrapperVersion=3.3.2
|
||||||
|
distributionType=only-script
|
||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
- [ ] Is this an issue (and hence not a question)?
|
|
||||||
|
|
||||||
If this is a question how to use MapStruct there are several resources available.
|
|
||||||
- Our reference- and API [documentation](http://mapstruct.org/documentation/reference-guide/).
|
|
||||||
- Our [examples](https://github.com/mapstruct/mapstruct-examples) repository (contributions always welcome)
|
|
||||||
- Our [FAQ](http://mapstruct.org/faq/)
|
|
||||||
- [StackOverflow](https://stackoverflow.com), tag MapStruct
|
|
||||||
- [Gitter](https://gitter.im/mapstruct/mapstruct-users) (you usually get fast feedback)
|
|
||||||
- Our [google group](https://groups.google.com/forum/#!forum/mapstruct-users)
|
|
29
NEXT_RELEASE_CHANGELOG.md
Normal file
29
NEXT_RELEASE_CHANGELOG.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
### Features
|
||||||
|
|
||||||
|
* Support for Java 21 Sequenced Collections (#3240)
|
||||||
|
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
* Add support for locale parameter for numberFormat and dateFormat (#3628)
|
||||||
|
* Detect Builder without a factory method (#3729) - With this if there is an inner class that ends with `Builder` and has a constructor with parameters,
|
||||||
|
it will be treated as a potential builder.
|
||||||
|
Builders through static methods on the type have a precedence.
|
||||||
|
* Behaviour change: Warning when the target has no target properties (#1140)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Bugs
|
||||||
|
|
||||||
|
* Improve error message when mapping non-iterable to array (#3786)
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
### Behaviour Change
|
||||||
|
|
||||||
|
#### Warning when the target has no target properties
|
||||||
|
|
||||||
|
With this change, if the target bean does not have any target properties, a warning will be shown.
|
||||||
|
This is like this to avoid potential mistakes by users, where they might think that the target bean has properties, but it does not.
|
@ -12,7 +12,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
<artifactId>mapstruct-parent</artifactId>
|
<artifactId>mapstruct-parent</artifactId>
|
||||||
<version>1.6.0-SNAPSHOT</version>
|
<version>1.7.0-SNAPSHOT</version>
|
||||||
<relativePath>../parent/pom.xml</relativePath>
|
<relativePath>../parent/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
<!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
|
<!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
|
||||||
<module name="Translation"/>
|
<module name="Translation"/>
|
||||||
|
|
||||||
<module name="FileLength"/>
|
<module name="FileLength">
|
||||||
|
<property name="max" value="2500"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
<module name="LineLength">
|
<module name="LineLength">
|
||||||
<property name="max" value="120"/>
|
<property name="max" value="120"/>
|
||||||
@ -144,7 +146,9 @@
|
|||||||
</module>
|
</module>
|
||||||
<module name="TypecastParenPad"/>
|
<module name="TypecastParenPad"/>
|
||||||
<module name="WhitespaceAfter"/>
|
<module name="WhitespaceAfter"/>
|
||||||
<module name="WhitespaceAround"/>
|
<module name="WhitespaceAround">
|
||||||
|
<property name="ignoreEnhancedForColon" value="false"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
<module name="EmptyLineSeparator">
|
<module name="EmptyLineSeparator">
|
||||||
<property name="tokens" value="IMPORT, CLASS_DEF, INTERFACE_DEF, STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
<property name="tokens" value="IMPORT, CLASS_DEF, INTERFACE_DEF, STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||||
|
@ -42,8 +42,10 @@ Kevin Grüneberg - https://github.com/kevcodez
|
|||||||
Lukas Lazar - https://github.com/LukeLaz
|
Lukas Lazar - https://github.com/LukeLaz
|
||||||
Nikolas Charalambidis - https://github.com/Nikolas-Charalambidis
|
Nikolas Charalambidis - https://github.com/Nikolas-Charalambidis
|
||||||
Michael Pardo - https://github.com/pardom
|
Michael Pardo - https://github.com/pardom
|
||||||
|
Muhammad Usama - https://github.com/the-mgi
|
||||||
Mustafa Caylak - https://github.com/luxmeter
|
Mustafa Caylak - https://github.com/luxmeter
|
||||||
Oliver Ehrenmüller - https://github.com/greuelpirat
|
Oliver Ehrenmüller - https://github.com/greuelpirat
|
||||||
|
Oliver Erhart - https://github.com/thunderhook
|
||||||
Paul Strugnell - https://github.com/ps-powa
|
Paul Strugnell - https://github.com/ps-powa
|
||||||
Pascal Grün - https://github.com/pascalgn
|
Pascal Grün - https://github.com/pascalgn
|
||||||
Pavel Makhov - https://github.com/streetturtle
|
Pavel Makhov - https://github.com/streetturtle
|
||||||
@ -67,3 +69,5 @@ Timo Eckhardt - https://github.com/timoe
|
|||||||
Tomek Gubala - https://github.com/vgtworld
|
Tomek Gubala - https://github.com/vgtworld
|
||||||
Valentin Kulesh - https://github.com/unshare
|
Valentin Kulesh - https://github.com/unshare
|
||||||
Vincent Alexander Beelte - https://github.com/grandmasterpixel
|
Vincent Alexander Beelte - https://github.com/grandmasterpixel
|
||||||
|
Winter Andreas - https://github.dev/wandi34
|
||||||
|
Xiu Hong Kooi - https://github.com/kooixh
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
<artifactId>mapstruct-parent</artifactId>
|
<artifactId>mapstruct-parent</artifactId>
|
||||||
<version>1.6.0-SNAPSHOT</version>
|
<version>1.7.0-SNAPSHOT</version>
|
||||||
<relativePath>../parent/pom.xml</relativePath>
|
<relativePath>../parent/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
<artifactId>mapstruct-parent</artifactId>
|
<artifactId>mapstruct-parent</artifactId>
|
||||||
<version>1.6.0-SNAPSHOT</version>
|
<version>1.7.0-SNAPSHOT</version>
|
||||||
<relativePath>../parent/pom.xml</relativePath>
|
<relativePath>../parent/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
176
core/src/main/java/org/mapstruct/AnnotateWith.java
Normal file
176
core/src/main/java/org/mapstruct/AnnotateWith.java
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This can be used to have mapstruct generate additional annotations on classes/methods.
|
||||||
|
* <p>
|
||||||
|
* Examples based on the spring framework annotations.
|
||||||
|
* </p>
|
||||||
|
* Marking a class as `Lazy`:
|
||||||
|
*
|
||||||
|
* <pre><code>
|
||||||
|
* @AnnotateWith( value = Lazy.class )
|
||||||
|
* @Mapper
|
||||||
|
* public interface FooMapper {
|
||||||
|
* // mapper code
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* The following code would be generated:
|
||||||
|
*
|
||||||
|
* <pre><code>
|
||||||
|
* @Lazy
|
||||||
|
* public class FooMapperImpl implements FooMapper {
|
||||||
|
* // mapper code
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
* Setting the profile on the generated implementation:
|
||||||
|
*
|
||||||
|
* <pre><code>
|
||||||
|
* @AnnotateWith( value = Profile.class, elements = @AnnotateWith.Element( strings = "prod" ) )
|
||||||
|
* @Mapper
|
||||||
|
* public interface FooMapper {
|
||||||
|
* // mapper code
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* The following code would be generated:
|
||||||
|
*
|
||||||
|
* <pre><code>
|
||||||
|
* @Profile( value = "prod" )
|
||||||
|
* public class FooMapperImpl implements FooMapper {
|
||||||
|
* // mapper code
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* @author Ben Zegveld
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
@Repeatable( AnnotateWiths.class )
|
||||||
|
@Retention( CLASS )
|
||||||
|
@Target( { TYPE, METHOD, ANNOTATION_TYPE } )
|
||||||
|
public @interface AnnotateWith {
|
||||||
|
/**
|
||||||
|
* @return the annotation class that needs to be added.
|
||||||
|
*/
|
||||||
|
Class<? extends Annotation> value();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the annotation elements that are to be applied to this annotation.
|
||||||
|
*/
|
||||||
|
Element[] elements() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in combination with {@link AnnotateWith} to configure the annotation elements. Only 1 value type may be used
|
||||||
|
* within the same annotation at a time. For example mixing shorts and ints is not allowed.
|
||||||
|
*
|
||||||
|
* @author Ben Zegveld
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
@interface Element {
|
||||||
|
/**
|
||||||
|
* @return name of the annotation element.
|
||||||
|
*/
|
||||||
|
String name() default "value";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return short value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
short[] shorts() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return byte value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
byte[] bytes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return int value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
int[] ints() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return long value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
long[] longs() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return float value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
float[] floats() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return double value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
double[] doubles() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return char value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
char[] chars() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return boolean value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
boolean[] booleans() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return string value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
String[] strings() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields.
|
||||||
|
*
|
||||||
|
* @return class value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
Class<?>[] classes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* only used in conjunction with the {@link #enums()} annotation element.
|
||||||
|
*
|
||||||
|
* @return the class of the enum.
|
||||||
|
*/
|
||||||
|
Class<? extends Enum<?>> enumClass() default NullEnum.class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cannot be used in conjunction with other value fields. {@link #enumClass()} is also required when using
|
||||||
|
* {@link #enums()}
|
||||||
|
*
|
||||||
|
* @return enum value(s) for the annotation element.
|
||||||
|
*/
|
||||||
|
String[] enums() default {};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
31
core/src/main/java/org/mapstruct/AnnotateWiths.java
Normal file
31
core/src/main/java/org/mapstruct/AnnotateWiths.java
Normal file
@ -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 org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This can be used to have mapstruct generate additional annotations on classes/methods.
|
||||||
|
*
|
||||||
|
* @author Ben Zegveld
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
@Retention( CLASS )
|
||||||
|
@Target( { TYPE, METHOD } )
|
||||||
|
public @interface AnnotateWiths {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration of the additional annotations.
|
||||||
|
*
|
||||||
|
* @return The configuration of the additional annotations.
|
||||||
|
*/
|
||||||
|
AnnotateWith[] value();
|
||||||
|
}
|
@ -19,6 +19,8 @@ import static org.mapstruct.SubclassExhaustiveStrategy.COMPILE_ERROR;
|
|||||||
/**
|
/**
|
||||||
* Configures the mapping between two bean types.
|
* Configures the mapping between two bean types.
|
||||||
* <p>
|
* <p>
|
||||||
|
* Unless otherwise specified these properties are inherited to the generated bean mapping methods.
|
||||||
|
* <p>
|
||||||
* Either {@link #resultType()}, {@link #qualifiedBy()} or {@link #nullValueMappingStrategy()} must be specified.
|
* Either {@link #resultType()}, {@link #qualifiedBy()} or {@link #nullValueMappingStrategy()} must be specified.
|
||||||
* </p>
|
* </p>
|
||||||
* <p><strong>Example:</strong> Determining the result type</p>
|
* <p><strong>Example:</strong> Determining the result type</p>
|
||||||
@ -58,6 +60,8 @@ public @interface BeanMapping {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the result type of the factory method to be used in case several factory methods qualify.
|
* Specifies the result type of the factory method to be used in case several factory methods qualify.
|
||||||
|
* <p>
|
||||||
|
* <b>NOTE</b>: This property is not inherited to generated mapping methods
|
||||||
*
|
*
|
||||||
* @return the resultType to select
|
* @return the resultType to select
|
||||||
*/
|
*/
|
||||||
@ -128,6 +132,18 @@ public @interface BeanMapping {
|
|||||||
*/
|
*/
|
||||||
SubclassExhaustiveStrategy subclassExhaustiveStrategy() default COMPILE_ERROR;
|
SubclassExhaustiveStrategy subclassExhaustiveStrategy() default COMPILE_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the exception type to be thrown when a missing subclass implementation is detected
|
||||||
|
* in combination with {@link SubclassMappings}, based on the {@link #subclassExhaustiveStrategy()}.
|
||||||
|
* <p>
|
||||||
|
* This exception will only be thrown when the {@code subclassExhaustiveStrategy} is set to
|
||||||
|
* {@link SubclassExhaustiveStrategy#RUNTIME_EXCEPTION}.
|
||||||
|
*
|
||||||
|
* @return the exception class to throw when missing implementations are found.
|
||||||
|
* Defaults to {@link IllegalArgumentException}.
|
||||||
|
*/
|
||||||
|
Class<? extends Exception> subclassExhaustiveException() default IllegalArgumentException.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default ignore all mappings. All mappings have to be defined manually. No automatic mapping will take place. No
|
* Default ignore all mappings. All mappings have to be defined manually. No automatic mapping will take place. No
|
||||||
* warning will be issued on missing source or target properties.
|
* warning will be issued on missing source or target properties.
|
||||||
@ -145,6 +161,8 @@ public @interface BeanMapping {
|
|||||||
* source properties report.
|
* source properties report.
|
||||||
* <p>
|
* <p>
|
||||||
* <b>NOTE</b>: This does not support ignoring nested source properties
|
* <b>NOTE</b>: This does not support ignoring nested source properties
|
||||||
|
* <p>
|
||||||
|
* <b>NOTE</b>: This property is not inherited to generated mapping methods
|
||||||
*
|
*
|
||||||
* @return The source properties that should be ignored when performing a report
|
* @return The source properties that should be ignored when performing a report
|
||||||
*
|
*
|
||||||
@ -152,6 +170,17 @@ public @interface BeanMapping {
|
|||||||
*/
|
*/
|
||||||
String[] ignoreUnmappedSourceProperties() default {};
|
String[] ignoreUnmappedSourceProperties() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How unmapped properties of the source type of a mapping should be reported.
|
||||||
|
* If no policy is configured, the policy given via {@link MapperConfig#unmappedSourcePolicy()} or
|
||||||
|
* {@link Mapper#unmappedSourcePolicy()} will be applied, using {@link ReportingPolicy#IGNORE} by default.
|
||||||
|
*
|
||||||
|
* @return The reporting policy for unmapped source properties.
|
||||||
|
*
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
ReportingPolicy unmappedSourcePolicy() default ReportingPolicy.IGNORE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How unmapped properties of the target type of a mapping should be reported.
|
* How unmapped properties of the target type of a mapping should be reported.
|
||||||
* If no policy is configured, the policy given via {@link MapperConfig#unmappedTargetPolicy()} or
|
* If no policy is configured, the policy given via {@link MapperConfig#unmappedTargetPolicy()} or
|
||||||
|
@ -7,6 +7,54 @@ package org.mapstruct;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Strategy for propagating the value of collection-typed properties from source to target.
|
* Strategy for propagating the value of collection-typed properties from source to target.
|
||||||
|
* <p>
|
||||||
|
* In the table below, the dash {@code -} indicates a property name.
|
||||||
|
* Next, the trailing {@code s} indicates the plural form.
|
||||||
|
* The table explains the options and how they are applied to the presence / absence of a
|
||||||
|
* {@code set-s}, {@code add-} and / or {@code get-s} method on the target object.
|
||||||
|
* <table>
|
||||||
|
* <caption>Collection mapping strategy options</caption>
|
||||||
|
* <tr>
|
||||||
|
* <th>Option</th>
|
||||||
|
* <th>Only target set-s Available</th>
|
||||||
|
* <th>Only target add- Available</th>
|
||||||
|
* <th>Both set-s/add- Available</th>
|
||||||
|
* <th>No set-s/add- Available</th>
|
||||||
|
* <th>Existing Target ({@code @TargetType})</th>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>{@link #ACCESSOR_ONLY}</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* <td>get-s</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* <td>get-s</td>
|
||||||
|
* <td>get-s</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>{@link #SETTER_PREFERRED}</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* <td>add-</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* <td>get-s</td>
|
||||||
|
* <td>get-s</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>{@link #ADDER_PREFERRED}</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* <td>add-</td>
|
||||||
|
* <td>add-</td>
|
||||||
|
* <td>get-s</td>
|
||||||
|
* <td>get-s</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>{@link #TARGET_IMMUTABLE}</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* <td>exception</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* <td>exception</td>
|
||||||
|
* <td>set-s</td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
*
|
*
|
||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
|
@ -11,24 +11,35 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This annotation marks a method as a <em>presence check method</em> to check check for presence in beans.
|
* This annotation marks a method as a <em>presence check method</em> to check for presence in beans
|
||||||
|
* or it can be used to define additional check methods for something like source parameters.
|
||||||
* <p>
|
* <p>
|
||||||
* By default bean properties are checked against {@code null} or using a presence check method in the source bean.
|
* By default, bean properties are checked against {@code null} or using a presence check method in the source bean.
|
||||||
* If a presence check method is available then it will be used instead.
|
* If a presence check method is available then it will be used instead.
|
||||||
* <p>
|
* <p>
|
||||||
* Presence check methods have to return {@code boolean}.
|
* Presence check methods have to return {@code boolean}.
|
||||||
* The following parameters are accepted for the presence check methods:
|
* The following parameters are accepted for the presence check methods:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>The parameter with the value of the source property.
|
* <li>The parameter with the value of the source property.
|
||||||
* e.g. the value given by calling {@code getName()} for the name property of the source bean</li>
|
* e.g. the value given by calling {@code getName()} for the name property of the source bean
|
||||||
|
* - only possible when using the {@link ConditionStrategy#PROPERTIES}
|
||||||
|
* </li>
|
||||||
* <li>The mapping source parameter</li>
|
* <li>The mapping source parameter</li>
|
||||||
* <li>{@code @}{@link Context} parameter</li>
|
* <li>{@code @}{@link Context} parameter</li>
|
||||||
|
* <li>
|
||||||
|
* {@code @}{@link TargetPropertyName} parameter -
|
||||||
|
* only possible when using the {@link ConditionStrategy#PROPERTIES}
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@code @}{@link SourcePropertyName} parameter -
|
||||||
|
* only possible when using the {@link ConditionStrategy#PROPERTIES}
|
||||||
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <strong>Note:</strong> The usage of this annotation is <em>mandatory</em>
|
* <strong>Note:</strong> The usage of this annotation is <em>mandatory</em>
|
||||||
* for a method to be considered as a presence check method.
|
* for a method to be considered as a presence check method.
|
||||||
*
|
*
|
||||||
* <pre><code>
|
* <pre><code class='java'>
|
||||||
* public class PresenceCheckUtils {
|
* public class PresenceCheckUtils {
|
||||||
*
|
*
|
||||||
* @Condition
|
* @Condition
|
||||||
@ -43,11 +54,10 @@ import java.lang.annotation.Target;
|
|||||||
* MovieDto map(Movie movie);
|
* MovieDto map(Movie movie);
|
||||||
* }
|
* }
|
||||||
* </code></pre>
|
* </code></pre>
|
||||||
*
|
* <p>
|
||||||
* The following implementation of {@code MovieMapper} will be generated:
|
* The following implementation of {@code MovieMapper} will be generated:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre><code class='java'>
|
||||||
* <code>
|
|
||||||
* public class MovieMapperImpl implements MovieMapper {
|
* public class MovieMapperImpl implements MovieMapper {
|
||||||
*
|
*
|
||||||
* @Override
|
* @Override
|
||||||
@ -65,14 +75,22 @@ import java.lang.annotation.Target;
|
|||||||
* return movieDto;
|
* return movieDto;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </code>
|
* </code></pre>
|
||||||
* </pre>
|
* <p>
|
||||||
|
* This annotation can also be used as a meta-annotation to define the condition strategy.
|
||||||
*
|
*
|
||||||
* @author Filip Hrisafov
|
* @author Filip Hrisafov
|
||||||
|
* @see SourceParameterCondition
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@Target({ ElementType.METHOD })
|
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||||
@Retention(RetentionPolicy.CLASS)
|
@Retention(RetentionPolicy.CLASS)
|
||||||
public @interface Condition {
|
public @interface Condition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the places where the condition should apply to
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
ConditionStrategy[] appliesTo() default ConditionStrategy.PROPERTIES;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
23
core/src/main/java/org/mapstruct/ConditionStrategy.java
Normal file
23
core/src/main/java/org/mapstruct/ConditionStrategy.java
Normal file
@ -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 org.mapstruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strategy for defining what to what a condition (check) method is applied to
|
||||||
|
*
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
public enum ConditionStrategy {
|
||||||
|
/**
|
||||||
|
* The condition method should be applied whether a property should be mapped.
|
||||||
|
*/
|
||||||
|
PROPERTIES,
|
||||||
|
/**
|
||||||
|
* The condition method should be applied to check if a source parameters should be mapped.
|
||||||
|
*/
|
||||||
|
SOURCE_PARAMETERS,
|
||||||
|
}
|
@ -98,7 +98,7 @@ public @interface EnumMapping {
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link MappingConstants#SUFFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
|
* <li>{@link MappingConstants#SUFFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
|
||||||
* suffix to the source enum</li>
|
* suffix to the source enum</li>
|
||||||
* <li>{@link MappingConstants#STRIP_SUFFIX_TRANSFORMATION} - strips the the given {@link #configuration()}
|
* <li>{@link MappingConstants#STRIP_SUFFIX_TRANSFORMATION} - strips the given {@link #configuration()}
|
||||||
* from the end of the source enum</li>
|
* from the end of the source enum</li>
|
||||||
* <li>{@link MappingConstants#PREFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
|
* <li>{@link MappingConstants#PREFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
|
||||||
* prefix to the source enum</li>
|
* prefix to the source enum</li>
|
||||||
|
67
core/src/main/java/org/mapstruct/Ignored.java
Normal file
67
core/src/main/java/org/mapstruct/Ignored.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the ignored of one bean attribute.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The name all attributes of for ignored is to be specified via {@link #targets()}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <strong>Example 1:</strong> Implicitly mapping fields with the same name:
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* // We need ignored Human.name and Human.lastName
|
||||||
|
* // we can use @Ignored with parameters "name", "lastName" {@link #targets()}
|
||||||
|
* @Mapper
|
||||||
|
* public interface HumanMapper {
|
||||||
|
* @Ignored( targets = { "name", "lastName" } )
|
||||||
|
* HumanDto toHumanDto(Human human)
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* // generates:
|
||||||
|
* @Override
|
||||||
|
* public HumanDto toHumanDto(Human human) {
|
||||||
|
* humanDto.setFullName( human.getFullName() );
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* @author Ivashin Aleksey
|
||||||
|
*/
|
||||||
|
@Repeatable(IgnoredList.class)
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
public @interface Ignored {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the specified properties should be ignored by the generated mapping method.
|
||||||
|
* This can be useful when certain attributes should not be propagated from source to target or when properties in
|
||||||
|
* the target object are populated using a decorator and thus would be reported as unmapped target property by
|
||||||
|
* default.
|
||||||
|
*
|
||||||
|
* @return The target names of the configured properties that should be ignored
|
||||||
|
*/
|
||||||
|
String[] targets();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prefix that should be applied to all the properties specified via {@link #targets()}.
|
||||||
|
*
|
||||||
|
* @return The target prefix to be applied to the defined properties
|
||||||
|
*/
|
||||||
|
String prefix() default "";
|
||||||
|
|
||||||
|
}
|
54
core/src/main/java/org/mapstruct/IgnoredList.java
Normal file
54
core/src/main/java/org/mapstruct/IgnoredList.java
Normal file
@ -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 org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the ignored list for several bean attributes.
|
||||||
|
* <p>
|
||||||
|
* <strong>TIP: When using Java 8 or later, you can omit the {@code @IgnoredList}
|
||||||
|
* wrapper annotation and directly specify several {@code @Ignored} annotations on one method.</strong>
|
||||||
|
*
|
||||||
|
* <p>These two examples are equal.
|
||||||
|
* </p>
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* // before Java 8
|
||||||
|
* @Mapper
|
||||||
|
* public interface MyMapper {
|
||||||
|
* @IgnoredList({
|
||||||
|
* @Ignored(targets = { "firstProperty" } ),
|
||||||
|
* @Ignored(targets = { "secondProperty" } )
|
||||||
|
* })
|
||||||
|
* HumanDto toHumanDto(Human human);
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* // Java 8 and later
|
||||||
|
* @Mapper
|
||||||
|
* public interface MyMapper {
|
||||||
|
* @Ignored(targets = { "firstProperty" } ),
|
||||||
|
* @Ignored(targets = { "secondProperty" } )
|
||||||
|
* HumanDto toHumanDto(Human human);
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* @author Ivashin Aleksey
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||||
|
public @interface IgnoredList {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration of the bean attributes.
|
||||||
|
*
|
||||||
|
* @return The configuration of the bean attributes.
|
||||||
|
*/
|
||||||
|
Ignored[] value();
|
||||||
|
}
|
@ -81,8 +81,8 @@ import java.lang.annotation.Target;
|
|||||||
public @interface InheritInverseConfiguration {
|
public @interface InheritInverseConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the inverse mapping method to inherit the mappings from. Needs only to be specified in case more than
|
* The name of the inverse mapping method to inherit the mappings from. Needs to be specified only in case more than
|
||||||
* one inverse method with matching source and target type exists.
|
* one inverse method exists with a matching source and target type exists.
|
||||||
*
|
*
|
||||||
* @return The name of the inverse mapping method to inherit the mappings from.
|
* @return The name of the inverse mapping method to inherit the mappings from.
|
||||||
*/
|
*/
|
||||||
|
@ -10,6 +10,7 @@ package org.mapstruct;
|
|||||||
* JSR330 / Jakarta.
|
* JSR330 / Jakarta.
|
||||||
*
|
*
|
||||||
* @author Kevin Grüneberg
|
* @author Kevin Grüneberg
|
||||||
|
* @author Lucas Resch
|
||||||
*/
|
*/
|
||||||
public enum InjectionStrategy {
|
public enum InjectionStrategy {
|
||||||
|
|
||||||
@ -17,5 +18,8 @@ public enum InjectionStrategy {
|
|||||||
FIELD,
|
FIELD,
|
||||||
|
|
||||||
/** Annotations are written on the constructor **/
|
/** Annotations are written on the constructor **/
|
||||||
CONSTRUCTOR
|
CONSTRUCTOR,
|
||||||
|
|
||||||
|
/** A dedicated setter method is created */
|
||||||
|
SETTER
|
||||||
}
|
}
|
||||||
|
@ -66,19 +66,38 @@ public @interface IterableMapping {
|
|||||||
/**
|
/**
|
||||||
* A format string as processable by {@link SimpleDateFormat} if the annotated method maps from an iterable of
|
* A format string as processable by {@link SimpleDateFormat} if the annotated method maps from an iterable of
|
||||||
* {@code String} to an iterable {@link Date} or vice-versa. Will be ignored for all other element types.
|
* {@code String} to an iterable {@link Date} or vice-versa. Will be ignored for all other element types.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is also specified, the format will consider the specified locale when processing
|
||||||
|
* the date. Otherwise, the system's default locale will be used.
|
||||||
*
|
*
|
||||||
* @return A date format string as processable by {@link SimpleDateFormat}.
|
* @return A date format string as processable by {@link SimpleDateFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String dateFormat() default "";
|
String dateFormat() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other element types.
|
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other element types.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is also specified, the number format will be applied in the context of the given locale.
|
||||||
|
* Otherwise, the system's default locale will be used to process the number format.
|
||||||
*
|
*
|
||||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String numberFormat() default "";
|
String numberFormat() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the locale to be used when processing {@link #dateFormat()} or {@link #numberFormat()}.
|
||||||
|
* <p>
|
||||||
|
* The locale should be a plain tag representing the language, such as "en" for English, "de" for German, etc.
|
||||||
|
* <p>
|
||||||
|
* If no locale is specified, the system's default locale will be used.
|
||||||
|
*
|
||||||
|
* @return A string representing the locale to be used when formatting dates or numbers.
|
||||||
|
*/
|
||||||
|
String locale() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple
|
* A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple
|
||||||
* mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error.
|
* mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error.
|
||||||
|
115
core/src/main/java/org/mapstruct/Javadoc.java
Normal file
115
core/src/main/java/org/mapstruct/Javadoc.java
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the definition of Javadoc comments in the MapStruct <code>Mapper</code> generated class.
|
||||||
|
*
|
||||||
|
* <p>The annotation provides support for the usual Javadoc comments elements by defining analogous attributes.</p>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>Please, note that at least one of these attributes must be specified.</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For instance, the following definition;
|
||||||
|
* </p>
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* @Javadoc(
|
||||||
|
* value = "This is the description",
|
||||||
|
* authors = { "author1", "author2" },
|
||||||
|
* deprecated = "Use {@link OtherMapper} instead",
|
||||||
|
* since = "0.1"
|
||||||
|
* )
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* will generate:
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* /**
|
||||||
|
* * This is the description
|
||||||
|
* *
|
||||||
|
* * @author author1
|
||||||
|
* * @author author2
|
||||||
|
* *
|
||||||
|
* * @deprecated Use {@link OtherMapper} instead
|
||||||
|
* * @since 0.1
|
||||||
|
* */
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The entire Javadoc comment block can be passed directly:
|
||||||
|
* </p>
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* @Javadoc("This is the description\n"
|
||||||
|
* + "\n"
|
||||||
|
* + "@author author1\n"
|
||||||
|
* + "@author author2\n"
|
||||||
|
* + "\n"
|
||||||
|
* + "@deprecated Use {@link OtherMapper} instead\n"
|
||||||
|
* + "@since 0.1\n"
|
||||||
|
* )
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* // or using Text Blocks
|
||||||
|
* @Javadoc(
|
||||||
|
* """
|
||||||
|
* This is the description
|
||||||
|
*
|
||||||
|
* @author author1
|
||||||
|
* @author author2
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link OtherMapper} instead
|
||||||
|
* @since 0.1
|
||||||
|
* """
|
||||||
|
* )
|
||||||
|
* </code></pre>
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Javadoc {
|
||||||
|
/**
|
||||||
|
* Main Javadoc comment text block.
|
||||||
|
*
|
||||||
|
* @return Main Javadoc comment text block.
|
||||||
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of authors of the code that it is being documented.
|
||||||
|
* <p>
|
||||||
|
* It will generate a list of the Javadoc tool comment element <code>@author</code>
|
||||||
|
* with the different values and in the order provided.
|
||||||
|
*
|
||||||
|
* @return array of javadoc authors.
|
||||||
|
*/
|
||||||
|
String[] authors() default { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that the functionality that is being documented is deprecated.
|
||||||
|
* <p>
|
||||||
|
* Corresponds to the <code>@deprecated</code> Javadoc tool comment element.
|
||||||
|
*
|
||||||
|
* @return Deprecation message about the documented functionality
|
||||||
|
*/
|
||||||
|
String deprecated() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the version since the functionality that is being documented is available.
|
||||||
|
* <p>
|
||||||
|
* Corresponds to the <code>@since</code> Javadoc tool comment element.
|
||||||
|
*
|
||||||
|
* @return Version since the functionality is available
|
||||||
|
*/
|
||||||
|
String since() default "";
|
||||||
|
}
|
@ -56,8 +56,12 @@ public @interface MapMapping {
|
|||||||
/**
|
/**
|
||||||
* A format string as processable by {@link SimpleDateFormat} if the annotated method maps from a map with key type
|
* A format string as processable by {@link SimpleDateFormat} if the annotated method maps from a map with key type
|
||||||
* {@code String} to an map with key type {@link Date} or vice-versa. Will be ignored for all other key types.
|
* {@code String} to an map with key type {@link Date} or vice-versa. Will be ignored for all other key types.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is specified, the format will consider the specified locale when processing the date.
|
||||||
|
* Otherwise, the system's default locale will be used.
|
||||||
*
|
*
|
||||||
* @return A date format string as processable by {@link SimpleDateFormat}.
|
* @return A date format string as processable by {@link SimpleDateFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String keyDateFormat() default "";
|
String keyDateFormat() default "";
|
||||||
|
|
||||||
@ -65,27 +69,50 @@ public @interface MapMapping {
|
|||||||
* A format string as processable by {@link SimpleDateFormat} if the annotated method maps from a map with value
|
* A format string as processable by {@link SimpleDateFormat} if the annotated method maps from a map with value
|
||||||
* type {@code String} to an map with value type {@link Date} or vice-versa. Will be ignored for all other value
|
* type {@code String} to an map with value type {@link Date} or vice-versa. Will be ignored for all other value
|
||||||
* types.
|
* types.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is specified, the format will consider the specified locale when processing the date.
|
||||||
|
* Otherwise, the system's default locale will be used.
|
||||||
*
|
*
|
||||||
* @return A date format string as processable by {@link SimpleDateFormat}.
|
* @return A date format string as processable by {@link SimpleDateFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String valueDateFormat() default "";
|
String valueDateFormat() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other key types.
|
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other key types.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is specified, the number format will be applied in the context of the given locale.
|
||||||
|
* Otherwise, the system's default locale will be used.
|
||||||
*
|
*
|
||||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String keyNumberFormat() default "";
|
String keyNumberFormat() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other value types.
|
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other value types.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is specified, the number format will be applied in the context of the given locale.
|
||||||
|
* Otherwise, the system's default locale will be used.
|
||||||
*
|
*
|
||||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String valueNumberFormat() default "";
|
String valueNumberFormat() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the locale to be used when processing {@link SimpleDateFormat} or {@link DecimalFormat} for key or
|
||||||
|
* value mappings in maps. The locale should be a plain tag representing the language, such as "en" for English,
|
||||||
|
* "de" for German, etc.
|
||||||
|
* <p>
|
||||||
|
* If no locale is specified, the system's default locale will be used.
|
||||||
|
*
|
||||||
|
* @return A string representing the locale to be used when formatting dates or numbers in maps.
|
||||||
|
*/
|
||||||
|
String locale() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key value qualifier can be specified to aid the selection process of a suitable mapper. This is useful in
|
* A key value qualifier can be specified to aid the selection process of a suitable mapper. This is useful in
|
||||||
* case multiple mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found'
|
* case multiple mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found'
|
||||||
|
@ -74,6 +74,7 @@ import static org.mapstruct.SubclassExhaustiveStrategy.COMPILE_ERROR;
|
|||||||
* </code></pre>
|
* </code></pre>
|
||||||
*
|
*
|
||||||
* @author Gunnar Morling
|
* @author Gunnar Morling
|
||||||
|
* @see Javadoc
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.CLASS)
|
@Retention(RetentionPolicy.CLASS)
|
||||||
@ -280,6 +281,18 @@ public @interface Mapper {
|
|||||||
*/
|
*/
|
||||||
SubclassExhaustiveStrategy subclassExhaustiveStrategy() default COMPILE_ERROR;
|
SubclassExhaustiveStrategy subclassExhaustiveStrategy() default COMPILE_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the exception type to be thrown when a missing subclass implementation is detected
|
||||||
|
* in combination with {@link SubclassMappings}, based on the {@link #subclassExhaustiveStrategy()}.
|
||||||
|
* <p>
|
||||||
|
* This exception will only be thrown when the {@code subclassExhaustiveStrategy} is set to
|
||||||
|
* {@link SubclassExhaustiveStrategy#RUNTIME_EXCEPTION}.
|
||||||
|
*
|
||||||
|
* @return the exception class to throw when missing implementations are found.
|
||||||
|
* Defaults to {@link IllegalArgumentException}.
|
||||||
|
*/
|
||||||
|
Class<? extends Exception> subclassExhaustiveException() default IllegalArgumentException.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether to use field or constructor injection. This is only used on annotated based component models
|
* Determines whether to use field or constructor injection. This is only used on annotated based component models
|
||||||
* such as CDI, Spring and JSR 330.
|
* such as CDI, Spring and JSR 330.
|
||||||
@ -298,7 +311,7 @@ public @interface Mapper {
|
|||||||
* Can be configured by the {@link MapperConfig#disableSubMappingMethodsGeneration()} as well.
|
* Can be configured by the {@link MapperConfig#disableSubMappingMethodsGeneration()} as well.
|
||||||
* <p>
|
* <p>
|
||||||
* Note: If you need to use {@code disableSubMappingMethodsGeneration} please contact the MapStruct team at
|
* Note: If you need to use {@code disableSubMappingMethodsGeneration} please contact the MapStruct team at
|
||||||
* <a href="http://mapstruct.org">mapstruct.org</a> or
|
* <a href="https://mapstruct.org">mapstruct.org</a> or
|
||||||
* <a href="https://github.com/mapstruct/mapstruct">github.com/mapstruct/mapstruct</a> to share what problem you
|
* <a href="https://github.com/mapstruct/mapstruct">github.com/mapstruct/mapstruct</a> to share what problem you
|
||||||
* are facing with the automatic sub-mapping generation.
|
* are facing with the automatic sub-mapping generation.
|
||||||
*
|
*
|
||||||
|
@ -249,6 +249,18 @@ public @interface MapperConfig {
|
|||||||
*/
|
*/
|
||||||
SubclassExhaustiveStrategy subclassExhaustiveStrategy() default COMPILE_ERROR;
|
SubclassExhaustiveStrategy subclassExhaustiveStrategy() default COMPILE_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the exception type to be thrown when a missing subclass implementation is detected
|
||||||
|
* in combination with {@link SubclassMappings}, based on the {@link #subclassExhaustiveStrategy()}.
|
||||||
|
* <p>
|
||||||
|
* This exception will only be thrown when the {@code subclassExhaustiveStrategy} is set to
|
||||||
|
* {@link SubclassExhaustiveStrategy#RUNTIME_EXCEPTION}.
|
||||||
|
*
|
||||||
|
* @return the exception class to throw when missing implementations are found.
|
||||||
|
* Defaults to {@link IllegalArgumentException}.
|
||||||
|
*/
|
||||||
|
Class<? extends Exception> subclassExhaustiveException() default IllegalArgumentException.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether to use field or constructor injection. This is only used on annotated based component models
|
* Determines whether to use field or constructor injection. This is only used on annotated based component models
|
||||||
* such as CDI, Spring and JSR 330.
|
* such as CDI, Spring and JSR 330.
|
||||||
@ -269,7 +281,7 @@ public @interface MapperConfig {
|
|||||||
* Can be overridden by {@link Mapper#disableSubMappingMethodsGeneration()}
|
* Can be overridden by {@link Mapper#disableSubMappingMethodsGeneration()}
|
||||||
* <p>
|
* <p>
|
||||||
* Note: If you need to use {@code disableSubMappingMethodsGeneration} please contact the MapStruct team at
|
* Note: If you need to use {@code disableSubMappingMethodsGeneration} please contact the MapStruct team at
|
||||||
* <a href="http://mapstruct.org">mapstruct.org</a> or
|
* <a href="https://mapstruct.org">mapstruct.org</a> or
|
||||||
* <a href="https://github.com/mapstruct/mapstruct">github.com/mapstruct/mapstruct</a> to share what problem you
|
* <a href="https://github.com/mapstruct/mapstruct">github.com/mapstruct/mapstruct</a> to share what problem you
|
||||||
* are facing with the automatic sub-mapping generation.
|
* are facing with the automatic sub-mapping generation.
|
||||||
*
|
*
|
||||||
|
@ -20,7 +20,7 @@ import org.mapstruct.control.MappingControl;
|
|||||||
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the mapping of one bean attribute or enum constant.
|
* Configures the mapping of one bean attribute.
|
||||||
* <p>
|
* <p>
|
||||||
* The name of the mapped attribute or constant is to be specified via {@link #target()}. For mapped bean attributes it
|
* The name of the mapped attribute or constant is to be specified via {@link #target()}. For mapped bean attributes it
|
||||||
* is assumed by default that the attribute has the same name in the source bean. Alternatively, one of
|
* is assumed by default that the attribute has the same name in the source bean. Alternatively, one of
|
||||||
@ -136,9 +136,6 @@ import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
|||||||
* }
|
* }
|
||||||
* </code></pre>
|
* </code></pre>
|
||||||
*
|
*
|
||||||
* <b>IMPORTANT NOTE:</b> the enum mapping capability is deprecated and replaced by {@link ValueMapping} it
|
|
||||||
* will be removed in subsequent versions.
|
|
||||||
*
|
|
||||||
* @author Gunnar Morling
|
* @author Gunnar Morling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -178,19 +175,38 @@ public @interface Mapping {
|
|||||||
/**
|
/**
|
||||||
* A format string as processable by {@link SimpleDateFormat} if the attribute is mapped from {@code String} to
|
* A format string as processable by {@link SimpleDateFormat} if the attribute is mapped from {@code String} to
|
||||||
* {@link Date} or vice-versa. Will be ignored for all other attribute types and when mapping enum constants.
|
* {@link Date} or vice-versa. Will be ignored for all other attribute types and when mapping enum constants.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is also specified, the format will consider the specified locale when processing
|
||||||
|
* the date. Otherwise, the system's default locale will be used.
|
||||||
*
|
*
|
||||||
* @return A date format string as processable by {@link SimpleDateFormat}.
|
* @return A date format string as processable by {@link SimpleDateFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String dateFormat() default "";
|
String dateFormat() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other element types.
|
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other element types.
|
||||||
|
* <p>
|
||||||
|
* If the {@link #locale()} is also specified, the number format will be applied in the context of the given locale.
|
||||||
|
* Otherwise, the system's default locale will be used to process the number format.
|
||||||
*
|
*
|
||||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||||
|
* @see #locale()
|
||||||
*/
|
*/
|
||||||
String numberFormat() default "";
|
String numberFormat() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the locale to be used when processing {@link #dateFormat()} or {@link #numberFormat()}.
|
||||||
|
* <p>
|
||||||
|
* The locale should be a plain tag representing the language, such as "en" for English, "de" for German, etc.
|
||||||
|
* <p>
|
||||||
|
* If no locale is specified, the system's default locale will be used.
|
||||||
|
*
|
||||||
|
* @return A string representing the locale to be used when formatting dates or numbers.
|
||||||
|
*/
|
||||||
|
String locale() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constant {@link String} based on which the specified target property is to be set.
|
* A constant {@link String} based on which the specified target property is to be set.
|
||||||
* <p>
|
* <p>
|
||||||
@ -287,9 +303,12 @@ public @interface Mapping {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the property specified via {@link #target()} should be ignored by the generated mapping method or not.
|
* Whether the property specified via {@link #target()} should be ignored by the generated mapping method or not.
|
||||||
* This can be useful when certain attributes should not be propagated from source or target or when properties in
|
* This can be useful when certain attributes should not be propagated from source to target or when properties in
|
||||||
* the target object are populated using a decorator and thus would be reported as unmapped target property by
|
* the target object are populated using a decorator and thus would be reported as unmapped target property by
|
||||||
* default.
|
* default.
|
||||||
|
* <p>
|
||||||
|
* If you have multiple properties to ignore,
|
||||||
|
* you can use the {@link Ignored} annotation instead and group them all at once.
|
||||||
*
|
*
|
||||||
* @return {@code true} if the given property should be ignored, {@code false} otherwise
|
* @return {@code true} if the given property should be ignored, {@code false} otherwise
|
||||||
*/
|
*/
|
||||||
|
@ -109,7 +109,12 @@ public final class MappingConstants {
|
|||||||
public static final String DEFAULT = "default";
|
public static final String DEFAULT = "default";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
|
* The generated mapper is an application-scoped CDI bean and can be retrieved via @Inject.
|
||||||
|
* The annotations are either from {@code javax} or {@code jakarta}.
|
||||||
|
* Priority have the {@code javax} annotations.
|
||||||
|
* In case you want to only use Jakarta then use {@link #JAKARTA_CDI}.
|
||||||
|
*
|
||||||
|
* @see #JAKARTA_CDI
|
||||||
*/
|
*/
|
||||||
public static final String CDI = "cdi";
|
public static final String CDI = "cdi";
|
||||||
|
|
||||||
@ -138,6 +143,12 @@ public final class MappingConstants {
|
|||||||
*/
|
*/
|
||||||
public static final String JAKARTA = "jakarta";
|
public static final String JAKARTA = "jakarta";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The generated mapper is an application-scoped Jakarta CDI bean and can be retrieved via @Inject.
|
||||||
|
* @see #CDI
|
||||||
|
*/
|
||||||
|
public static final String JAKARTA_CDI = "jakarta-cdi";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
15
core/src/main/java/org/mapstruct/NullEnum.java
Normal file
15
core/src/main/java/org/mapstruct/NullEnum.java
Normal file
@ -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 org.mapstruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used as a default value for enum class annotation elements.
|
||||||
|
*
|
||||||
|
* @author Ben Zegveld
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
enum NullEnum {
|
||||||
|
}
|
@ -8,7 +8,7 @@ package org.mapstruct;
|
|||||||
/**
|
/**
|
||||||
* Strategy for dealing with null source values.
|
* Strategy for dealing with null source values.
|
||||||
*
|
*
|
||||||
* <b>Note:</b> This strategy is not in effect when the a specific source presence check method is defined
|
* <b>Note:</b> This strategy is not in effect when a specific source presence check method is defined
|
||||||
* in the service provider interface (SPI).
|
* in the service provider interface (SPI).
|
||||||
* <p>
|
* <p>
|
||||||
* <b>Note</b>: some types of mappings (collections, maps), in which MapStruct is instructed to use a getter or adder
|
* <b>Note</b>: some types of mappings (collections, maps), in which MapStruct is instructed to use a getter or adder
|
||||||
|
@ -10,7 +10,7 @@ package org.mapstruct;
|
|||||||
* {@link NullValuePropertyMappingStrategy} can be defined on {@link MapperConfig}, {@link Mapper}, {@link BeanMapping}
|
* {@link NullValuePropertyMappingStrategy} can be defined on {@link MapperConfig}, {@link Mapper}, {@link BeanMapping}
|
||||||
* and {@link Mapping}.
|
* and {@link Mapping}.
|
||||||
* Precedence is arranged in the reverse order. So {@link Mapping} will override {@link BeanMapping}, will
|
* Precedence is arranged in the reverse order. So {@link Mapping} will override {@link BeanMapping}, will
|
||||||
* overide {@link Mapper}
|
* override {@link Mapper}
|
||||||
*
|
*
|
||||||
* The enum <b>only applies to update methods</b>: methods that update a pre-existing target (annotated with
|
* The enum <b>only applies to update methods</b>: methods that update a pre-existing target (annotated with
|
||||||
* {@code @}{@link MappingTarget}).
|
* {@code @}{@link MappingTarget}).
|
||||||
|
@ -21,6 +21,7 @@ import java.lang.annotation.Target;
|
|||||||
* <li>{@link IterableMapping#qualifiedBy() }</li>
|
* <li>{@link IterableMapping#qualifiedBy() }</li>
|
||||||
* <li>{@link MapMapping#keyQualifiedBy() }</li>
|
* <li>{@link MapMapping#keyQualifiedBy() }</li>
|
||||||
* <li>{@link MapMapping#valueQualifiedBy() }</li>
|
* <li>{@link MapMapping#valueQualifiedBy() }</li>
|
||||||
|
* <li>{@link SubclassMapping#qualifiedBy() }</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p><strong>Example:</strong></p>
|
* <p><strong>Example:</strong></p>
|
||||||
* <pre><code class='java'>
|
* <pre><code class='java'>
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation marks a method as a <em>check method</em> to check if a source parameter needs to be mapped.
|
||||||
|
* <p>
|
||||||
|
* By default, source parameters are checked against {@code null}, unless they are primitives.
|
||||||
|
* <p>
|
||||||
|
* Check methods have to return {@code boolean}.
|
||||||
|
* The following parameters are accepted for the presence check methods:
|
||||||
|
* <ul>
|
||||||
|
* <li>The mapping source parameter</li>
|
||||||
|
* <li>{@code @}{@link Context} parameter</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <strong>Note:</strong> The usage of this annotation is <em>mandatory</em>
|
||||||
|
* for a method to be considered as a source check method.
|
||||||
|
*
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* public class PresenceCheckUtils {
|
||||||
|
*
|
||||||
|
* @SourceParameterCondition
|
||||||
|
* public static boolean isDefined(Car car) {
|
||||||
|
* return car != null && car.getId() != null;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @Mapper(uses = PresenceCheckUtils.class)
|
||||||
|
* public interface CarMapper {
|
||||||
|
*
|
||||||
|
* CarDto map(Car car);
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* The following implementation of {@code CarMapper} will be generated:
|
||||||
|
*
|
||||||
|
* <pre><code class='java'>
|
||||||
|
* public class CarMapperImpl implements CarMapper {
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* public CarDto map(Car car) {
|
||||||
|
* if ( !PresenceCheckUtils.isDefined( car ) ) {
|
||||||
|
* return null;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* CarDto carDto = new CarDto();
|
||||||
|
*
|
||||||
|
* carDto.setId( car.getId() );
|
||||||
|
* // ...
|
||||||
|
*
|
||||||
|
* return carDto;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
* @since 1.6
|
||||||
|
* @see Condition @Condition
|
||||||
|
*/
|
||||||
|
@Target({ ElementType.METHOD })
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
@Condition(appliesTo = ConditionStrategy.SOURCE_PARAMETERS)
|
||||||
|
public @interface SourceParameterCondition {
|
||||||
|
|
||||||
|
}
|
26
core/src/main/java/org/mapstruct/SourcePropertyName.java
Normal file
26
core/src/main/java/org/mapstruct/SourcePropertyName.java
Normal file
@ -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 org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation marks a <em>presence check method</em> parameter as a source property name parameter.
|
||||||
|
* <p>
|
||||||
|
* This parameter enables conditional filtering based on source property name at run-time.
|
||||||
|
* Parameter must be of type {@link String} and can be present only in {@link Condition} method.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Oliver Erhart
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
public @interface SourcePropertyName {
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct;
|
package org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Repeatable;
|
import java.lang.annotation.Repeatable;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@ -48,7 +49,7 @@ import org.mapstruct.util.Experimental;
|
|||||||
* }
|
* }
|
||||||
* </code></pre>
|
* </code></pre>
|
||||||
* <strong>Example 2:</strong> For parents that can be created. (e.g. normal classes or interfaces with
|
* <strong>Example 2:</strong> For parents that can be created. (e.g. normal classes or interfaces with
|
||||||
* @Mappper( uses = ObjectFactory.class ) )
|
* @Mapper( uses = ObjectFactory.class ) )
|
||||||
* <pre><code class='java'>
|
* <pre><code class='java'>
|
||||||
* // generates
|
* // generates
|
||||||
* @Override
|
* @Override
|
||||||
@ -81,4 +82,29 @@ public @interface SubclassMapping {
|
|||||||
* @return the target subclass to map the source to.
|
* @return the target subclass to map the source to.
|
||||||
*/
|
*/
|
||||||
Class<?> target();
|
Class<?> target();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @return the qualifiers
|
||||||
|
* @see Qualifier
|
||||||
|
*/
|
||||||
|
Class<? extends Annotation>[] 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
|
||||||
|
* for each of the specified qualifier names.
|
||||||
|
* <p>
|
||||||
|
* Note that annotation-based qualifiers are generally preferable as they allow more easily to find references and
|
||||||
|
* are safe for refactorings, but name-based qualifiers can be a less verbose alternative when requiring a large
|
||||||
|
* number of qualifiers as no custom annotation types are needed.
|
||||||
|
*
|
||||||
|
* @return One or more qualifier name(s)
|
||||||
|
* @see #qualifiedBy()
|
||||||
|
* @see Named
|
||||||
|
*/
|
||||||
|
String[] qualifiedByName() default {};
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ import org.mapstruct.util.Experimental;
|
|||||||
* @author Ben Zegveld
|
* @author Ben Zegveld
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.METHOD)
|
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||||
@Retention(RetentionPolicy.CLASS)
|
@Retention(RetentionPolicy.CLASS)
|
||||||
@Experimental
|
@Experimental
|
||||||
public @interface SubclassMappings {
|
public @interface SubclassMappings {
|
||||||
|
25
core/src/main/java/org/mapstruct/TargetPropertyName.java
Normal file
25
core/src/main/java/org/mapstruct/TargetPropertyName.java
Normal file
@ -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 org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation marks a <em>presence check method</em> parameter as a target property name parameter.
|
||||||
|
* <p>
|
||||||
|
* This parameter enables conditional filtering based on target property name at run-time.
|
||||||
|
* Parameter must be of type {@link String} and can be present only in {@link Condition} method.
|
||||||
|
* </p>
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
public @interface TargetPropertyName {
|
||||||
|
}
|
@ -84,7 +84,7 @@ import java.lang.annotation.Target;
|
|||||||
*/
|
*/
|
||||||
@Repeatable(ValueMappings.class)
|
@Repeatable(ValueMappings.class)
|
||||||
@Retention(RetentionPolicy.CLASS)
|
@Retention(RetentionPolicy.CLASS)
|
||||||
@Target(ElementType.METHOD)
|
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface ValueMapping {
|
public @interface ValueMapping {
|
||||||
/**
|
/**
|
||||||
* The source value constant to use for this mapping.
|
* The source value constant to use for this mapping.
|
||||||
|
@ -40,7 +40,7 @@ import java.lang.annotation.Target;
|
|||||||
*
|
*
|
||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.METHOD)
|
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
@Retention(RetentionPolicy.CLASS)
|
@Retention(RetentionPolicy.CLASS)
|
||||||
public @interface ValueMappings {
|
public @interface ValueMappings {
|
||||||
|
|
||||||
|
@ -13,6 +13,6 @@
|
|||||||
* This package contains several annotations which allow to configure how mapper interfaces are generated.
|
* This package contains several annotations which allow to configure how mapper interfaces are generated.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see <a href="http://mapstruct.org/">MapStruct reference documentation</a>
|
* @see <a href="https://mapstruct.org/">MapStruct reference documentation</a>
|
||||||
*/
|
*/
|
||||||
package org.mapstruct;
|
package org.mapstruct;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
<artifactId>mapstruct-parent</artifactId>
|
<artifactId>mapstruct-parent</artifactId>
|
||||||
<version>1.6.0-SNAPSHOT</version>
|
<version>1.7.0-SNAPSHOT</version>
|
||||||
<relativePath>../parent/pom.xml</relativePath>
|
<relativePath>../parent/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@ -39,6 +39,13 @@
|
|||||||
<groupId>org.mapstruct.tools.gem</groupId>
|
<groupId>org.mapstruct.tools.gem</groupId>
|
||||||
<artifactId>gem-api</artifactId>
|
<artifactId>gem-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.xml.bind</groupId>
|
||||||
|
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -59,7 +66,7 @@
|
|||||||
<groupId>org.freemarker</groupId>
|
<groupId>org.freemarker</groupId>
|
||||||
<artifactId>freemarker</artifactId>
|
<artifactId>freemarker</artifactId>
|
||||||
<outputDirectory>${project.build.directory}/freemarker-unpacked</outputDirectory>
|
<outputDirectory>${project.build.directory}/freemarker-unpacked</outputDirectory>
|
||||||
<includes>META-INF/LICENSE.txt,META-INF/NOTICE.txt</includes>
|
<includes>META-INF/LICENSE</includes>
|
||||||
</artifactItem>
|
</artifactItem>
|
||||||
</artifactItems>
|
</artifactItems>
|
||||||
</configuration>
|
</configuration>
|
||||||
@ -93,7 +100,7 @@
|
|||||||
<doctitle>MapStruct ${project.version}</doctitle>
|
<doctitle>MapStruct ${project.version}</doctitle>
|
||||||
<windowtitle>MapStruct ${project.version}</windowtitle>
|
<windowtitle>MapStruct ${project.version}</windowtitle>
|
||||||
<bottom>
|
<bottom>
|
||||||
<![CDATA[Copyright © ${project.inceptionYear}-{currentYear} <a href="http://mapstruct.org/">MapStruct Authors</a>; All rights reserved. Released under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache Software License 2.0</a>.]]>
|
<![CDATA[Copyright © ${project.inceptionYear}-{currentYear} <a href="https://mapstruct.org/">MapStruct Authors</a>; All rights reserved. Released under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache Software License 2.0</a>.]]>
|
||||||
</bottom>
|
</bottom>
|
||||||
|
|
||||||
<groups>
|
<groups>
|
||||||
@ -123,7 +130,7 @@
|
|||||||
<!--
|
<!--
|
||||||
There is a bug in JDK 11 (https://bugs.openjdk.java.net/browse/JDK-8215291) which doesn't work correctly when searching and adds undefined.
|
There is a bug in JDK 11 (https://bugs.openjdk.java.net/browse/JDK-8215291) which doesn't work correctly when searching and adds undefined.
|
||||||
It has been fixed since JDK 12, but not yet backported to JDK 11 (https://bugs.openjdk.java.net/browse/JDK-8244171).
|
It has been fixed since JDK 12, but not yet backported to JDK 11 (https://bugs.openjdk.java.net/browse/JDK-8244171).
|
||||||
One workardound is https://stackoverflow.com/a/57284322/1115491.
|
One workaround is https://stackoverflow.com/a/57284322/1115491.
|
||||||
-->
|
-->
|
||||||
<bottom>
|
<bottom>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
@ -155,7 +162,7 @@
|
|||||||
<descriptor>${basedir}/src/main/assembly/dist.xml</descriptor>
|
<descriptor>${basedir}/src/main/assembly/dist.xml</descriptor>
|
||||||
</descriptors>
|
</descriptors>
|
||||||
<finalName>mapstruct-${project.version}</finalName>
|
<finalName>mapstruct-${project.version}</finalName>
|
||||||
<tarLongFileMode>gnu</tarLongFileMode>
|
<tarLongFileMode>posix</tarLongFileMode>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
@ -187,7 +194,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
<artifactId>jaxb-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
<version>2.3.1</version>
|
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
@ -42,11 +42,7 @@
|
|||||||
<outputDirectory>/</outputDirectory>
|
<outputDirectory>/</outputDirectory>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
<file>
|
||||||
<source>target/freemarker-unpacked/META-INF/NOTICE.txt</source>
|
<source>target/freemarker-unpacked/META-INF/LICENSE</source>
|
||||||
<outputDirectory>/</outputDirectory>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<source>target/freemarker-unpacked/META-INF/LICENSE.txt</source>
|
|
||||||
<outputDirectory>etc/freemarker</outputDirectory>
|
<outputDirectory>etc/freemarker</outputDirectory>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
<file>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
<artifactId>mapstruct-parent</artifactId>
|
<artifactId>mapstruct-parent</artifactId>
|
||||||
<version>1.6.0-SNAPSHOT</version>
|
<version>1.7.0-SNAPSHOT</version>
|
||||||
<relativePath>../parent/pom.xml</relativePath>
|
<relativePath>../parent/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -141,6 +141,8 @@ In the case that the `Fruit` is an abstract class or an interface, you would get
|
|||||||
To allow mappings for abstract classes or interfaces you need to set the `subclassExhaustiveStrategy` to `RUNTIME_EXCEPTION`, you can do this at the `@MapperConfig`, `@Mapper` or `@BeanMapping` annotations. If you then pass a `GrapeDto` an `IllegalArgumentException` will be thrown because it is unknown how to map a `GrapeDto`.
|
To allow mappings for abstract classes or interfaces you need to set the `subclassExhaustiveStrategy` to `RUNTIME_EXCEPTION`, you can do this at the `@MapperConfig`, `@Mapper` or `@BeanMapping` annotations. If you then pass a `GrapeDto` an `IllegalArgumentException` will be thrown because it is unknown how to map a `GrapeDto`.
|
||||||
Adding the missing (`@SubclassMapping`) for it will fix that.
|
Adding the missing (`@SubclassMapping`) for it will fix that.
|
||||||
|
|
||||||
|
<<selection-based-on-qualifiers>> can be used to further control which methods may be chosen to map a specific subclass. For that, you will need to use one of `SubclassMapping#qualifiedByName` or `SubclassMapping#qualifiedBy`.
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
If the mapping method for the subclasses does not exist it will be created and any other annotations on the fruit mapping method will be inherited by the newly generated mappings.
|
If the mapping method for the subclasses does not exist it will be created and any other annotations on the fruit mapping method will be inherited by the newly generated mappings.
|
||||||
@ -279,7 +281,7 @@ First calling a mapping method on the source property is not protected by a null
|
|||||||
|
|
||||||
The option `nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS` will always include a null check when source is non primitive, unless a source presence checker is defined on the source bean.
|
The option `nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS` will always include a null check when source is non primitive, unless a source presence checker is defined on the source bean.
|
||||||
|
|
||||||
The strategy works in a hierarchical fashion. `@Mapping#nullValueCheckStrategy` will override `@BeanMapping#nullValueCheckStrategy`, `@BeanMapping#nullValueCheckStrategy` will override `@Mapper#nullValueCheckStrategy` and `@Mapper#nullValueCheckStrategy` will override `@MaperConfig#nullValueCheckStrategy`.
|
The strategy works in a hierarchical fashion. `@Mapping#nullValueCheckStrategy` will override `@BeanMapping#nullValueCheckStrategy`, `@BeanMapping#nullValueCheckStrategy` will override `@Mapper#nullValueCheckStrategy` and `@Mapper#nullValueCheckStrategy` will override `@MapperConfig#nullValueCheckStrategy`.
|
||||||
|
|
||||||
[[source-presence-check]]
|
[[source-presence-check]]
|
||||||
=== Source presence checking
|
=== Source presence checking
|
||||||
@ -292,7 +294,7 @@ The source presence checker name can be changed in the MapStruct service provide
|
|||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
Some types of mappings (collections, maps), in which MapStruct is instructed to use a getter or adder as target accessor see `CollectionMappingStrategy`, MapStruct will always generate a source property
|
Some types of mappings (collections, maps), in which MapStruct is instructed to use a getter or adder as target accessor (see `CollectionMappingStrategy`), MapStruct will always generate a source property
|
||||||
null check, regardless the value of the `NullValueCheckStrategy` to avoid addition of `null` to the target collection or map.
|
null check, regardless the value of the `NullValueCheckStrategy` to avoid addition of `null` to the target collection or map.
|
||||||
====
|
====
|
||||||
|
|
||||||
@ -301,10 +303,12 @@ null check, regardless the value of the `NullValueCheckStrategy` to avoid additi
|
|||||||
|
|
||||||
Conditional Mapping is a type of <<source-presence-check>>.
|
Conditional Mapping is a type of <<source-presence-check>>.
|
||||||
The difference is that it allows users to write custom condition methods that will be invoked to check if a property needs to be mapped or not.
|
The difference is that it allows users to write custom condition methods that will be invoked to check if a property needs to be mapped or not.
|
||||||
|
Conditional mapping can also be used to check if a source parameter should be mapped or not.
|
||||||
|
|
||||||
A custom condition method is a method that is annotated with `org.mapstruct.Condition` and returns `boolean`.
|
A custom condition method for properties is a method that is annotated with `org.mapstruct.Condition` and returns `boolean`.
|
||||||
|
A custom condition method for source parameters is annotated with `org.mapstruct.SourceParameterCondition`, `org.mapstruct.Condition(appliesTo = org.mapstruct.ConditionStrategy#SOURCE_PARAMETERS)` or meta-annotated with `Condition(appliesTo = ConditionStrategy#SOURCE_PARAMETERS)`
|
||||||
|
|
||||||
e.g. if you only want to map a String property when it is not `null, and it is not empty then you can do something like:
|
e.g. if you only want to map a String property when it is not `null` and not empty then you can do something like:
|
||||||
|
|
||||||
.Mapper using custom condition check method
|
.Mapper using custom condition check method
|
||||||
====
|
====
|
||||||
@ -404,6 +408,69 @@ public class CarMapperImpl implements CarMapper {
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
Additionally `@TargetPropertyName` or `@SourcePropertyName` of type `java.lang.String` can be used in custom condition check method:
|
||||||
|
|
||||||
|
.Mapper using custom condition check method with `@TargetPropertyName` and `@SourcePropertyName`
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
public interface CarMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "owner", source = "ownerName")
|
||||||
|
CarDto carToCarDto(Car car, @MappingTarget CarDto carDto);
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
default boolean isNotEmpty(
|
||||||
|
String value,
|
||||||
|
@TargetPropertyName String targetPropertyName,
|
||||||
|
@SourcePropertyName String sourcePropertyName
|
||||||
|
) {
|
||||||
|
|
||||||
|
if ( targetPropertyName.equals( "owner" )
|
||||||
|
&& sourcePropertyName.equals( "ownerName" ) ) {
|
||||||
|
|
||||||
|
return value != null
|
||||||
|
&& !value.isEmpty()
|
||||||
|
&& !value.equals( value.toLowerCase() );
|
||||||
|
}
|
||||||
|
return value != null && !value.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
The generated mapper with `@TargetPropertyName` and `@SourcePropertyName` will look like:
|
||||||
|
|
||||||
|
.Custom condition check in generated implementation
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
// GENERATED CODE
|
||||||
|
public class CarMapperImpl implements CarMapper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarDto carToCarDto(Car car, CarDto carDto) {
|
||||||
|
if ( car == null ) {
|
||||||
|
return carDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isNotEmpty( car.getOwner(), "owner", "ownerName" ) ) {
|
||||||
|
carDto.setOwner( car.getOwner() );
|
||||||
|
} else {
|
||||||
|
carDto.setOwner( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mapping of other properties
|
||||||
|
|
||||||
|
return carDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
[IMPORTANT]
|
[IMPORTANT]
|
||||||
====
|
====
|
||||||
If there is a custom `@Condition` method applicable for the property it will have a precedence over a presence check method in the bean itself.
|
If there is a custom `@Condition` method applicable for the property it will have a precedence over a presence check method in the bean itself.
|
||||||
@ -412,11 +479,62 @@ If there is a custom `@Condition` method applicable for the property it will hav
|
|||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
Methods annotated with `@Condition` in addition to the value of the source property can also have the source parameter as an input.
|
Methods annotated with `@Condition` in addition to the value of the source property can also have the source parameter as an input.
|
||||||
|
|
||||||
|
`@TargetPropertyName` and `@SourcePropertyName` parameters can only be used in `@Condition` methods.
|
||||||
====
|
====
|
||||||
|
|
||||||
<<selection-based-on-qualifiers>> is also valid for `@Condition` methods.
|
<<selection-based-on-qualifiers>> is also valid for `@Condition` methods.
|
||||||
In order to use a more specific condition method you will need to use one of `Mapping#conditionQualifiedByName` or `Mapping#conditionQualifiedBy`.
|
In order to use a more specific condition method you will need to use one of `Mapping#conditionQualifiedByName` or `Mapping#conditionQualifiedBy`.
|
||||||
|
|
||||||
|
If we want to only map cars that have an id provided then we can do something like:
|
||||||
|
|
||||||
|
|
||||||
|
.Mapper using custom condition source parameter check method
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
public interface CarMapper {
|
||||||
|
|
||||||
|
CarDto carToCarDto(Car car);
|
||||||
|
|
||||||
|
@SourceParameterCondition
|
||||||
|
default boolean hasCar(Car car) {
|
||||||
|
return car != null && car.getId() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
The generated mapper will look like:
|
||||||
|
|
||||||
|
.Custom condition source parameter check generated implementation
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
// GENERATED CODE
|
||||||
|
public class CarMapperImpl implements CarMapper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarDto carToCarDto(Car car) {
|
||||||
|
if ( !hasCar( car ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CarDto carDto = new CarDto();
|
||||||
|
|
||||||
|
carDto.setOwner( car.getOwner() );
|
||||||
|
|
||||||
|
// Mapping of other properties
|
||||||
|
|
||||||
|
return carDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
[[exceptions]]
|
[[exceptions]]
|
||||||
=== Exceptions
|
=== Exceptions
|
||||||
|
|
||||||
|
@ -248,9 +248,8 @@ All before/after-mapping methods that *can* be applied to a mapping method *will
|
|||||||
|
|
||||||
The order of the method invocation is determined primarily by their variant:
|
The order of the method invocation is determined primarily by their variant:
|
||||||
|
|
||||||
1. `@BeforeMapping` methods without an `@MappingTarget` parameter are called before any null-checks on source
|
1. `@BeforeMapping` methods without parameters, a `@MappingTarget` parameter or a `@TargetType` parameter are called before any null-checks on source parameters and constructing a new target bean.
|
||||||
parameters and constructing a new target bean.
|
2. `@BeforeMapping` methods with a `@MappingTarget` parameter are called after constructing a new target bean.
|
||||||
2. `@BeforeMapping` methods with an `@MappingTarget` parameter are called after constructing a new target bean.
|
|
||||||
3. `@AfterMapping` methods are called at the end of the mapping method before the last `return` statement.
|
3. `@AfterMapping` methods are called at the end of the mapping method before the last `return` statement.
|
||||||
|
|
||||||
Within those groups, the method invocations are ordered by their location of definition:
|
Within those groups, the method invocations are ordered by their location of definition:
|
||||||
@ -262,4 +261,11 @@ Within those groups, the method invocations are ordered by their location of def
|
|||||||
|
|
||||||
*Important:* the order of methods declared within one type can not be guaranteed, as it depends on the compiler and the processing environment implementation.
|
*Important:* the order of methods declared within one type can not be guaranteed, as it depends on the compiler and the processing environment implementation.
|
||||||
|
|
||||||
*Important:* when using a builder, the `@AfterMapping` annotated method must have the builder as `@MappingTarget` annotated parameter so that the method is able to modify the object going to be build. The `build` method is called when the `@AfterMapping` annotated method scope finishes. MapStruct will not call the `@AfterMapping` annotated method if the real target is used as `@MappingTarget` annotated parameter.
|
[NOTE]
|
||||||
|
====
|
||||||
|
Before/After-mapping methods can also be used with builders:
|
||||||
|
|
||||||
|
* `@BeforeMapping` methods with a `@MappingTarget` parameter of the real target will not be invoked because it is only available after the mapping was already performed.
|
||||||
|
* To be able to modify the object that is going to be built, the `@AfterMapping` annotated method must have the builder as `@MappingTarget` annotated parameter. The `build` method is called when the `@AfterMapping` annotated method scope finishes.
|
||||||
|
* The `@AfterMapping` annotated method can also have the real target as `@TargetType` or `@MappingTarget`. It will be invoked after the real target was built (first the methods annotated with `@TargetType`, then the methods annotated with `@MappingTarget`)
|
||||||
|
====
|
@ -71,7 +71,7 @@ public class GolfPlayerDto {
|
|||||||
|
|
||||||
public GolfPlayerDto withName(String name) {
|
public GolfPlayerDto withName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
return this
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
@ -371,3 +371,54 @@ A nice example is to provide support for a custom transformation strategy.
|
|||||||
include::{processor-ap-test}/value/nametransformation/CustomEnumTransformationStrategy.java[tag=documentation]
|
include::{processor-ap-test}/value/nametransformation/CustomEnumTransformationStrategy.java[tag=documentation]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[additional-supported-options-provider]]
|
||||||
|
=== Additional Supported Options Provider
|
||||||
|
|
||||||
|
SPI name: `org.mapstruct.ap.spi.AdditionalSupportedOptionsProvider`
|
||||||
|
|
||||||
|
MapStruct offers the ability to pass through declared compiler args (or "options") provided to the MappingProcessor
|
||||||
|
to the individual SPIs, by implementing `AdditionalSupportedOptionsProvider` via the Service Provider Interface (SPI).
|
||||||
|
|
||||||
|
.Custom Additional Supported Options Provider that declares `myorg.custom.defaultNullEnumConstant` as an option to pass through
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
include::{processor-ap-test}/additionalsupportedoptions/CustomAdditionalSupportedOptionsProvider.java[tag=documentation]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
The value of this option is provided by including an `arg` to the `compilerArgs` tag when defining your custom SPI
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
.Example maven configuration with additional options
|
||||||
|
====
|
||||||
|
[source, maven, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.myorg</groupId>
|
||||||
|
<artifactId>custom-spi-impl</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-Amyorg.custom.defaultNullEnumConstant=MISSING</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
Your custom SPI implementations can then access this configured value via `MapStructProcessingEnvironment#getOptions()`.
|
||||||
|
|
||||||
|
.Accessing your custom options
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
include::{processor-ap-test}/additionalsupportedoptions/UnknownEnumMappingStrategy.java[tag=documentation]
|
||||||
|
----
|
||||||
|
====
|
@ -46,8 +46,10 @@ public @interface Default {
|
|||||||
MapStruct works together with https://projectlombok.org/[Project Lombok] as of MapStruct 1.2.0.Beta1 and Lombok 1.16.14.
|
MapStruct works together with https://projectlombok.org/[Project Lombok] as of MapStruct 1.2.0.Beta1 and Lombok 1.16.14.
|
||||||
|
|
||||||
MapStruct takes advantage of generated getters, setters, and constructors and uses them to generate the mapper implementations.
|
MapStruct takes advantage of generated getters, setters, and constructors and uses them to generate the mapper implementations.
|
||||||
|
Be reminded that the generated code by Lombok might not always be compatible with the expectations from the individual mappings.
|
||||||
|
In such a case, either Mapstruct mapping must be changed or Lombok must be configured accordingly using https://projectlombok.org/features/configuration[`lombok.config`] for mutual synergy.
|
||||||
|
|
||||||
[NOTE]
|
[WARNING]
|
||||||
====
|
====
|
||||||
Lombok 1.18.16 introduces a breaking change (https://projectlombok.org/changelog[changelog]).
|
Lombok 1.18.16 introduces a breaking change (https://projectlombok.org/changelog[changelog]).
|
||||||
The additional annotation processor `lombok-mapstruct-binding` (https://mvnrepository.com/artifact/org.projectlombok/lombok-mapstruct-binding[Maven]) must be added otherwise MapStruct stops working with Lombok.
|
The additional annotation processor `lombok-mapstruct-binding` (https://mvnrepository.com/artifact/org.projectlombok/lombok-mapstruct-binding[Maven]) must be added otherwise MapStruct stops working with Lombok.
|
||||||
|
@ -130,7 +130,7 @@ You can find a complete example in the https://github.com/mapstruct/mapstruct-ex
|
|||||||
|
|
||||||
The MapStruct code generator can be configured using _annotation processor options_.
|
The MapStruct code generator can be configured using _annotation processor options_.
|
||||||
|
|
||||||
When invoking javac directly, these options are passed to the compiler in the form _-Akey=value_. When using MapStruct via Maven, any processor options can be passed using an `options` element within the configuration of the Maven processor plug-in like this:
|
When invoking javac directly, these options are passed to the compiler in the form _-Akey=value_. When using MapStruct via Maven, any processor options can be passed using `compilerArgs` within the configuration of the Maven processor plug-in like this:
|
||||||
|
|
||||||
.Maven configuration
|
.Maven configuration
|
||||||
====
|
====
|
||||||
@ -215,10 +215,11 @@ suppressGeneratorVersionInfoComment`
|
|||||||
Supported values are:
|
Supported values are:
|
||||||
|
|
||||||
* `default`: the mapper uses no component model, instances are typically retrieved via `Mappers#getMapper(Class)`
|
* `default`: the mapper uses no component model, instances are typically retrieved via `Mappers#getMapper(Class)`
|
||||||
* `cdi`: the generated mapper is an application-scoped CDI bean and can be retrieved via `@Inject`
|
* `cdi`: the generated mapper is an application-scoped (from javax.enterprise.context or jakarta.enterprise.context, depending on which one is available with javax.inject having priority) CDI bean and can be retrieved via `@Inject`
|
||||||
* `spring`: the generated mapper is a singleton-scoped Spring bean and can be retrieved via `@Autowired`
|
* `spring`: the generated mapper is a singleton-scoped Spring bean and can be retrieved via `@Autowired`
|
||||||
* `jsr330`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from javax.inject or jakarta.inject, depending which one is available with javax.inject having priority), e.g. using Spring
|
* `jsr330`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from javax.inject or jakarta.inject, depending which one is available with javax.inject having priority), e.g. using Spring
|
||||||
* `jakarta`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from jakarta.inject), e.g. using Spring
|
* `jakarta`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from jakarta.inject), e.g. using Spring
|
||||||
|
* `jakarta-cdi`: the generated mapper is an application-scoped (from jakarta.enterprise.context) CDI bean and can be retrieved via `@Inject`
|
||||||
|
|
||||||
If a component model is given for a specific mapper via `@Mapper#componentModel()`, the value from the annotation takes precedence.
|
If a component model is given for a specific mapper via `@Mapper#componentModel()`, the value from the annotation takes precedence.
|
||||||
|`default`
|
|`default`
|
||||||
@ -260,12 +261,36 @@ Supported values are:
|
|||||||
|
|
||||||
If a policy is given for a specific mapper via `@Mapper#unmappedSourcePolicy()`, the value from the annotation takes precedence.
|
If a policy is given for a specific mapper via `@Mapper#unmappedSourcePolicy()`, the value from the annotation takes precedence.
|
||||||
If a policy is given for a specific bean mapping via `@BeanMapping#ignoreUnmappedSourceProperties()`, it takes precedence over both `@Mapper#unmappedSourcePolicy()` and the option.
|
If a policy is given for a specific bean mapping via `@BeanMapping#ignoreUnmappedSourceProperties()`, it takes precedence over both `@Mapper#unmappedSourcePolicy()` and the option.
|
||||||
|`WARN`
|
|`IGNORE`
|
||||||
|
|
||||||
|`mapstruct.
|
|`mapstruct.
|
||||||
disableBuilders`
|
disableBuilders`
|
||||||
|If set to `true`, then MapStruct will not use builder patterns when doing the mapping. This is equivalent to doing `@Mapper( builder = @Builder( disableBuilder = true ) )` for all of your mappers.
|
|If set to `true`, then MapStruct will not use builder patterns when doing the mapping. This is equivalent to doing `@Mapper( builder = @Builder( disableBuilder = true ) )` for all of your mappers.
|
||||||
|`false`
|
|`false`
|
||||||
|
|
||||||
|
|`mapstruct.nullValueIterableMappingStrategy`
|
||||||
|
|The strategy to be applied when `null` is passed as a source value to an iterable mapping.
|
||||||
|
|
||||||
|
Supported values are:
|
||||||
|
|
||||||
|
* `RETURN_NULL`: if `null` is passed as a source value, then `null` will be returned
|
||||||
|
* `RETURN_DEFAULT`: if `null` is passed then a default value (empty collection) will be returned
|
||||||
|
|
||||||
|
If a strategy is given for a specific mapper via `@Mapper#nullValueIterableMappingStrategy()`, the value from the annotation takes precedence.
|
||||||
|
If a strategy is given for a specific iterable mapping via `@IterableMapping#nullValueMappingStrategy()`, it takes precedence over both `@Mapper#nullValueIterableMappingStrategy()` and the option.
|
||||||
|
|`RETURN_NULL`
|
||||||
|
|
||||||
|
|`mapstruct.nullValueMapMappingStrategy`
|
||||||
|
|The strategy to be applied when `null` is passed as a source value to a map mapping.
|
||||||
|
|
||||||
|
Supported values are:
|
||||||
|
|
||||||
|
* `RETURN_NULL`: if `null` is passed as a source value, then `null` will be returned
|
||||||
|
* `RETURN_DEFAULT`: if `null` is passed then a default value (empty map) will be returned
|
||||||
|
|
||||||
|
If a strategy is given for a specific mapper via `@Mapper#nullValueMapMappingStrategy()`, the value from the annotation takes precedence.
|
||||||
|
If a strategy is given for a specific map mapping via `@MapMapping#nullValueMappingStrategy()`, it takes precedence over both `@Mapper#nullValueMapMappingStrategy()` and the option.
|
||||||
|
|`RETURN_NULL`
|
||||||
|===
|
|===
|
||||||
|
|
||||||
=== Using MapStruct with the Java Module System
|
=== Using MapStruct with the Java Module System
|
||||||
@ -273,3 +298,28 @@ disableBuilders`
|
|||||||
MapStruct can be used with Java 9 and higher versions.
|
MapStruct can be used with Java 9 and higher versions.
|
||||||
|
|
||||||
To allow usage of the `@Generated` annotation `java.annotation.processing.Generated` (part of the `java.compiler` module) can be enabled.
|
To allow usage of the `@Generated` annotation `java.annotation.processing.Generated` (part of the `java.compiler` module) can be enabled.
|
||||||
|
|
||||||
|
=== IDE Integration
|
||||||
|
|
||||||
|
There are optional MapStruct plugins for IntelliJ and Eclipse that allow you to have additional completion support (and more) in the annotations.
|
||||||
|
|
||||||
|
==== IntelliJ
|
||||||
|
|
||||||
|
The https://plugins.jetbrains.com/plugin/10036-mapstruct-support[MapStruct IntelliJ] plugin offers assistance in projects that use MapStruct.
|
||||||
|
|
||||||
|
Some features include:
|
||||||
|
|
||||||
|
* Code completion in `target`, `source`, `expression`
|
||||||
|
* Go To Declaration for properties in `target` and `source`
|
||||||
|
* Find Usages of properties in `target` and `source`
|
||||||
|
* Refactoring support
|
||||||
|
* Errors and Quick Fixes
|
||||||
|
|
||||||
|
==== Eclipse
|
||||||
|
|
||||||
|
The https://marketplace.eclipse.org/content/mapstruct-eclipse-plugin[MapStruct Eclipse] Plugin offers assistance in projects that use MapStruct.
|
||||||
|
|
||||||
|
Some features include:
|
||||||
|
|
||||||
|
* Code completion in `target` and `source`
|
||||||
|
* Quick Fixes
|
||||||
|
@ -39,7 +39,7 @@ The property name as defined in the http://www.oracle.com/technetwork/java/javas
|
|||||||
====
|
====
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
By means of the `@BeanMapping(ignoreByDefault = true)` the default behavior will be *explicit mapping*, meaning that all mappings have to be specified by means of the `@Mapping` and no warnings will be issued on missing target properties.
|
By means of the `@BeanMapping(ignoreByDefault = true)` the default behavior will be *explicit mapping*, meaning that all mappings (including nested ones) have to be specified by means of the `@Mapping` and no warnings will be issued on missing target properties.
|
||||||
This allows to ignore all fields, except the ones that are explicitly defined through `@Mapping`.
|
This allows to ignore all fields, except the ones that are explicitly defined through `@Mapping`.
|
||||||
====
|
====
|
||||||
[TIP]
|
[TIP]
|
||||||
@ -126,7 +126,7 @@ Collection-typed attributes with the same element type will be copied by creatin
|
|||||||
MapStruct takes all public properties of the source and target types into account. This includes properties declared on super-types.
|
MapStruct takes all public properties of the source and target types into account. This includes properties declared on super-types.
|
||||||
|
|
||||||
[[mapping-composition]]
|
[[mapping-composition]]
|
||||||
=== Mapping Composition (experimental)
|
=== Mapping Composition
|
||||||
MapStruct supports the use of meta annotations. The `@Mapping` annotation supports now `@Target` with `ElementType#ANNOTATION_TYPE` in addition to `ElementType#METHOD`. This allows `@Mapping` to be used on other (user defined) annotations for re-use purposes. For example:
|
MapStruct supports the use of meta annotations. The `@Mapping` annotation supports now `@Target` with `ElementType#ANNOTATION_TYPE` in addition to `ElementType#METHOD`. This allows `@Mapping` to be used on other (user defined) annotations for re-use purposes. For example:
|
||||||
|
|
||||||
====
|
====
|
||||||
@ -164,7 +164,7 @@ public interface StorageMapper {
|
|||||||
|
|
||||||
Still, they do have some properties in common. The `@ToEntity` assumes both target beans `ShelveEntity` and `BoxEntity` have properties: `"id"`, `"creationDate"` and `"name"`. It furthermore assumes that the source beans `ShelveDto` and `BoxDto` always have a property `"groupName"`. This concept is also known as "duck-typing". In other words, if it quacks like duck, walks like a duck its probably a duck.
|
Still, they do have some properties in common. The `@ToEntity` assumes both target beans `ShelveEntity` and `BoxEntity` have properties: `"id"`, `"creationDate"` and `"name"`. It furthermore assumes that the source beans `ShelveDto` and `BoxDto` always have a property `"groupName"`. This concept is also known as "duck-typing". In other words, if it quacks like duck, walks like a duck its probably a duck.
|
||||||
|
|
||||||
This feature is still experimental. Error messages are not mature yet: the method on which the problem occurs is displayed, as well as the concerned values in the `@Mapping` annotation. However, the composition aspect is not visible. The messages are "as if" the `@Mapping` would be present on the concerned method directly.
|
Error messages are not mature yet: the method on which the problem occurs is displayed, as well as the concerned values in the `@Mapping` annotation. However, the composition aspect is not visible. The messages are "as if" the `@Mapping` would be present on the concerned method directly.
|
||||||
Therefore, the user should use this feature with care, especially when uncertain when a property is always present.
|
Therefore, the user should use this feature with care, especially when uncertain when a property is always present.
|
||||||
|
|
||||||
A more typesafe (but also more verbose) way would be to define base classes / interfaces on the target bean and the source bean and use `@InheritConfiguration` to achieve the same result (see <<mapping-configuration-inheritance>>).
|
A more typesafe (but also more verbose) way would be to define base classes / interfaces on the target bean and the source bean and use `@InheritConfiguration` to achieve the same result (see <<mapping-configuration-inheritance>>).
|
||||||
@ -302,7 +302,7 @@ If you don't want explicitly name all properties from nested source bean, you ca
|
|||||||
The generated code will map every property from `CustomerDto.record` to `Customer` directly, without need to manually name any of them.
|
The generated code will map every property from `CustomerDto.record` to `Customer` directly, without need to manually name any of them.
|
||||||
The same goes for `Customer.account`.
|
The same goes for `Customer.account`.
|
||||||
|
|
||||||
When there are conflicts, these can be resolved by explicitely defining the mapping. For instance in the example above. `name` occurs in `CustomerDto.record` and in `CustomerDto.account`. The mapping `@Mapping( target = "name", source = "record.name" )` resolves this conflict.
|
When there are conflicts, these can be resolved by explicitly defining the mapping. For instance in the example above. `name` occurs in `CustomerDto.record` and in `CustomerDto.account`. The mapping `@Mapping( target = "name", source = "record.name" )` resolves this conflict.
|
||||||
|
|
||||||
|
|
||||||
This "target this" notation can be very useful when mapping hierarchical objects to flat objects and vice versa (`@InheritInverseConfiguration`).
|
This "target this" notation can be very useful when mapping hierarchical objects to flat objects and vice versa (`@InheritInverseConfiguration`).
|
||||||
@ -421,8 +421,11 @@ If a Builder exists for a certain type, then that builder will be used for the m
|
|||||||
|
|
||||||
The default implementation of the `BuilderProvider` assumes the following:
|
The default implementation of the `BuilderProvider` assumes the following:
|
||||||
|
|
||||||
* The type has a parameterless public static builder creation method that returns a builder.
|
* The type has either
|
||||||
So for example `Person` has a public static method that returns `PersonBuilder`.
|
** A parameterless public static builder creation method that returns a builder.
|
||||||
|
e.g. `Person` has a public static method that returns `PersonBuilder`.
|
||||||
|
** A public static inner class with the name having the suffix "Builder", and a public no-args constructor
|
||||||
|
e.g. `Person` has an inner class `PersonBuilder` with a public no-args constructor.
|
||||||
* The builder type has a parameterless public method (build method) that returns the type being built.
|
* The builder type has a parameterless public method (build method) that returns the type being built.
|
||||||
In our example `PersonBuilder` has a method returning `Person`.
|
In our example `PersonBuilder` has a method returning `Person`.
|
||||||
* In case there are multiple build methods, MapStruct will look for a method called `build`, if such method exists
|
* In case there are multiple build methods, MapStruct will look for a method called `build`, if such method exists
|
||||||
@ -448,7 +451,7 @@ E.g. If an object factory exists for our `PersonBuilder` then this factory would
|
|||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
======
|
======
|
||||||
Detected builders influence `@BeforeMapping` and `@AfterMapping` behavior. See chapter `Mapping customization with before-mapping and after-mapping methods` for more information.
|
Detected builders influence `@BeforeMapping` and `@AfterMapping` behavior. See <<customizing-mappings-with-before-and-after>> for more information.
|
||||||
======
|
======
|
||||||
|
|
||||||
.Person with Builder example
|
.Person with Builder example
|
||||||
@ -721,3 +724,143 @@ i.e. You can map from `Map<String, Integer>` where for each property a conversio
|
|||||||
When a raw map or a map that does not have a String as a key is used, then a warning will be generated.
|
When a raw map or a map that does not have a String as a key is used, then a warning will be generated.
|
||||||
The warning is not generated if the map itself is mapped into some other target property directly as is.
|
The warning is not generated if the map itself is mapped into some other target property directly as is.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[adding-annotations]]
|
||||||
|
=== Adding annotations
|
||||||
|
|
||||||
|
Other frameworks sometimes requires you to add annotations to certain classes so that they can easily detect the mappers.
|
||||||
|
Using the `@AnnotateWith` annotation you can generate an annotation at the specified location.
|
||||||
|
|
||||||
|
For example Apache Camel has a `@Converter` annotation which you can apply to generated mappers using the `@AnnotateWith` annotation.
|
||||||
|
|
||||||
|
.AnnotateWith source example
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
@AnnotateWith(
|
||||||
|
value = Converter.class,
|
||||||
|
elements = @AnnotateWith.Element( name = "generateBulkLoader", booleans = true )
|
||||||
|
)
|
||||||
|
public interface MyConverter {
|
||||||
|
@AnnotateWith( Converter.class )
|
||||||
|
DomainObject map( DtoObject dto );
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
.AnnotateWith generated mapper
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Converter( generateBulkLoader = true )
|
||||||
|
public class MyConverterImpl implements MyConverter {
|
||||||
|
@Converter
|
||||||
|
public DomainObject map( DtoObject dto ) {
|
||||||
|
// default mapping behaviour
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
[[javadoc]]
|
||||||
|
=== Adding Javadoc comments
|
||||||
|
|
||||||
|
MapStruct provides support for defining Javadoc comments in the generated mapper implementation using the
|
||||||
|
`org.mapstruct.Javadoc` annotation.
|
||||||
|
|
||||||
|
This functionality could be relevant especially in situations where certain Javadoc standards need to be met or
|
||||||
|
to deal with Javadoc validation constraints.
|
||||||
|
|
||||||
|
The `@Javadoc` annotation defines attributes for the different Javadoc elements.
|
||||||
|
|
||||||
|
Consider the following example:
|
||||||
|
|
||||||
|
.Javadoc annotation example
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
@Javadoc(
|
||||||
|
value = "This is the description",
|
||||||
|
authors = { "author1", "author2" },
|
||||||
|
deprecated = "Use {@link OtherMapper} instead",
|
||||||
|
since = "0.1"
|
||||||
|
)
|
||||||
|
public interface MyAnnotatedWithJavadocMapper {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
.Javadoc annotated generated mapper
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
/**
|
||||||
|
* This is the description
|
||||||
|
*
|
||||||
|
* @author author1
|
||||||
|
* @author author2
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link OtherMapper} instead
|
||||||
|
* @since 0.1
|
||||||
|
*/
|
||||||
|
public class MyAnnotatedWithJavadocMapperImpl implements MyAnnotatedWithJavadocMapper {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
The entire Javadoc comment block can be provided directly as well.
|
||||||
|
|
||||||
|
.Javadoc annotation example with the entire Javadoc comment block provided directly
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
@Javadoc(
|
||||||
|
"This is the description\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "@author author1\n"
|
||||||
|
+ "@author author2\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "@deprecated Use {@link OtherMapper} instead\n"
|
||||||
|
+ "@since 0.1\n"
|
||||||
|
)
|
||||||
|
public interface MyAnnotatedWithJavadocMapper {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
Or using Text blocks:
|
||||||
|
|
||||||
|
.Javadoc annotation example with the entire Javadoc comment block provided directly using Text blocks
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
@Javadoc(
|
||||||
|
"""
|
||||||
|
This is the description
|
||||||
|
|
||||||
|
@author author1
|
||||||
|
@author author2
|
||||||
|
|
||||||
|
@deprecated Use {@link OtherMapper} instead
|
||||||
|
@since 0.1
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
public interface MyAnnotatedWithJavadocMapper {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
@ -102,7 +102,7 @@ A mapper which uses other mapper classes (see <<invoking-other-mappers>>) will o
|
|||||||
[[injection-strategy]]
|
[[injection-strategy]]
|
||||||
=== Injection strategy
|
=== Injection strategy
|
||||||
|
|
||||||
When using <<using-dependency-injection,dependency injection>>, you can choose between field and constructor injection.
|
When using <<using-dependency-injection,dependency injection>>, you can choose between constructor, field, or setter injection.
|
||||||
This can be done by either providing the injection strategy via `@Mapper` or `@MapperConfig` annotation.
|
This can be done by either providing the injection strategy via `@Mapper` or `@MapperConfig` annotation.
|
||||||
|
|
||||||
.Using constructor injection
|
.Using constructor injection
|
||||||
@ -120,9 +120,13 @@ public interface CarMapper {
|
|||||||
The generated mapper will inject classes defined in the **uses** attribute if MapStruct has detected that it needs to use an instance of it for a mapping.
|
The generated mapper will inject classes defined in the **uses** attribute if MapStruct has detected that it needs to use an instance of it for a mapping.
|
||||||
When `InjectionStrategy#CONSTRUCTOR` is used, the constructor will have the appropriate annotation and the fields won't.
|
When `InjectionStrategy#CONSTRUCTOR` is used, the constructor will have the appropriate annotation and the fields won't.
|
||||||
When `InjectionStrategy#FIELD` is used, the annotation is on the field itself.
|
When `InjectionStrategy#FIELD` is used, the annotation is on the field itself.
|
||||||
|
When `InjectionStrategy#SETTER` is used the annotation is on a generated setter method.
|
||||||
For now, the default injection strategy is field injection, but it can be configured with <<configuration-options>>.
|
For now, the default injection strategy is field injection, but it can be configured with <<configuration-options>>.
|
||||||
It is recommended to use constructor injection to simplify testing.
|
It is recommended to use constructor injection to simplify testing.
|
||||||
|
|
||||||
|
When you define mappers in Spring with circular dependencies compilation may fail.
|
||||||
|
In that case utilize the `InjectionStrategy#SETTER` strategy.
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
For abstract classes or decorators setter injection should be used.
|
For abstract classes or decorators setter injection should be used.
|
||||||
|
@ -43,6 +43,9 @@ public interface CarMapper {
|
|||||||
====
|
====
|
||||||
* Between `enum` types and `String`.
|
* Between `enum` types and `String`.
|
||||||
|
|
||||||
|
* Between `enum` types and `Integer`, according to `enum.ordinal()`.
|
||||||
|
** When converting from an `Integer`, the value needs to be less than the number of values of the enum, otherwise an `ArrayOutOfBoundsException` is thrown.
|
||||||
|
|
||||||
* Between big number types (`java.math.BigInteger`, `java.math.BigDecimal`) and Java primitive types (including their wrappers) as well as String. A format string as understood by `java.text.DecimalFormat` can be specified.
|
* Between big number types (`java.math.BigInteger`, `java.math.BigDecimal`) and Java primitive types (including their wrappers) as well as String. A format string as understood by `java.text.DecimalFormat` can be specified.
|
||||||
|
|
||||||
.Conversion from BigDecimal to String
|
.Conversion from BigDecimal to String
|
||||||
@ -104,6 +107,8 @@ public interface CarMapper {
|
|||||||
|
|
||||||
* Between `java.time.Instant` from Java 8 Date-Time package and `java.util.Date`.
|
* Between `java.time.Instant` from Java 8 Date-Time package and `java.util.Date`.
|
||||||
|
|
||||||
|
* Between `java.time.LocalDateTime` from Java 8 Date-Time package and `java.time.LocalDate` from the same package.
|
||||||
|
|
||||||
* Between `java.time.ZonedDateTime` from Java 8 Date-Time package and `java.util.Calendar`.
|
* Between `java.time.ZonedDateTime` from Java 8 Date-Time package and `java.util.Calendar`.
|
||||||
|
|
||||||
* Between `java.sql.Date` and `java.util.Date`
|
* Between `java.sql.Date` and `java.util.Date`
|
||||||
@ -125,6 +130,9 @@ public interface CarMapper {
|
|||||||
* Between `java.net.URL` and `String`.
|
* Between `java.net.URL` and `String`.
|
||||||
** When converting from a `String`, the value needs to be a valid https://en.wikipedia.org/wiki/URL[URL] otherwise a `MalformedURLException` is thrown.
|
** When converting from a `String`, the value needs to be a valid https://en.wikipedia.org/wiki/URL[URL] otherwise a `MalformedURLException` is thrown.
|
||||||
|
|
||||||
|
* Between `java.util.Locale` and `String`.
|
||||||
|
** When converting from a `Locale`, the resulting `String` will be a well-formed IETF BCP 47 language tag representing the locale. When converting from a `String`, the locale that best represents the language tag will be returned. See https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html#forLanguageTag-java.lang.String-[Locale.forLanguageTag()] and https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html#toLanguageTag--[Locale.toLanguageTag()] for more information.
|
||||||
|
|
||||||
[[mapping-object-references]]
|
[[mapping-object-references]]
|
||||||
=== Mapping object references
|
=== Mapping object references
|
||||||
|
|
||||||
@ -272,6 +280,13 @@ This puts the configuration of the nested mapping into one place (method) where
|
|||||||
instead of re-configuring the same things on all of those upper methods.
|
instead of re-configuring the same things on all of those upper methods.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[TIP]
|
||||||
|
====
|
||||||
|
When ignoring multiple properties instead of defining multiple `@Mapping` annotations, you can use the `@Ignored` annotation to group them together.
|
||||||
|
e.g. for the `FishTankMapperWithDocument` example above, you could write:
|
||||||
|
`@Ignored(targets = { "plant", "ornament", "material" })`
|
||||||
|
====
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
In some cases the `ReportingPolicy` that is going to be used for the generated nested method would be `IGNORE`.
|
In some cases the `ReportingPolicy` that is going to be used for the generated nested method would be `IGNORE`.
|
||||||
@ -393,6 +408,39 @@ When having a custom mapper hooked into the generated mapper with `@Mapper#uses(
|
|||||||
|
|
||||||
For instance, the `CarDto` could have a property `owner` of type `Reference` that contains the primary key of a `Person` entity. You could now create a generic custom mapper that resolves any `Reference` objects to their corresponding managed JPA entity instances.
|
For instance, the `CarDto` could have a property `owner` of type `Reference` that contains the primary key of a `Person` entity. You could now create a generic custom mapper that resolves any `Reference` objects to their corresponding managed JPA entity instances.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
.Example classes for the passing target type example
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
public class Car {
|
||||||
|
|
||||||
|
private Person owner;
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Person extends BaseEntity {
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Reference {
|
||||||
|
|
||||||
|
private String pk;
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CarDto {
|
||||||
|
|
||||||
|
private Reference owner;
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
.Mapping method expecting mapping target type as parameter
|
.Mapping method expecting mapping target type as parameter
|
||||||
====
|
====
|
||||||
[source, java, linenums]
|
[source, java, linenums]
|
||||||
|
@ -192,7 +192,7 @@ The option `DEFAULT` should not be used explicitly. It is used to distinguish be
|
|||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
When working with an `adder` method and JPA entities, Mapstruct assumes that the target collections are initialized with a collection implementation (e.g. an `ArrayList`). You can use factories to create a new target entity with intialized collections instead of Mapstruct creating the target entity by its constructor.
|
When working with an `adder` method and JPA entities, Mapstruct assumes that the target collections are initialized with a collection implementation (e.g. an `ArrayList`). You can use factories to create a new target entity with initialized collections instead of Mapstruct creating the target entity by its constructor.
|
||||||
====
|
====
|
||||||
|
|
||||||
[[implementation-types-for-collection-mappings]]
|
[[implementation-types-for-collection-mappings]]
|
||||||
@ -212,12 +212,16 @@ When an iterable or map mapping method declares an interface type as return type
|
|||||||
|
|
||||||
|`Set`|`LinkedHashSet`
|
|`Set`|`LinkedHashSet`
|
||||||
|
|
||||||
|
|`SequencedSet`|`LinkedHashSet`
|
||||||
|
|
||||||
|`SortedSet`|`TreeSet`
|
|`SortedSet`|`TreeSet`
|
||||||
|
|
||||||
|`NavigableSet`|`TreeSet`
|
|`NavigableSet`|`TreeSet`
|
||||||
|
|
||||||
|`Map`|`LinkedHashMap`
|
|`Map`|`LinkedHashMap`
|
||||||
|
|
||||||
|
|`SequencedMap`|`LinkedHashMap`
|
||||||
|
|
||||||
|`SortedMap`|`TreeMap`
|
|`SortedMap`|`TreeMap`
|
||||||
|
|
||||||
|`NavigableMap`|`TreeMap`
|
|`NavigableMap`|`TreeMap`
|
||||||
|
@ -65,7 +65,7 @@ public class OrderMapperImpl implements OrderMapper {
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
By default an error will be raised by MapStruct in case a constant of the source enum type does not have a corresponding constant with the same name in the target type and also is not mapped to another constant via `@ValueMapping`. This ensures that all constants are mapped in a safe and predictable manner. The generated
|
By default an error will be raised by MapStruct in case a constant of the source enum type does not have a corresponding constant with the same name in the target type and also is not mapped to another constant via `@ValueMapping`. This ensures that all constants are mapped in a safe and predictable manner. The generated
|
||||||
mapping method will throw an IllegalStateException if for some reason an unrecognized source value occurs.
|
mapping method will throw an `IllegalStateException` if for some reason an unrecognized source value occurs.
|
||||||
|
|
||||||
MapStruct also has a mechanism for mapping any remaining (unspecified) mappings to a default. This can be used only once in a set of value mappings and only applies to the source. It comes in two flavors: `<ANY_REMAINING>` and `<ANY_UNMAPPED>`. They cannot be used at the same time.
|
MapStruct also has a mechanism for mapping any remaining (unspecified) mappings to a default. This can be used only once in a set of value mappings and only applies to the source. It comes in two flavors: `<ANY_REMAINING>` and `<ANY_UNMAPPED>`. They cannot be used at the same time.
|
||||||
|
|
||||||
@ -75,14 +75,18 @@ MapStruct will *not* attempt such name based mapping for `<ANY_UNMAPPED>` and di
|
|||||||
|
|
||||||
MapStruct is able to handle `null` sources and `null` targets by means of the `<NULL>` keyword.
|
MapStruct is able to handle `null` sources and `null` targets by means of the `<NULL>` keyword.
|
||||||
|
|
||||||
|
In addition, the constant value `<THROW_EXCEPTION>` can be used for throwing an exception for particular value mappings. This value is only applicable to `ValueMapping#target()` and not `ValueMapping#source()` since MapStruct can't map from exceptions.
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
Constants for `<ANY_REMAINING>`, `<ANY_UNMAPPED>` and `<NULL>` are available in the `MappingConstants` class.
|
Constants for `<ANY_REMAINING>`, `<ANY_UNMAPPED>`, `<THROW_EXCEPTION>` and `<NULL>` are available in the `MappingConstants` class.
|
||||||
====
|
====
|
||||||
|
|
||||||
Finally `@InheritInverseConfiguration` and `@InheritConfiguration` can be used in combination with `@ValueMappings`. `<ANY_REMAINING>` and `<ANY_UNMAPPED>` will be ignored in that case.
|
Finally `@InheritInverseConfiguration` and `@InheritConfiguration` can be used in combination with `@ValueMappings`. `<ANY_REMAINING>` and `<ANY_UNMAPPED>` will be ignored in that case.
|
||||||
|
|
||||||
.Enum mapping method, <NULL> and <ANY_REMAINING>
|
The following code snippets exemplify the use of the aforementioned constants.
|
||||||
|
|
||||||
|
.Enum mapping method, `<NULL>` and `<ANY_REMAINING>`
|
||||||
====
|
====
|
||||||
[source, java, linenums]
|
[source, java, linenums]
|
||||||
[subs="verbatim,attributes"]
|
[subs="verbatim,attributes"]
|
||||||
@ -102,7 +106,7 @@ public interface SpecialOrderMapper {
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
.Enum mapping method result, <NULL> and <ANY_REMAINING>
|
.Enum mapping method result, `<NULL>` and `<ANY_REMAINING>`
|
||||||
====
|
====
|
||||||
[source, java, linenums]
|
[source, java, linenums]
|
||||||
[subs="verbatim,attributes"]
|
[subs="verbatim,attributes"]
|
||||||
@ -137,9 +141,52 @@ public class SpecialOrderMapperImpl implements SpecialOrderMapper {
|
|||||||
*Note:* MapStruct would have refrained from mapping the `RETAIL` and `B2B` when `<ANY_UNMAPPED>` was used instead of `<ANY_REMAINING>`.
|
*Note:* MapStruct would have refrained from mapping the `RETAIL` and `B2B` when `<ANY_UNMAPPED>` was used instead of `<ANY_REMAINING>`.
|
||||||
|
|
||||||
|
|
||||||
[WARNING]
|
.Enum mapping method with `<THROW_EXCEPTION>`
|
||||||
====
|
====
|
||||||
The mapping of enum to enum via the `@Mapping` annotation is *DEPRECATED*. It will be removed from future versions of MapStruct. Please adapt existing enum mapping methods to make use of `@ValueMapping` instead.
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
public interface SpecialOrderMapper {
|
||||||
|
|
||||||
|
SpecialOrderMapper INSTANCE = Mappers.getMapper( SpecialOrderMapper.class );
|
||||||
|
|
||||||
|
@ValueMappings({
|
||||||
|
@ValueMapping( source = "STANDARD", target = "DEFAULT" ),
|
||||||
|
@ValueMapping( source = "C2C", target = MappingConstants.THROW_EXCEPTION )
|
||||||
|
})
|
||||||
|
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
.Enum mapping method with `<THROW_EXCEPTION>` result
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
// GENERATED CODE
|
||||||
|
public class SpecialOrderMapperImpl implements SpecialOrderMapper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExternalOrderType orderTypeToExternalOrderType(OrderType orderType) {
|
||||||
|
if ( orderType == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalOrderType externalOrderType;
|
||||||
|
|
||||||
|
switch ( orderType ) {
|
||||||
|
case STANDARD: externalOrderType = ExternalOrderType.DEFAULT;
|
||||||
|
break;
|
||||||
|
case C2C: throw new IllegalArgumentException( "Unexpected enum constant: " + orderType );
|
||||||
|
default: throw new IllegalArgumentException( "Unexpected enum constant: " + orderType );
|
||||||
|
}
|
||||||
|
|
||||||
|
return externalOrderType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
=== Mapping enum-to-String or String-to-enum
|
=== Mapping enum-to-String or String-to-enum
|
||||||
@ -152,6 +199,7 @@ MapStruct supports enum to a String mapping along the same lines as is described
|
|||||||
2. Similarity: `<ANY_UNMAPPED`> stops after handling defined mapping and proceeds to the switch/default clause value.
|
2. Similarity: `<ANY_UNMAPPED`> stops after handling defined mapping and proceeds to the switch/default clause value.
|
||||||
3. Difference: `<ANY_REMAINING>` will result in an error. It acts on the premise that there is name similarity between enum constants in source and target which does not make sense for a String type.
|
3. Difference: `<ANY_REMAINING>` will result in an error. It acts on the premise that there is name similarity between enum constants in source and target which does not make sense for a String type.
|
||||||
4. Difference: Given 1. and 3. there will never be unmapped values.
|
4. Difference: Given 1. and 3. there will never be unmapped values.
|
||||||
|
5. Similarity: `<THROW_EXCEPTION>` can be used for throwing an exception for particular enum values.
|
||||||
|
|
||||||
*`String` to enum*
|
*`String` to enum*
|
||||||
|
|
||||||
@ -159,6 +207,7 @@ MapStruct supports enum to a String mapping along the same lines as is described
|
|||||||
2. Similarity: `<ANY_UNMAPPED`> stops after handling defined mapping and proceeds to the switch/default clause value.
|
2. Similarity: `<ANY_UNMAPPED`> stops after handling defined mapping and proceeds to the switch/default clause value.
|
||||||
3. Similarity: `<ANY_REMAINING>` will create a mapping for each target enum constant and proceed to the switch/default clause value.
|
3. Similarity: `<ANY_REMAINING>` will create a mapping for each target enum constant and proceed to the switch/default clause value.
|
||||||
4. Difference: A switch/default value needs to be provided to have a determined outcome (enum has a limited set of values, `String` has unlimited options). Failing to specify `<ANY_REMAINING>` or `<ANY_UNMAPPED`> will result in a warning.
|
4. Difference: A switch/default value needs to be provided to have a determined outcome (enum has a limited set of values, `String` has unlimited options). Failing to specify `<ANY_REMAINING>` or `<ANY_UNMAPPED`> will result in a warning.
|
||||||
|
5. Similarity: `<THROW_EXCEPTION>` can be used for throwing an exception for any arbitrary `String` value.
|
||||||
|
|
||||||
=== Custom name transformation
|
=== Custom name transformation
|
||||||
|
|
||||||
@ -266,3 +315,42 @@ MapStruct provides the following out of the box enum name transformation strateg
|
|||||||
|
|
||||||
It is also possible to register custom strategies.
|
It is also possible to register custom strategies.
|
||||||
For more information on how to do that have a look at <<custom-enum-transformation-strategy>>
|
For more information on how to do that have a look at <<custom-enum-transformation-strategy>>
|
||||||
|
|
||||||
|
[[value-mapping-composition]]
|
||||||
|
=== ValueMapping Composition
|
||||||
|
|
||||||
|
The `@ValueMapping` annotation supports now `@Target` with `ElementType#ANNOTATION_TYPE` in addition to `ElementType#METHOD`.
|
||||||
|
This allows `@ValueMapping` to be used on other (user defined) annotations for re-use purposes.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.Custom value mapping annotations
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Retention( RetentionPolicy.CLASS )
|
||||||
|
@ValueMapping(source = "EXTRA", target = "SPECIAL")
|
||||||
|
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = "DEFAULT")
|
||||||
|
public @interface CustomValueAnnotation {
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
It can be used to describe some common value mapping relationships to avoid duplicate declarations, as in the following example:
|
||||||
|
|
||||||
|
.Using custom combination annotations
|
||||||
|
====
|
||||||
|
[source, java, linenums]
|
||||||
|
[subs="verbatim,attributes"]
|
||||||
|
----
|
||||||
|
@Mapper
|
||||||
|
public interface ValueMappingCompositionMapper {
|
||||||
|
|
||||||
|
@CustomValueAnnotation
|
||||||
|
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
|
||||||
|
|
||||||
|
@CustomValueAnnotation
|
||||||
|
@ValueMapping(source = "STANDARD", target = "SPECIAL")
|
||||||
|
ExternalOrderType duplicateAnnotation(OrderType orderType);
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
<artifactId>mapstruct-parent</artifactId>
|
<artifactId>mapstruct-parent</artifactId>
|
||||||
<version>1.6.0-SNAPSHOT</version>
|
<version>1.7.0-SNAPSHOT</version>
|
||||||
<relativePath>../parent/pom.xml</relativePath>
|
<relativePath>../parent/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@ -133,8 +133,8 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
<artifactId>jaxb-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
<version>2.3.1</version>
|
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
@ -26,16 +26,36 @@ public final class FullFeatureCompilationExclusionCliEnhancer implements Process
|
|||||||
// SPI not working correctly here.. (not picked up)
|
// SPI not working correctly here.. (not picked up)
|
||||||
additionalExcludes.add( "org/mapstruct/ap/test/bugs/_1596/*.java" );
|
additionalExcludes.add( "org/mapstruct/ap/test/bugs/_1596/*.java" );
|
||||||
additionalExcludes.add( "org/mapstruct/ap/test/bugs/_1801/*.java" );
|
additionalExcludes.add( "org/mapstruct/ap/test/bugs/_1801/*.java" );
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/bugs/_3089/*.java" );
|
||||||
|
|
||||||
switch ( currentJreVersion ) {
|
switch ( currentJreVersion ) {
|
||||||
|
case JAVA_8:
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/**/spring/**/*.java" );
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/cdi/**/*.java" );
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/jakarta_cdi/**/*.java" );
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/annotatewith/deprecated/jdk11/*.java" );
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/**/jdk21/*.java" );
|
||||||
|
if ( processorType == ProcessorTest.ProcessorType.ECLIPSE_JDT ) {
|
||||||
|
additionalExcludes.add(
|
||||||
|
"org/mapstruct/ap/test/selection/methodgenerics/wildcards/LifecycleIntersectionMapper.java" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
case JAVA_9:
|
case JAVA_9:
|
||||||
// TODO find out why this fails:
|
// TODO find out why this fails:
|
||||||
additionalExcludes.add( "org/mapstruct/ap/test/collection/wildcard/BeanMapper.java" );
|
additionalExcludes.add( "org/mapstruct/ap/test/collection/wildcard/BeanMapper.java" );
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/**/jdk21/*.java" );
|
||||||
|
break;
|
||||||
|
case JAVA_11:
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/**/spring/**/*.java" );
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/**/jdk21/*.java" );
|
||||||
|
break;
|
||||||
|
case JAVA_17:
|
||||||
|
additionalExcludes.add( "org/mapstruct/ap/test/**/jdk21/*.java" );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<String> result = new ArrayList<String>( additionalExcludes.size() );
|
Collection<String> result = new ArrayList<>(additionalExcludes.size());
|
||||||
for ( int i = 0; i < additionalExcludes.size(); i++ ) {
|
for ( int i = 0; i < additionalExcludes.size(); i++ ) {
|
||||||
result.add( "-DadditionalExclude" + i + "=" + additionalExcludes.get( i ) );
|
result.add( "-DadditionalExclude" + i + "=" + additionalExcludes.get( i ) );
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class GradleIncrementalCompilationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private GradleRunner getRunner(String... additionalArguments) {
|
private GradleRunner getRunner(String... additionalArguments) {
|
||||||
List<String> fullArguments = new ArrayList<String>( compileArgs );
|
List<String> fullArguments = new ArrayList<>(compileArgs);
|
||||||
fullArguments.addAll( Arrays.asList( additionalArguments ) );
|
fullArguments.addAll( Arrays.asList( additionalArguments ) );
|
||||||
return runner.withArguments( fullArguments );
|
return runner.withArguments( fullArguments );
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.itest.tests;
|
package org.mapstruct.itest.tests;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||||
import org.junit.jupiter.api.condition.EnabledForJreRange;
|
import org.junit.jupiter.api.condition.EnabledForJreRange;
|
||||||
import org.junit.jupiter.api.condition.JRE;
|
import org.junit.jupiter.api.condition.JRE;
|
||||||
import org.junit.jupiter.api.parallel.Execution;
|
import org.junit.jupiter.api.parallel.Execution;
|
||||||
@ -75,13 +76,20 @@ public class MavenIntegrationTest {
|
|||||||
void jaxbTest() {
|
void jaxbTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProcessorTest(baseDir = "jakartaJaxbTest")
|
||||||
|
void jakartaJaxbTest() {
|
||||||
|
}
|
||||||
|
|
||||||
@ProcessorTest(baseDir = "jsr330Test")
|
@ProcessorTest(baseDir = "jsr330Test")
|
||||||
|
@EnabledForJreRange(min = JRE.JAVA_17)
|
||||||
|
@DisabledOnJre(JRE.OTHER)
|
||||||
void jsr330Test() {
|
void jsr330Test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ProcessorTest(baseDir = "lombokBuilderTest", processorTypes = {
|
@ProcessorTest(baseDir = "lombokBuilderTest", processorTypes = {
|
||||||
ProcessorTest.ProcessorType.JAVAC
|
ProcessorTest.ProcessorType.JAVAC
|
||||||
})
|
})
|
||||||
|
@DisabledOnJre(JRE.OTHER)
|
||||||
void lombokBuilderTest() {
|
void lombokBuilderTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +98,7 @@ public class MavenIntegrationTest {
|
|||||||
ProcessorTest.ProcessorType.JAVAC_WITH_PATHS
|
ProcessorTest.ProcessorType.JAVAC_WITH_PATHS
|
||||||
})
|
})
|
||||||
@EnabledForJreRange(min = JRE.JAVA_11)
|
@EnabledForJreRange(min = JRE.JAVA_11)
|
||||||
|
@DisabledOnJre(JRE.OTHER)
|
||||||
void lombokModuleTest() {
|
void lombokModuleTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +117,11 @@ public class MavenIntegrationTest {
|
|||||||
void protobufBuilderTest() {
|
void protobufBuilderTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProcessorTest(baseDir = "sealedSubclassTest")
|
||||||
|
@EnabledForJreRange(min = JRE.JAVA_17)
|
||||||
|
void sealedSubclassTest() {
|
||||||
|
}
|
||||||
|
|
||||||
@ProcessorTest(baseDir = "recordsTest", processorTypes = {
|
@ProcessorTest(baseDir = "recordsTest", processorTypes = {
|
||||||
ProcessorTest.ProcessorType.JAVAC
|
ProcessorTest.ProcessorType.JAVAC
|
||||||
})
|
})
|
||||||
@ -122,6 +136,13 @@ public class MavenIntegrationTest {
|
|||||||
void recordsCrossModuleTest() {
|
void recordsCrossModuleTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ProcessorTest(baseDir = "recordsCrossModuleInterfaceTest", processorTypes = {
|
||||||
|
ProcessorTest.ProcessorType.JAVAC
|
||||||
|
})
|
||||||
|
@EnabledForJreRange(min = JRE.JAVA_17)
|
||||||
|
void recordsCrossModuleInterfaceTest() {
|
||||||
|
}
|
||||||
|
|
||||||
@ProcessorTest(baseDir = "expressionTextBlocksTest", processorTypes = {
|
@ProcessorTest(baseDir = "expressionTextBlocksTest", processorTypes = {
|
||||||
ProcessorTest.ProcessorType.JAVAC
|
ProcessorTest.ProcessorType.JAVAC
|
||||||
})
|
})
|
||||||
@ -134,6 +155,7 @@ public class MavenIntegrationTest {
|
|||||||
}, forkJvm = true)
|
}, forkJvm = true)
|
||||||
// We have to fork the jvm because there is an NPE in com.intellij.openapi.util.SystemInfo.getRtVersion
|
// We have to fork the jvm because there is an NPE in com.intellij.openapi.util.SystemInfo.getRtVersion
|
||||||
// and the kotlin-maven-plugin uses that. See also https://youtrack.jetbrains.com/issue/IDEA-238907
|
// and the kotlin-maven-plugin uses that. See also https://youtrack.jetbrains.com/issue/IDEA-238907
|
||||||
|
@DisabledOnJre(JRE.OTHER)
|
||||||
void kotlinDataTest() {
|
void kotlinDataTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +169,8 @@ public class MavenIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ProcessorTest(baseDir = "springTest")
|
@ProcessorTest(baseDir = "springTest")
|
||||||
|
@EnabledForJreRange(min = JRE.JAVA_17)
|
||||||
|
@DisabledOnJre(JRE.OTHER)
|
||||||
void springTest() {
|
void springTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,14 +134,20 @@ public class ProcessorInvocationInterceptor implements InvocationInterceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void configureProcessor(Verifier verifier) {
|
private void configureProcessor(Verifier verifier) {
|
||||||
String compilerId = processorTestContext.getProcessor().getCompilerId();
|
ProcessorTest.ProcessorType processor = processorTestContext.getProcessor();
|
||||||
|
String compilerId = processor.getCompilerId();
|
||||||
if ( compilerId != null ) {
|
if ( compilerId != null ) {
|
||||||
String profile = processorTestContext.getProcessor().getProfile();
|
String profile = processor.getProfile();
|
||||||
if ( profile == null ) {
|
if ( profile == null ) {
|
||||||
profile = "generate-via-compiler-plugin";
|
profile = "generate-via-compiler-plugin";
|
||||||
}
|
}
|
||||||
verifier.addCliOption( "-P" + profile );
|
verifier.addCliOption( "-P" + profile );
|
||||||
verifier.addCliOption( "-Dcompiler-id=" + compilerId );
|
verifier.addCliOption( "-Dcompiler-id=" + compilerId );
|
||||||
|
if ( processor == ProcessorTest.ProcessorType.JAVAC ) {
|
||||||
|
if ( CURRENT_VERSION.ordinal() >= JRE.JAVA_21.ordinal() ) {
|
||||||
|
verifier.addCliOption( "-Dmaven.compiler.proc=full" );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
verifier.addCliOption( "-Pgenerate-via-processor-plugin" );
|
verifier.addCliOption( "-Pgenerate-via-processor-plugin" );
|
||||||
|
@ -25,6 +25,13 @@
|
|||||||
<additionalExclude2>x</additionalExclude2>
|
<additionalExclude2>x</additionalExclude2>
|
||||||
<additionalExclude3>x</additionalExclude3>
|
<additionalExclude3>x</additionalExclude3>
|
||||||
<additionalExclude4>x</additionalExclude4>
|
<additionalExclude4>x</additionalExclude4>
|
||||||
|
<additionalExclude5>x</additionalExclude5>
|
||||||
|
<additionalExclude6>x</additionalExclude6>
|
||||||
|
<additionalExclude7>x</additionalExclude7>
|
||||||
|
<additionalExclude8>x</additionalExclude8>
|
||||||
|
<additionalExclude9>x</additionalExclude9>
|
||||||
|
<additionalExclude10>x</additionalExclude10>
|
||||||
|
<additionalExclude11>x</additionalExclude11>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -45,6 +52,15 @@
|
|||||||
<exclude>${additionalExclude2}</exclude>
|
<exclude>${additionalExclude2}</exclude>
|
||||||
<exclude>${additionalExclude3}</exclude>
|
<exclude>${additionalExclude3}</exclude>
|
||||||
<exclude>${additionalExclude4}</exclude>
|
<exclude>${additionalExclude4}</exclude>
|
||||||
|
<exclude>${additionalExclude5}</exclude>
|
||||||
|
<exclude>${additionalExclude6}</exclude>
|
||||||
|
<exclude>${additionalExclude7}</exclude>
|
||||||
|
<exclude>${additionalExclude8}</exclude>
|
||||||
|
<exclude>${additionalExclude9}</exclude>
|
||||||
|
<exclude>${additionalExclude10}</exclude>
|
||||||
|
<exclude>${additionalExclude11}</exclude>
|
||||||
|
<exclude>${additionalExclude12}</exclude>
|
||||||
|
<exclude>${additionalExclude13}</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -64,6 +80,10 @@
|
|||||||
<groupId>jakarta.inject</groupId>
|
<groupId>jakarta.inject</groupId>
|
||||||
<artifactId>jakarta.inject-api</artifactId>
|
<artifactId>jakarta.inject-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.enterprise</groupId>
|
||||||
|
<artifactId>jakarta.enterprise.cdi-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -79,6 +99,13 @@
|
|||||||
<groupId>joda-time</groupId>
|
<groupId>joda-time</groupId>
|
||||||
<artifactId>joda-time</artifactId>
|
<artifactId>joda-time</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.xml.bind</groupId>
|
||||||
|
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
@ -89,14 +116,16 @@
|
|||||||
</activation>
|
</activation>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
<version>2.3.2</version>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jaxb</groupId>
|
<groupId>org.glassfish.jaxb</groupId>
|
||||||
<artifactId>jaxb-runtime</artifactId>
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
<version>2.3.2</version>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
64
integrationtest/src/test/resources/jakartaJaxbTest/pom.xml
Normal file
64
integrationtest/src/test/resources/jakartaJaxbTest/pom.xml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-it-parent</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>jakartaJaxbTest</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.xml.bind</groupId>
|
||||||
|
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-impl</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>jaxb2-maven-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>xjc</id>
|
||||||
|
<phase>initialize</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>xjc</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<xjbSources>
|
||||||
|
<xjbSource>${project.build.resources[0].directory}/binding</xjbSource>
|
||||||
|
</xjbSources>
|
||||||
|
<sources>
|
||||||
|
<source>${project.build.resources[0].directory}/schema</source>
|
||||||
|
</sources>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -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 org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class OrderDetailsDto {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private List<String> description;
|
||||||
|
private OrderStatusDto status;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(List<String> description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderStatusDto getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(OrderStatusDto status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
@ -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 org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class OrderDto {
|
||||||
|
|
||||||
|
private Long orderNumber;
|
||||||
|
private Date orderDate;
|
||||||
|
private OrderDetailsDto orderDetails;
|
||||||
|
private ShippingAddressDto shippingAddress;
|
||||||
|
|
||||||
|
public Long getOrderNumber() {
|
||||||
|
return orderNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderNumber(Long orderNumber) {
|
||||||
|
this.orderNumber = orderNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getOrderDate() {
|
||||||
|
return orderDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderDate(Date orderDate) {
|
||||||
|
this.orderDate = orderDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderDetailsDto getOrderDetails() {
|
||||||
|
return orderDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderDetails(OrderDetailsDto orderDetails) {
|
||||||
|
this.orderDetails = orderDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShippingAddressDto getShippingAddress() {
|
||||||
|
return shippingAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShippingAddress(ShippingAddressDto shippingAddress) {
|
||||||
|
this.shippingAddress = shippingAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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 org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public enum OrderStatusDto {
|
||||||
|
|
||||||
|
ORDERED( "small" ),
|
||||||
|
PROCESSED( "medium" ),
|
||||||
|
DELIVERED( "large" );
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
OrderStatusDto(String v) {
|
||||||
|
value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OrderStatusDto fromValue(String v) {
|
||||||
|
for ( OrderStatusDto c : OrderStatusDto.values() ) {
|
||||||
|
if ( c.value.equals( v ) ) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException( v );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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 org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class ShippingAddressDto {
|
||||||
|
|
||||||
|
private String street;
|
||||||
|
private String houseNumber;
|
||||||
|
private String city;
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreet(String street) {
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHouseNumber() {
|
||||||
|
return houseNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHouseNumber(String houseNumber) {
|
||||||
|
this.houseNumber = houseNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(String city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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 org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.test1.OrderDetailsType;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.test1.OrderType;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.test2.OrderStatusType;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.test2.ShippingAddressType;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.underscores.SubType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
@Mapper(uses = {
|
||||||
|
org.mapstruct.itest.jakarta.jaxb.xsd.test1.ObjectFactory.class,
|
||||||
|
org.mapstruct.itest.jakarta.jaxb.xsd.test2.ObjectFactory.class,
|
||||||
|
org.mapstruct.itest.jakarta.jaxb.xsd.underscores.ObjectFactory.class
|
||||||
|
})
|
||||||
|
public interface SourceTargetMapper {
|
||||||
|
|
||||||
|
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
|
||||||
|
|
||||||
|
// source 2 target methods
|
||||||
|
OrderDto sourceToTarget(OrderType source);
|
||||||
|
|
||||||
|
OrderDetailsDto detailsToDto(OrderDetailsType source);
|
||||||
|
|
||||||
|
OrderStatusDto statusToDto(OrderStatusType source);
|
||||||
|
|
||||||
|
ShippingAddressDto shippingAddressToDto(ShippingAddressType source);
|
||||||
|
|
||||||
|
SubTypeDto subTypeToDto(SubType source);
|
||||||
|
|
||||||
|
// target 2 source methods
|
||||||
|
OrderType targetToSource(OrderDto target);
|
||||||
|
|
||||||
|
OrderDetailsType dtoToDetails(OrderDetailsDto target);
|
||||||
|
|
||||||
|
OrderStatusType dtoToStatus(OrderStatusDto target);
|
||||||
|
|
||||||
|
ShippingAddressType dtoToShippingAddress(ShippingAddressDto source);
|
||||||
|
|
||||||
|
SubType dtoToSubType(SubTypeDto source);
|
||||||
|
}
|
@ -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 org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
public class SubTypeDto extends SuperTypeDto {
|
||||||
|
private String declaredCamelCase;
|
||||||
|
private String declaredUnderscore;
|
||||||
|
|
||||||
|
public String getDeclaredCamelCase() {
|
||||||
|
return declaredCamelCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeclaredCamelCase(String declaredCamelCase) {
|
||||||
|
this.declaredCamelCase = declaredCamelCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeclaredUnderscore() {
|
||||||
|
return declaredUnderscore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeclaredUnderscore(String declaredUnderscore) {
|
||||||
|
this.declaredUnderscore = declaredUnderscore;
|
||||||
|
}
|
||||||
|
}
|
@ -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 org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
public class SuperTypeDto {
|
||||||
|
private String inheritedCamelCase;
|
||||||
|
private String inheritedUnderscore;
|
||||||
|
|
||||||
|
public String getInheritedCamelCase() {
|
||||||
|
return inheritedCamelCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInheritedCamelCase(String inheritedCamelCase) {
|
||||||
|
this.inheritedCamelCase = inheritedCamelCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInheritedUnderscore() {
|
||||||
|
return inheritedUnderscore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInheritedUnderscore(String inheritedUnderscore) {
|
||||||
|
this.inheritedUnderscore = inheritedUnderscore;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<jaxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
|
||||||
|
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
|
||||||
|
jaxb:extensionBindingPrefixes="xjc"
|
||||||
|
version="3.0" >
|
||||||
|
|
||||||
|
|
||||||
|
<jaxb:globalBindings
|
||||||
|
fixedAttributeAsConstantProperty="true"
|
||||||
|
typesafeEnumBase="xs:string"
|
||||||
|
typesafeEnumMemberName="generateName"
|
||||||
|
generateIsSetMethod="true"
|
||||||
|
generateElementProperty="true" >
|
||||||
|
<xjc:noValidator/>
|
||||||
|
<xjc:noValidatingUnmarshaller/>
|
||||||
|
</jaxb:globalBindings>
|
||||||
|
|
||||||
|
</jaxb:bindings>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:test1="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/test1"
|
||||||
|
xmlns:test2="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/test2"
|
||||||
|
targetNamespace="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/test1"
|
||||||
|
elementFormDefault="qualified" version="1.0.0">
|
||||||
|
|
||||||
|
<import namespace="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/test2" schemaLocation="test2.xsd"/>
|
||||||
|
|
||||||
|
<element name="Order" type="test1:OrderType" />
|
||||||
|
<complexType name="OrderType">
|
||||||
|
<sequence>
|
||||||
|
<element name="orderNumber" type="long"/>
|
||||||
|
<element name="orderDate" type="dateTime"/>
|
||||||
|
<element name="orderDetails" type="test1:OrderDetailsType"/>
|
||||||
|
<element name="shippingAddress" type="test2:ShippingAddressType"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<element name="OrderDetails" type="test1:OrderDetailsType" />
|
||||||
|
<complexType name="OrderDetailsType">
|
||||||
|
<sequence>
|
||||||
|
<element name="name" type="string"/>
|
||||||
|
<element name="description" minOccurs="1" maxOccurs="5" type="string"/>
|
||||||
|
<element name="status" type="test2:OrderStatusType"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
</schema>
|
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:test2="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/test2"
|
||||||
|
targetNamespace="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/test2"
|
||||||
|
elementFormDefault="qualified" version="1.0.0">
|
||||||
|
|
||||||
|
<element name="OrderStatus" type="test2:OrderStatusType" />
|
||||||
|
<simpleType name="OrderStatusType">
|
||||||
|
<restriction base="string">
|
||||||
|
<enumeration value="ordered" />
|
||||||
|
<enumeration value="processed" />
|
||||||
|
<enumeration value="delivered" />
|
||||||
|
</restriction>
|
||||||
|
</simpleType>
|
||||||
|
|
||||||
|
<element name="ShippingAddress" type="test2:ShippingAddressType" />
|
||||||
|
<complexType name="ShippingAddressType">
|
||||||
|
<sequence>
|
||||||
|
<element name="street" type="string"/>
|
||||||
|
<element name="houseNumber" type="string"/>
|
||||||
|
<element name="city" type="string"/>
|
||||||
|
<element name="country" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
</schema>
|
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:underscores="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/underscores"
|
||||||
|
targetNamespace="http://www.mapstruct.org/itest/jakarta/jaxb/xsd/underscores"
|
||||||
|
elementFormDefault="qualified" version="1.0.0">
|
||||||
|
|
||||||
|
<element name="Super" type="underscores:SuperType" />
|
||||||
|
<complexType name="SuperType">
|
||||||
|
<sequence>
|
||||||
|
<element name="inheritedCamelCase" type="string"/>
|
||||||
|
<element name="inherited_underscore" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<element name="Sub" type="underscores:SubType" />
|
||||||
|
<complexType name="SubType">
|
||||||
|
<complexContent>
|
||||||
|
<extension base="underscores:SuperType">
|
||||||
|
<sequence>
|
||||||
|
<element name="declaredCamelCase" type="string"/>
|
||||||
|
<element name="declared_underscore" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</extension>
|
||||||
|
</complexContent>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
</schema>
|
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.itest.jakarta.jaxb;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.JAXBContext;
|
||||||
|
import jakarta.xml.bind.JAXBElement;
|
||||||
|
import jakarta.xml.bind.JAXBException;
|
||||||
|
import jakarta.xml.bind.Marshaller;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.test1.ObjectFactory;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.test1.OrderType;
|
||||||
|
import org.mapstruct.itest.jakarta.jaxb.xsd.underscores.SubType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for generation of Jakarta JAXB based mapper implementations.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Bogdanchikov
|
||||||
|
*/
|
||||||
|
public class JakartaJaxbBasedMapperTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMapJakartaJaxb() throws ParseException, JAXBException {
|
||||||
|
|
||||||
|
SourceTargetMapper mapper = SourceTargetMapper.INSTANCE;
|
||||||
|
|
||||||
|
OrderDto source1 = new OrderDto();
|
||||||
|
source1.setOrderDetails( new OrderDetailsDto() );
|
||||||
|
source1.setOrderNumber( 11L );
|
||||||
|
source1.setOrderDate( createDate( "31-08-1982 10:20:56" ) );
|
||||||
|
source1.setShippingAddress( new ShippingAddressDto() );
|
||||||
|
source1.getShippingAddress().setCity( "SmallTown" );
|
||||||
|
source1.getShippingAddress().setHouseNumber( "11a" );
|
||||||
|
source1.getShippingAddress().setStreet( "Awesome rd" );
|
||||||
|
source1.getShippingAddress().setCountry( "USA" );
|
||||||
|
source1.getOrderDetails().setDescription( new ArrayList<String>() );
|
||||||
|
source1.getOrderDetails().setName( "Shopping list for a Mapper" );
|
||||||
|
source1.getOrderDetails().getDescription().add( "1 MapStruct" );
|
||||||
|
source1.getOrderDetails().getDescription().add( "3 Lines of Code" );
|
||||||
|
source1.getOrderDetails().getDescription().add( "1 Dose of Luck" );
|
||||||
|
source1.getOrderDetails().setStatus( OrderStatusDto.ORDERED );
|
||||||
|
|
||||||
|
// map to JAXB
|
||||||
|
OrderType target = mapper.targetToSource( source1 );
|
||||||
|
|
||||||
|
// do a pretty print
|
||||||
|
ObjectFactory of = new ObjectFactory();
|
||||||
|
System.out.println( toXml( of.createOrder( target ) ) );
|
||||||
|
|
||||||
|
// map back from JAXB
|
||||||
|
OrderDto source2 = mapper.sourceToTarget( target );
|
||||||
|
|
||||||
|
// verify that source1 and source 2 are equal
|
||||||
|
assertThat( source2.getOrderNumber() ).isEqualTo( source1.getOrderNumber() );
|
||||||
|
assertThat( source2.getOrderDate() ).isEqualTo( source1.getOrderDate() );
|
||||||
|
assertThat( source2.getOrderDetails().getDescription().size() ).isEqualTo(
|
||||||
|
source1.getOrderDetails().getDescription().size()
|
||||||
|
);
|
||||||
|
assertThat( source2.getOrderDetails().getDescription().get( 0 ) ).isEqualTo(
|
||||||
|
source1.getOrderDetails().getDescription().get( 0 )
|
||||||
|
);
|
||||||
|
assertThat( source2.getOrderDetails().getDescription().get( 1 ) ).isEqualTo(
|
||||||
|
source1.getOrderDetails().getDescription().get( 1 )
|
||||||
|
);
|
||||||
|
assertThat( source2.getOrderDetails().getDescription().get( 2 ) ).isEqualTo(
|
||||||
|
source1.getOrderDetails().getDescription().get( 2 )
|
||||||
|
);
|
||||||
|
assertThat( source2.getOrderDetails().getName() ).isEqualTo( source1.getOrderDetails().getName() );
|
||||||
|
assertThat( source2.getOrderDetails().getStatus() ).isEqualTo( source1.getOrderDetails().getStatus() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void underscores() throws ParseException, JAXBException {
|
||||||
|
|
||||||
|
SourceTargetMapper mapper = SourceTargetMapper.INSTANCE;
|
||||||
|
|
||||||
|
SubTypeDto source1 = new SubTypeDto();
|
||||||
|
source1.setInheritedCamelCase("InheritedCamelCase");
|
||||||
|
source1.setInheritedUnderscore("InheritedUnderscore");
|
||||||
|
source1.setDeclaredCamelCase("DeclaredCamelCase");
|
||||||
|
source1.setDeclaredUnderscore("DeclaredUnderscore");
|
||||||
|
|
||||||
|
SubType target = mapper.dtoToSubType( source1 );
|
||||||
|
|
||||||
|
SubTypeDto source2 = mapper.subTypeToDto( target );
|
||||||
|
|
||||||
|
assertThat( source2.getInheritedCamelCase() ).isEqualTo( source1.getInheritedCamelCase() );
|
||||||
|
assertThat( source2.getInheritedUnderscore() ).isEqualTo( source1.getInheritedUnderscore() );
|
||||||
|
assertThat( source2.getDeclaredCamelCase() ).isEqualTo( source1.getDeclaredCamelCase() );
|
||||||
|
assertThat( source2.getDeclaredUnderscore() ).isEqualTo( source1.getDeclaredUnderscore() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date createDate(String date) throws ParseException {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat( "dd-M-yyyy hh:mm:ss" );
|
||||||
|
return sdf.parse( date );
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toXml(JAXBElement<?> element) throws JAXBException {
|
||||||
|
JAXBContext jc = JAXBContext.newInstance( element.getValue().getClass() );
|
||||||
|
Marshaller marshaller = jc.createMarshaller();
|
||||||
|
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
marshaller.marshal( element, baos );
|
||||||
|
return baos.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -51,7 +51,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jaxb</groupId>
|
<groupId>org.glassfish.jaxb</groupId>
|
||||||
<artifactId>jaxb-runtime</artifactId>
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
<version>2.3.2</version>
|
<version>${jaxb-runtime.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -66,14 +66,16 @@
|
|||||||
</activation>
|
</activation>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
<version>2.3.2</version>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jaxb</groupId>
|
<groupId>org.glassfish.jaxb</groupId>
|
||||||
<artifactId>jaxb-runtime</artifactId>
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
<version>2.3.2</version>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>recordsCrossModuleInterfaceTest</artifactId>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>records-cross-module-1</artifactId>
|
||||||
|
|
||||||
|
</project>
|
@ -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 org.mapstruct.itest.records.module1;
|
||||||
|
|
||||||
|
public interface NestedInterface {
|
||||||
|
String field();
|
||||||
|
}
|
@ -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 org.mapstruct.itest.records.module1;
|
||||||
|
|
||||||
|
public interface RootInterface {
|
||||||
|
NestedInterface nested();
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.itest.records.module1;
|
||||||
|
|
||||||
|
public record SourceNestedRecord(
|
||||||
|
String field
|
||||||
|
) implements NestedInterface {
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.itest.records.module1;
|
||||||
|
|
||||||
|
public record SourceRootRecord(
|
||||||
|
SourceNestedRecord nested
|
||||||
|
) implements RootInterface {
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>recordsCrossModuleInterfaceTest</artifactId>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>records-cross-module-2</artifactId>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>records-cross-module-1</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -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 org.mapstruct.itest.records.module2;
|
||||||
|
|
||||||
|
import org.mapstruct.itest.records.module1.SourceRootRecord;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface RecordInterfaceIssueMapper {
|
||||||
|
|
||||||
|
RecordInterfaceIssueMapper INSTANCE = Mappers.getMapper(RecordInterfaceIssueMapper.class);
|
||||||
|
|
||||||
|
TargetRootRecord map(SourceRootRecord source);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.itest.records.module2;
|
||||||
|
|
||||||
|
public record TargetNestedRecord(
|
||||||
|
String field
|
||||||
|
) {
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.itest.records.module2;
|
||||||
|
|
||||||
|
public record TargetRootRecord(
|
||||||
|
TargetNestedRecord nested
|
||||||
|
) {
|
||||||
|
}
|
@ -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 org.mapstruct.itest.records.module2;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mapstruct.itest.records.module1.SourceRootRecord;
|
||||||
|
import org.mapstruct.itest.records.module1.SourceNestedRecord;
|
||||||
|
|
||||||
|
public class RecordsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMap() {
|
||||||
|
SourceRootRecord source = new SourceRootRecord( new SourceNestedRecord( "test" ) );
|
||||||
|
TargetRootRecord target = RecordInterfaceIssueMapper.INSTANCE.map( source );
|
||||||
|
|
||||||
|
assertThat( target ).isNotNull();
|
||||||
|
assertThat( target.nested() ).isNotNull();
|
||||||
|
assertThat( target.nested().field() ).isEqualTo( "test" );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright MapStruct Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-it-parent</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>recordsCrossModuleInterfaceTest</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>module-1</module>
|
||||||
|
<module>module-2</module>
|
||||||
|
</modules>
|
||||||
|
</project>
|
@ -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 org.mapstruct.itest.records;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Target(ElementType.CONSTRUCTOR)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Default {
|
||||||
|
}
|
@ -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 org.mapstruct.itest.records;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
public record Task( String id, Long number ) {
|
||||||
|
|
||||||
|
}
|
@ -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 org.mapstruct.itest.records;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
public record TaskDto(String id, Long number) {
|
||||||
|
|
||||||
|
@Default
|
||||||
|
TaskDto(String id) {
|
||||||
|
this( id, 1L );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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 org.mapstruct.itest.records;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.ReportingPolicy;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
|
||||||
|
public interface TaskMapper {
|
||||||
|
|
||||||
|
TaskMapper INSTANCE = Mappers.getMapper( TaskMapper.class );
|
||||||
|
|
||||||
|
TaskDto toRecord(Task source);
|
||||||
|
|
||||||
|
}
|
@ -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 org.mapstruct.itest.records.nested;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public record Address(String street, String city) {
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user