mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
Compare commits
85 Commits
1.6.0.Beta
...
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 |
20
.github/scripts/update-website.sh
vendored
20
.github/scripts/update-website.sh
vendored
@ -38,16 +38,22 @@ STABLE_VERSION=`grep stableVersion config.toml | sed 's/.*"\(.*\)"/\1/'`
|
||||
MAJOR_MINOR_STABLE_VERSION=$(computeMajorMinorVersion $STABLE_VERSION)
|
||||
|
||||
echo "📝 Updating versions"
|
||||
sed -i '' -e "s/^devVersion = \"\(.*\)\"/devVersion = \"${VERSION}\"/g" config.toml
|
||||
|
||||
SEDOPTION="-i"
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
SEDOPTION="-i ''"
|
||||
fi
|
||||
|
||||
sed $SEDOPTION -e "s/^devVersion = \"\(.*\)\"/devVersion = \"${VERSION}\"/g" config.toml
|
||||
|
||||
if [ "${STABLE}" == "yes" ]; then
|
||||
sed -i '' -e "s/^stableVersion = \"\(.*\)\"/stableVersion = \"${VERSION}\"/g" config.toml
|
||||
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 -i '' -e "s/^order = \(.*\)/order = 500/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||
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 -i '' -e "s/^order = \(.*\)/order = ${NEXT_STABLE_ORDER}/g" data/releases/${MAJOR_MINOR_STABLE_VERSION}.toml
|
||||
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
|
||||
@ -55,11 +61,11 @@ elif [ "${MAJOR_MINOR_DEV_VERSION}" != "${MAJOR_MINOR_VERSION}" ]; then
|
||||
# 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 -i '' -e "s/^order = \(.*\)/order = 1000/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||
sed $SEDOPTION -e "s/^order = \(.*\)/order = 1000/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||
fi
|
||||
|
||||
sed -i '' -e "s/^name = \"\(.*\)\"/name = \"${VERSION}\"/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||
sed -i '' -e "s/^releaseDate = \(.*\)/releaseDate = $(date +%F)/g" data/releases/${MAJOR_MINOR_VERSION}.toml
|
||||
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
|
||||
|
||||
|
8
.github/workflows/java-ea.yml
vendored
8
.github/workflows/java-ea.yml
vendored
@ -7,15 +7,11 @@ env:
|
||||
|
||||
jobs:
|
||||
test_jdk_ea:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java: [19-ea]
|
||||
name: 'Linux JDK ${{ matrix.java }}'
|
||||
name: 'Linux JDK EA'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Set up JDK'
|
||||
uses: oracle-actions/setup-java@v1
|
||||
with:
|
||||
|
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:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java: [17, 21]
|
||||
java: [21]
|
||||
name: 'Linux JDK ${{ matrix.java }}'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Set up JDK'
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ matrix.java }}
|
||||
- name: 'Test'
|
||||
run: ./mvnw ${MAVEN_ARGS} -Djacoco.skip=true install -DskipDistribution=true
|
||||
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
|
||||
run: ./mvnw ${MAVEN_ARGS} -Djacoco.skip=${{ matrix.java != 21 }} install -DskipDistribution=${{ matrix.java != 21 }}
|
||||
- name: 'Generate coverage report'
|
||||
if: matrix.java == 21
|
||||
run: ./mvnw jacoco:report
|
||||
- name: 'Upload coverage to Codecov'
|
||||
if: matrix.java == 21
|
||||
uses: codecov/codecov-action@v2
|
||||
- name: 'Publish Snapshots'
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && 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
|
||||
linux-jdk-8:
|
||||
name: 'Linux JDK 8'
|
||||
integration_test_jdk:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java: [ 8, 11, 17 ]
|
||||
name: 'Linux JDK ${{ matrix.java }}'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v3
|
||||
- name: 'Set up JDK 11 for building everything'
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Set up JDK 21 for building everything'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
java-version: 21
|
||||
- name: 'Install Processor'
|
||||
run: ./mvnw ${MAVEN_ARGS} -DskipTests install -pl processor -am
|
||||
- name: 'Set up JDK 8 for running integration tests'
|
||||
uses: actions/setup-java@v3
|
||||
- name: 'Set up JDK ${{ matrix.java }} for running integration tests'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 8
|
||||
java-version: ${{ matrix.java }}
|
||||
- name: 'Run integration tests'
|
||||
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
|
||||
|
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 21
|
||||
distribution: 'zulu'
|
||||
cache: maven
|
||||
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
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 "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
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
|
||||
@ -72,6 +72,10 @@ jobs:
|
||||
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
|
||||
@ -109,5 +113,5 @@ jobs:
|
||||
VERSION: ${{ github.event.inputs.version }}
|
||||
GH_BOT_EMAIL: ${{ vars.GH_BOT_EMAIL }}
|
||||
run: |
|
||||
chmod +x update-website.sh
|
||||
./update-website.sh
|
||||
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
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# 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,29 +1,29 @@
|
||||
### Features
|
||||
|
||||
* Support conditional mapping for source parameters (#2610, #3459, #3270)
|
||||
* Add `@SourcePropertyName` to handle a property name of the source object (#3323) - Currently only applicable for `@Condition` methods
|
||||
* Support for Java 21 Sequenced Collections (#3240)
|
||||
|
||||
|
||||
### Enhancements
|
||||
|
||||
* Improve error message for mapping to `target = "."` using expression (#3485)
|
||||
* Improve error messages for auto generated mappings (#2788)
|
||||
* Remove unnecessary casts to long (#3400)
|
||||
* 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
|
||||
|
||||
* `@Condition` cannot be used only with `@Context` parameters (#3561)
|
||||
* `@Condition` treated as ambiguous mapping for methods returning Boolean/boolean (#3565)
|
||||
* Subclass mapping warns about unmapped property that is mapped in referenced mapper (#3360)
|
||||
* Interface inherited build method is not found (#3463)
|
||||
* Bean with getter returning Stream is treating the Stream as an alternative setter (#3462)
|
||||
* Using `Mapping#expression` and `Mapping#conditionalQualifiedBy(Name)` should lead to compile error (#3413)
|
||||
* Defined mappings for subclass mappings with runtime exception subclass exhaustive strategy not working if result type is abstract class (#3331)
|
||||
* Improve error message when mapping non-iterable to array (#3786)
|
||||
|
||||
### Documentation
|
||||
|
||||
* Clarify that `Mapping#ignoreByDefault` is inherited in nested mappings in documentation (#3577)
|
||||
|
||||
### Build
|
||||
|
||||
* Improve tests to show that Lombok `@SuperBuilder` is supported (#3524)
|
||||
* Add Java 21 CI matrix build (#3473)
|
||||
### 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>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -146,7 +146,9 @@
|
||||
</module>
|
||||
<module name="TypecastParenPad"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround"/>
|
||||
<module name="WhitespaceAround">
|
||||
<property name="ignoreEnhancedForColon" value="false"/>
|
||||
</module>
|
||||
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="tokens" value="IMPORT, CLASS_DEF, INTERFACE_DEF, STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -132,6 +132,18 @@ public @interface BeanMapping {
|
||||
*/
|
||||
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
|
||||
* warning will be issued on missing source or target properties.
|
||||
|
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();
|
||||
}
|
@ -66,19 +66,38 @@ public @interface IterableMapping {
|
||||
/**
|
||||
* 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.
|
||||
* <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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
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
|
||||
* mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error.
|
||||
|
@ -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
|
||||
* {@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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
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
|
||||
* type {@code String} to an map with value type {@link Date} or vice-versa. Will be ignored for all other value
|
||||
* 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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
String valueDateFormat() default "";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
String keyNumberFormat() default "";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
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
|
||||
* case multiple mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found'
|
||||
|
@ -281,6 +281,18 @@ public @interface Mapper {
|
||||
*/
|
||||
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
|
||||
* such as CDI, Spring and JSR 330.
|
||||
|
@ -249,6 +249,18 @@ public @interface MapperConfig {
|
||||
*/
|
||||
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
|
||||
* such as CDI, Spring and JSR 330.
|
||||
|
@ -20,7 +20,7 @@ import org.mapstruct.control.MappingControl;
|
||||
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>
|
||||
* 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
|
||||
@ -136,9 +136,6 @@ import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||
* }
|
||||
* </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
|
||||
*/
|
||||
|
||||
@ -178,19 +175,38 @@ public @interface Mapping {
|
||||
/**
|
||||
* 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.
|
||||
* <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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <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}.
|
||||
* @see #locale()
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
@ -290,6 +306,9 @@ public @interface Mapping {
|
||||
* 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.
|
||||
* <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
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@ package org.mapstruct;
|
||||
* {@link NullValuePropertyMappingStrategy} can be defined on {@link MapperConfig}, {@link Mapper}, {@link BeanMapping}
|
||||
* and {@link Mapping}.
|
||||
* 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
|
||||
* {@code @}{@link MappingTarget}).
|
||||
|
@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@ -130,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.
|
||||
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>
|
||||
<![CDATA[
|
||||
|
@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -308,7 +308,7 @@ Conditional mapping can also be used to check if a source parameter should be ma
|
||||
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
|
||||
====
|
||||
|
@ -261,7 +261,7 @@ 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 bean mapping via `@BeanMapping#ignoreUnmappedSourceProperties()`, it takes precedence over both `@Mapper#unmappedSourcePolicy()` and the option.
|
||||
|`WARN`
|
||||
|`IGNORE`
|
||||
|
||||
|`mapstruct.
|
||||
disableBuilders`
|
||||
|
@ -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 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`).
|
||||
@ -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 type has a parameterless public static builder creation method that returns a builder.
|
||||
So for example `Person` has a public static method that returns `PersonBuilder`.
|
||||
* The type has either
|
||||
** 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.
|
||||
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
|
||||
@ -448,7 +451,7 @@ E.g. If an object factory exists for our `PersonBuilder` then this factory would
|
||||
|
||||
[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
|
||||
|
@ -280,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.
|
||||
====
|
||||
|
||||
[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]
|
||||
====
|
||||
In some cases the `ReportingPolicy` that is going to be used for the generated nested method would be `IGNORE`.
|
||||
@ -401,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.
|
||||
|
||||
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
|
||||
====
|
||||
[source, java, linenums]
|
||||
|
@ -192,7 +192,7 @@ The option `DEFAULT` should not be used explicitly. It is used to distinguish be
|
||||
|
||||
[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]]
|
||||
@ -212,16 +212,20 @@ When an iterable or map mapping method declares an interface type as return type
|
||||
|
||||
|`Set`|`LinkedHashSet`
|
||||
|
||||
|`SequencedSet`|`LinkedHashSet`
|
||||
|
||||
|`SortedSet`|`TreeSet`
|
||||
|
||||
|`NavigableSet`|`TreeSet`
|
||||
|
||||
|`Map`|`LinkedHashMap`
|
||||
|
||||
|`SequencedMap`|`LinkedHashMap`
|
||||
|
||||
|`SortedMap`|`TreeMap`
|
||||
|
||||
|`NavigableMap`|`TreeMap`
|
||||
|
||||
|`ConcurrentMap`|`ConcurrentHashMap`
|
||||
|`ConcurrentNavigableMap`|`ConcurrentSkipListMap`
|
||||
|===
|
||||
|===
|
@ -189,12 +189,6 @@ public class SpecialOrderMapperImpl implements SpecialOrderMapper {
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
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.
|
||||
====
|
||||
|
||||
=== Mapping enum-to-String or String-to-enum
|
||||
|
||||
MapStruct supports enum to a String mapping along the same lines as is described in <<Mapping enum to enum types, enum-to-enum types>>. There are similarities and differences:
|
||||
|
@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -30,9 +30,11 @@ public final class FullFeatureCompilationExclusionCliEnhancer implements Process
|
||||
|
||||
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" );
|
||||
@ -41,6 +43,14 @@ public final class FullFeatureCompilationExclusionCliEnhancer implements Process
|
||||
case JAVA_9:
|
||||
// TODO find out why this fails:
|
||||
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;
|
||||
default:
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
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.JRE;
|
||||
import org.junit.jupiter.api.parallel.Execution;
|
||||
@ -80,12 +81,15 @@ public class MavenIntegrationTest {
|
||||
}
|
||||
|
||||
@ProcessorTest(baseDir = "jsr330Test")
|
||||
@EnabledForJreRange(min = JRE.JAVA_17)
|
||||
@DisabledOnJre(JRE.OTHER)
|
||||
void jsr330Test() {
|
||||
}
|
||||
|
||||
@ProcessorTest(baseDir = "lombokBuilderTest", processorTypes = {
|
||||
ProcessorTest.ProcessorType.JAVAC
|
||||
})
|
||||
@DisabledOnJre(JRE.OTHER)
|
||||
void lombokBuilderTest() {
|
||||
}
|
||||
|
||||
@ -94,6 +98,7 @@ public class MavenIntegrationTest {
|
||||
ProcessorTest.ProcessorType.JAVAC_WITH_PATHS
|
||||
})
|
||||
@EnabledForJreRange(min = JRE.JAVA_11)
|
||||
@DisabledOnJre(JRE.OTHER)
|
||||
void lombokModuleTest() {
|
||||
}
|
||||
|
||||
@ -131,6 +136,13 @@ public class MavenIntegrationTest {
|
||||
void recordsCrossModuleTest() {
|
||||
}
|
||||
|
||||
@ProcessorTest(baseDir = "recordsCrossModuleInterfaceTest", processorTypes = {
|
||||
ProcessorTest.ProcessorType.JAVAC
|
||||
})
|
||||
@EnabledForJreRange(min = JRE.JAVA_17)
|
||||
void recordsCrossModuleInterfaceTest() {
|
||||
}
|
||||
|
||||
@ProcessorTest(baseDir = "expressionTextBlocksTest", processorTypes = {
|
||||
ProcessorTest.ProcessorType.JAVAC
|
||||
})
|
||||
@ -143,6 +155,7 @@ public class MavenIntegrationTest {
|
||||
}, forkJvm = true)
|
||||
// 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
|
||||
@DisabledOnJre(JRE.OTHER)
|
||||
void kotlinDataTest() {
|
||||
}
|
||||
|
||||
@ -156,6 +169,8 @@ public class MavenIntegrationTest {
|
||||
}
|
||||
|
||||
@ProcessorTest(baseDir = "springTest")
|
||||
@EnabledForJreRange(min = JRE.JAVA_17)
|
||||
@DisabledOnJre(JRE.OTHER)
|
||||
void springTest() {
|
||||
}
|
||||
|
||||
|
@ -134,14 +134,20 @@ public class ProcessorInvocationInterceptor implements InvocationInterceptor {
|
||||
}
|
||||
|
||||
private void configureProcessor(Verifier verifier) {
|
||||
String compilerId = processorTestContext.getProcessor().getCompilerId();
|
||||
ProcessorTest.ProcessorType processor = processorTestContext.getProcessor();
|
||||
String compilerId = processor.getCompilerId();
|
||||
if ( compilerId != null ) {
|
||||
String profile = processorTestContext.getProcessor().getProfile();
|
||||
String profile = processor.getProfile();
|
||||
if ( profile == null ) {
|
||||
profile = "generate-via-compiler-plugin";
|
||||
}
|
||||
verifier.addCliOption( "-P" + profile );
|
||||
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 {
|
||||
verifier.addCliOption( "-Pgenerate-via-processor-plugin" );
|
||||
|
@ -27,6 +27,11 @@
|
||||
<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>
|
||||
|
||||
<build>
|
||||
@ -49,6 +54,13 @@
|
||||
<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>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
@ -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,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) {
|
||||
|
||||
}
|
@ -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 CareProvider(String externalId, Address address) {
|
||||
|
||||
}
|
@ -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 CareProviderDto(String id, String street, String city) {
|
||||
|
||||
}
|
@ -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.itest.records.nested;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
|
||||
public interface CareProviderMapper {
|
||||
|
||||
CareProviderMapper INSTANCE = Mappers.getMapper( CareProviderMapper.class );
|
||||
|
||||
@Mapping(target = "id", source = "externalId")
|
||||
@Mapping(target = "street", source = "address.street")
|
||||
@Mapping(target = "city", source = "address.city")
|
||||
CareProviderDto map(CareProvider source);
|
||||
}
|
@ -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.nested;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class NestedRecordsTest {
|
||||
|
||||
@Test
|
||||
public void shouldMapRecord() {
|
||||
CareProvider source = new CareProvider( "kermit", new Address( "Sesame Street", "New York" ) );
|
||||
CareProviderDto target = CareProviderMapper.INSTANCE.map( source );
|
||||
|
||||
assertThat( target ).isNotNull();
|
||||
assertThat( target.id() ).isEqualTo( "kermit" );
|
||||
assertThat( target.street() ).isEqualTo( "Sesame Street" );
|
||||
assertThat( target.city() ).isEqualTo( "New York" );
|
||||
}
|
||||
}
|
@ -32,7 +32,6 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<compilerArg>-proc:none</compilerArg>
|
||||
|
@ -38,7 +38,6 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<compilerArg>-XprintProcessorInfo</compilerArg>
|
||||
|
@ -32,7 +32,6 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<compilerArg>-proc:none</compilerArg>
|
||||
|
@ -38,7 +38,6 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<compilerArg>-XprintProcessorInfo</compilerArg>
|
||||
|
471
mvnw
vendored
471
mvnw
vendored
@ -19,292 +19,241 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
# Apache Maven Wrapper startup batch script, version 3.3.2
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
|
||||
# MVNW_REPOURL - repo url base for downloading maven distribution
|
||||
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
set -euf
|
||||
[ "${MVNW_VERBOSE-}" != debug ] || set -x
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
# OS specific support.
|
||||
native_path() { printf %s\\n "$1"; }
|
||||
case "$(uname)" in
|
||||
CYGWIN* | MINGW*)
|
||||
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
|
||||
native_path() { cygpath --path --windows "$1"; }
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# set JAVACMD and JAVACCMD
|
||||
set_java_home() {
|
||||
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
|
||||
if [ -n "${JAVA_HOME-}" ]; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACCMD="$JAVA_HOME/jre/sh/javac"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACCMD="$JAVA_HOME/bin/javac"
|
||||
|
||||
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
|
||||
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
|
||||
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
JAVACMD="$(
|
||||
'set' +e
|
||||
'unset' -f command 2>/dev/null
|
||||
'command' -v java
|
||||
)" || :
|
||||
JAVACCMD="$(
|
||||
'set' +e
|
||||
'unset' -f command 2>/dev/null
|
||||
'command' -v javac
|
||||
)" || :
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
|
||||
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
|
||||
return 1
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
fi
|
||||
}
|
||||
|
||||
# hash string like Java String::hashCode
|
||||
hash_string() {
|
||||
str="${1:-}" h=0
|
||||
while [ -n "$str" ]; do
|
||||
char="${str%"${str#?}"}"
|
||||
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
|
||||
str="${str#?}"
|
||||
done
|
||||
echo "${basedir}"
|
||||
printf %x\\n $h
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
verbose() { :; }
|
||||
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
|
||||
|
||||
die() {
|
||||
printf %s\\n "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
trim() {
|
||||
# MWRAPPER-139:
|
||||
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
|
||||
# Needed for removing poorly interpreted newline sequences when running in more
|
||||
# exotic environments such as mingw bash on Windows.
|
||||
printf "%s" "${1}" | tr -d '[:space:]'
|
||||
}
|
||||
|
||||
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
|
||||
while IFS="=" read -r key value; do
|
||||
case "${key-}" in
|
||||
distributionUrl) distributionUrl=$(trim "${value-}") ;;
|
||||
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
|
||||
esac
|
||||
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
|
||||
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
|
||||
|
||||
case "${distributionUrl##*/}" in
|
||||
maven-mvnd-*bin.*)
|
||||
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
|
||||
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
|
||||
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
|
||||
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
|
||||
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
|
||||
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
|
||||
*)
|
||||
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
|
||||
distributionPlatform=linux-amd64
|
||||
;;
|
||||
esac
|
||||
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
|
||||
;;
|
||||
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
|
||||
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
|
||||
esac
|
||||
|
||||
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
|
||||
distributionUrlName="${distributionUrl##*/}"
|
||||
distributionUrlNameMain="${distributionUrlName%.*}"
|
||||
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
|
||||
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
|
||||
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
|
||||
|
||||
exec_maven() {
|
||||
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
|
||||
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
|
||||
}
|
||||
|
||||
if [ -d "$MAVEN_HOME" ]; then
|
||||
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||
exec_maven "$@"
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
case "${distributionUrl-}" in
|
||||
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
|
||||
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
|
||||
esac
|
||||
|
||||
# prepare tmp dir
|
||||
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
|
||||
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
|
||||
trap clean HUP INT TERM EXIT
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
die "cannot create temp dir"
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
mkdir -p -- "${MAVEN_HOME%/*}"
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
# Download and Install Apache Maven
|
||||
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||
verbose "Downloading from: $distributionUrl"
|
||||
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
# select .zip or .tar.gz
|
||||
if ! command -v unzip >/dev/null; then
|
||||
distributionUrl="${distributionUrl%.zip}.tar.gz"
|
||||
distributionUrlName="${distributionUrl##*/}"
|
||||
fi
|
||||
|
||||
# verbose opt
|
||||
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
|
||||
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
|
||||
|
||||
# normalize http auth
|
||||
case "${MVNW_PASSWORD:+has-password}" in
|
||||
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||
esac
|
||||
|
||||
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
|
||||
verbose "Found wget ... using wget"
|
||||
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
|
||||
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
|
||||
verbose "Found curl ... using curl"
|
||||
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
|
||||
elif set_java_home; then
|
||||
verbose "Falling back to use Java to download"
|
||||
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
|
||||
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
cat >"$javaSource" <<-END
|
||||
public class Downloader extends java.net.Authenticator
|
||||
{
|
||||
protected java.net.PasswordAuthentication getPasswordAuthentication()
|
||||
{
|
||||
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
|
||||
}
|
||||
public static void main( String[] args ) throws Exception
|
||||
{
|
||||
setDefault( new Downloader() );
|
||||
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
|
||||
}
|
||||
}
|
||||
END
|
||||
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
|
||||
verbose " - Compiling Downloader.java ..."
|
||||
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
|
||||
verbose " - Running Downloader.java ..."
|
||||
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
|
||||
fi
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||
if [ -n "${distributionSha256Sum-}" ]; then
|
||||
distributionSha256Result=false
|
||||
if [ "$MVN_CMD" = mvnd.sh ]; then
|
||||
echo "Checksum validation is not supported for maven-mvnd." >&2
|
||||
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
elif command -v sha256sum >/dev/null; then
|
||||
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
|
||||
distributionSha256Result=true
|
||||
fi
|
||||
elif command -v shasum >/dev/null; then
|
||||
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||
distributionSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
|
||||
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ $distributionSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# unzip and move
|
||||
if command -v unzip >/dev/null; then
|
||||
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
|
||||
else
|
||||
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
|
||||
fi
|
||||
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
|
||||
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
|
||||
|
||||
clean || :
|
||||
exec_maven "$@"
|
||||
|
261
mvnw.cmd
vendored
261
mvnw.cmd
vendored
@ -1,3 +1,4 @@
|
||||
<# : batch portion
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@ -18,165 +19,131 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM Apache Maven Wrapper startup batch script, version 3.3.2
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
||||
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
|
||||
@SET __MVNW_CMD__=
|
||||
@SET __MVNW_ERROR__=
|
||||
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
|
||||
@SET PSModulePath=
|
||||
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
|
||||
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
|
||||
)
|
||||
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
|
||||
@SET __MVNW_PSMODULEP_SAVE=
|
||||
@SET __MVNW_ARG0_NAME__=
|
||||
@SET MVNW_USERNAME=
|
||||
@SET MVNW_PASSWORD=
|
||||
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
|
||||
@echo Cannot start maven from wrapper >&2 && exit /b 1
|
||||
@GOTO :EOF
|
||||
: end batch / begin powershell #>
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($env:MVNW_VERBOSE -eq "true") {
|
||||
$VerbosePreference = "Continue"
|
||||
}
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
|
||||
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
|
||||
if (!$distributionUrl) {
|
||||
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||
}
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
|
||||
"maven-mvnd-*" {
|
||||
$USE_MVND = $true
|
||||
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
|
||||
$MVN_CMD = "mvnd.cmd"
|
||||
break
|
||||
}
|
||||
default {
|
||||
$USE_MVND = $false
|
||||
$MVN_CMD = $script -replace '^mvnw','mvn'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||
if ($env:MVNW_REPOURL) {
|
||||
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
|
||||
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
|
||||
}
|
||||
$distributionUrlName = $distributionUrl -replace '^.*/',''
|
||||
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
|
||||
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
|
||||
if ($env:MAVEN_USER_HOME) {
|
||||
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
|
||||
}
|
||||
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
|
||||
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
|
||||
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||
exit $?
|
||||
}
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
|
||||
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
|
||||
}
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
# prepare tmp dir
|
||||
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
|
||||
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
|
||||
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
|
||||
trap {
|
||||
if ($TMP_DOWNLOAD_DIR.Exists) {
|
||||
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||
}
|
||||
}
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
# Download and Install Apache Maven
|
||||
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||
Write-Verbose "Downloading from: $distributionUrl"
|
||||
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
$webclient = New-Object System.Net.WebClient
|
||||
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
|
||||
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
|
||||
}
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
|
||||
if ($distributionSha256Sum) {
|
||||
if ($USE_MVND) {
|
||||
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
|
||||
}
|
||||
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
|
||||
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
|
||||
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
|
||||
}
|
||||
}
|
||||
|
||||
# unzip and move
|
||||
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
|
||||
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
|
||||
try {
|
||||
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
|
||||
} catch {
|
||||
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
|
||||
Write-Error "fail to move MAVEN_HOME"
|
||||
}
|
||||
} finally {
|
||||
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||
}
|
||||
|
||||
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>MapStruct Parent</name>
|
||||
@ -28,13 +28,13 @@
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<!-- value comes from property git.commit.author.time -->
|
||||
<project.build.outputTimestamp>2024-05-11T07:01:58Z</project.build.outputTimestamp>
|
||||
<project.build.outputTimestamp>${git.commit.author.time}</project.build.outputTimestamp>
|
||||
|
||||
<org.mapstruct.gem.version>1.0.0.Alpha3</org.mapstruct.gem.version>
|
||||
<org.apache.maven.plugins.enforcer.version>3.4.1</org.apache.maven.plugins.enforcer.version>
|
||||
<org.apache.maven.plugins.surefire.version>3.2.2</org.apache.maven.plugins.surefire.version>
|
||||
<org.apache.maven.plugins.javadoc.version>3.1.0</org.apache.maven.plugins.javadoc.version>
|
||||
<org.springframework.version>5.3.31</org.springframework.version>
|
||||
<org.springframework.version>6.2.7</org.springframework.version>
|
||||
<org.eclipse.tycho.compiler-jdt.version>1.6.0</org.eclipse.tycho.compiler-jdt.version>
|
||||
<com.puppycrawl.tools.checkstyle.version>8.36.1</com.puppycrawl.tools.checkstyle.version>
|
||||
<org.junit.jupiter.version>5.10.1</org.junit.jupiter.version>
|
||||
@ -47,10 +47,10 @@
|
||||
<m2e.apt.activation>jdt_apt</m2e.apt.activation>
|
||||
<!--
|
||||
The minimum Java Version that is needed to build a module in MapStruct.
|
||||
The processor module needs at least Java 11.
|
||||
The processor module needs at least Java 21.
|
||||
-->
|
||||
<minimum.java.version>1.8</minimum.java.version>
|
||||
<protobuf.version>3.21.7</protobuf.version>
|
||||
<protobuf.version>3.25.5</protobuf.version>
|
||||
<jaxb-runtime.version>2.3.2</jaxb-runtime.version>
|
||||
</properties>
|
||||
|
||||
@ -400,7 +400,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<version>3.13.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
2
pom.xml
2
pom.xml
@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-parent</artifactId>
|
||||
<version>1.6.0.Beta2</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
<!-- Netbeans has a problem when we use late binding with @ in the surefire arg line.
|
||||
Therefore we set this empty property here-->
|
||||
<jacocoArgLine />
|
||||
<minimum.java.version>11</minimum.java.version>
|
||||
<minimum.java.version>21</minimum.java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -286,6 +286,7 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<testRelease>${minimum.java.version}</testRelease>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.mapstruct.tools.gem</groupId>
|
||||
|
@ -13,17 +13,16 @@ import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.Processor;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedOptions;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
@ -35,9 +34,8 @@ import javax.lang.model.util.ElementKindVisitor6;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.MapperGem;
|
||||
import org.mapstruct.ap.internal.gem.NullValueMappingStrategyGem;
|
||||
import org.mapstruct.ap.internal.gem.ReportingPolicyGem;
|
||||
import org.mapstruct.ap.internal.model.Mapper;
|
||||
import org.mapstruct.ap.internal.option.MappingOption;
|
||||
import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.processor.DefaultModelElementProcessorContext;
|
||||
import org.mapstruct.ap.internal.processor.ModelElementProcessor;
|
||||
@ -84,18 +82,6 @@ import static javax.lang.model.element.ElementKind.CLASS;
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
@SupportedAnnotationTypes("org.mapstruct.Mapper")
|
||||
@SupportedOptions({
|
||||
MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP,
|
||||
MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT,
|
||||
MappingProcessor.UNMAPPED_TARGET_POLICY,
|
||||
MappingProcessor.UNMAPPED_SOURCE_POLICY,
|
||||
MappingProcessor.DEFAULT_COMPONENT_MODEL,
|
||||
MappingProcessor.DEFAULT_INJECTION_STRATEGY,
|
||||
MappingProcessor.DISABLE_BUILDERS,
|
||||
MappingProcessor.VERBOSE,
|
||||
MappingProcessor.NULL_VALUE_ITERABLE_MAPPING_STRATEGY,
|
||||
MappingProcessor.NULL_VALUE_MAP_MAPPING_STRATEGY,
|
||||
})
|
||||
public class MappingProcessor extends AbstractProcessor {
|
||||
|
||||
/**
|
||||
@ -103,18 +89,32 @@ public class MappingProcessor extends AbstractProcessor {
|
||||
*/
|
||||
private static final boolean ANNOTATIONS_CLAIMED_EXCLUSIVELY = false;
|
||||
|
||||
protected static final String SUPPRESS_GENERATOR_TIMESTAMP = "mapstruct.suppressGeneratorTimestamp";
|
||||
protected static final String SUPPRESS_GENERATOR_VERSION_INFO_COMMENT =
|
||||
"mapstruct.suppressGeneratorVersionInfoComment";
|
||||
protected static final String UNMAPPED_TARGET_POLICY = "mapstruct.unmappedTargetPolicy";
|
||||
protected static final String UNMAPPED_SOURCE_POLICY = "mapstruct.unmappedSourcePolicy";
|
||||
protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel";
|
||||
protected static final String DEFAULT_INJECTION_STRATEGY = "mapstruct.defaultInjectionStrategy";
|
||||
protected static final String ALWAYS_GENERATE_SERVICE_FILE = "mapstruct.alwaysGenerateServicesFile";
|
||||
protected static final String DISABLE_BUILDERS = "mapstruct.disableBuilders";
|
||||
protected static final String VERBOSE = "mapstruct.verbose";
|
||||
protected static final String NULL_VALUE_ITERABLE_MAPPING_STRATEGY = "mapstruct.nullValueIterableMappingStrategy";
|
||||
protected static final String NULL_VALUE_MAP_MAPPING_STRATEGY = "mapstruct.nullValueMapMappingStrategy";
|
||||
// CHECKSTYLE:OFF
|
||||
// Deprecated options, kept for backwards compatibility.
|
||||
// They will be removed in a future release.
|
||||
@Deprecated
|
||||
protected static final String SUPPRESS_GENERATOR_TIMESTAMP = MappingOption.SUPPRESS_GENERATOR_TIMESTAMP.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String SUPPRESS_GENERATOR_VERSION_INFO_COMMENT = MappingOption.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String UNMAPPED_TARGET_POLICY = MappingOption.UNMAPPED_TARGET_POLICY.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String UNMAPPED_SOURCE_POLICY = MappingOption.UNMAPPED_SOURCE_POLICY.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String DEFAULT_COMPONENT_MODEL = MappingOption.DEFAULT_COMPONENT_MODEL.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String DEFAULT_INJECTION_STRATEGY = MappingOption.DEFAULT_INJECTION_STRATEGY.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String ALWAYS_GENERATE_SERVICE_FILE = MappingOption.ALWAYS_GENERATE_SERVICE_FILE.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String DISABLE_BUILDERS = MappingOption.DISABLE_BUILDERS.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String VERBOSE = MappingOption.VERBOSE.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String NULL_VALUE_ITERABLE_MAPPING_STRATEGY = MappingOption.NULL_VALUE_ITERABLE_MAPPING_STRATEGY.getOptionName();
|
||||
@Deprecated
|
||||
protected static final String NULL_VALUE_MAP_MAPPING_STRATEGY = MappingOption.NULL_VALUE_MAP_MAPPING_STRATEGY.getOptionName();
|
||||
// CHECKSTYLE:ON
|
||||
|
||||
private final Set<String> additionalSupportedOptions;
|
||||
private final String additionalSupportedOptionsError;
|
||||
@ -153,7 +153,7 @@ public class MappingProcessor extends AbstractProcessor {
|
||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||
super.init( processingEnv );
|
||||
|
||||
options = createOptions();
|
||||
options = new Options( processingEnv.getOptions() );
|
||||
annotationProcessorContext = new AnnotationProcessorContext(
|
||||
processingEnv.getElementUtils(),
|
||||
processingEnv.getTypeUtils(),
|
||||
@ -168,31 +168,6 @@ public class MappingProcessor extends AbstractProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private Options createOptions() {
|
||||
String unmappedTargetPolicy = processingEnv.getOptions().get( UNMAPPED_TARGET_POLICY );
|
||||
String unmappedSourcePolicy = processingEnv.getOptions().get( UNMAPPED_SOURCE_POLICY );
|
||||
String nullValueIterableMappingStrategy = processingEnv.getOptions()
|
||||
.get( NULL_VALUE_ITERABLE_MAPPING_STRATEGY );
|
||||
String nullValueMapMappingStrategy = processingEnv.getOptions().get( NULL_VALUE_MAP_MAPPING_STRATEGY );
|
||||
|
||||
return new Options(
|
||||
Boolean.parseBoolean( processingEnv.getOptions().get( SUPPRESS_GENERATOR_TIMESTAMP ) ),
|
||||
Boolean.parseBoolean( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ),
|
||||
unmappedTargetPolicy != null ? ReportingPolicyGem.valueOf( unmappedTargetPolicy.toUpperCase() ) : null,
|
||||
unmappedSourcePolicy != null ? ReportingPolicyGem.valueOf( unmappedSourcePolicy.toUpperCase() ) : null,
|
||||
processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ),
|
||||
processingEnv.getOptions().get( DEFAULT_INJECTION_STRATEGY ),
|
||||
Boolean.parseBoolean( processingEnv.getOptions().get( ALWAYS_GENERATE_SERVICE_FILE ) ),
|
||||
Boolean.parseBoolean( processingEnv.getOptions().get( DISABLE_BUILDERS ) ),
|
||||
Boolean.parseBoolean( processingEnv.getOptions().get( VERBOSE ) ),
|
||||
nullValueIterableMappingStrategy != null ?
|
||||
NullValueMappingStrategyGem.valueOf( nullValueIterableMappingStrategy.toUpperCase( Locale.ROOT ) ) :
|
||||
null,
|
||||
nullValueMapMappingStrategy != null ?
|
||||
NullValueMappingStrategyGem.valueOf( nullValueMapMappingStrategy.toUpperCase( Locale.ROOT ) ) : null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceVersion getSupportedSourceVersion() {
|
||||
return SourceVersion.latestSupported();
|
||||
@ -253,13 +228,11 @@ public class MappingProcessor extends AbstractProcessor {
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedOptions() {
|
||||
Set<String> supportedOptions = super.getSupportedOptions();
|
||||
if ( additionalSupportedOptions.isEmpty() ) {
|
||||
return supportedOptions;
|
||||
}
|
||||
Set<String> allSupportedOptions = new HashSet<>( supportedOptions );
|
||||
allSupportedOptions.addAll( additionalSupportedOptions );
|
||||
return allSupportedOptions;
|
||||
return Stream.concat(
|
||||
Stream.of( MappingOption.values() ).map( MappingOption::getOptionName ),
|
||||
additionalSupportedOptions.stream()
|
||||
)
|
||||
.collect( Collectors.toSet() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,8 +14,9 @@ import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.bigDecimal;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.locale;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* Conversion between {@link BigDecimal} and {@link String}.
|
||||
@ -64,18 +65,31 @@ public class BigDecimalToStringConversion extends AbstractNumberToStringConversi
|
||||
public List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext) {
|
||||
List<HelperMethod> helpers = new ArrayList<>();
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
helpers.add( new CreateDecimalFormat( conversionContext.getTypeFactory() ) );
|
||||
helpers.add( new CreateDecimalFormat(
|
||||
conversionContext.getTypeFactory(),
|
||||
conversionContext.getLocale() != null
|
||||
) );
|
||||
}
|
||||
return helpers;
|
||||
}
|
||||
|
||||
private void appendDecimalFormatter(StringBuilder sb, ConversionContext conversionContext) {
|
||||
sb.append( "createDecimalFormat( " );
|
||||
boolean withLocale = conversionContext.getLocale() != null;
|
||||
sb.append( "createDecimalFormat" );
|
||||
if ( withLocale ) {
|
||||
sb.append( "WithLocale" );
|
||||
}
|
||||
sb.append( "( " );
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
}
|
||||
if ( withLocale ) {
|
||||
sb.append( ", " ).append( locale( conversionContext ) ).append( ".forLanguageTag( \"" );
|
||||
sb.append( conversionContext.getLocale() );
|
||||
sb.append( "\" )" );
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
}
|
||||
|
@ -15,9 +15,10 @@ import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.locale;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.bigDecimal;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.bigInteger;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* Conversion between {@link BigInteger} and {@link String}.
|
||||
@ -72,18 +73,31 @@ public class BigIntegerToStringConversion extends AbstractNumberToStringConversi
|
||||
public List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext) {
|
||||
List<HelperMethod> helpers = new ArrayList<>();
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
helpers.add( new CreateDecimalFormat( conversionContext.getTypeFactory() ) );
|
||||
helpers.add( new CreateDecimalFormat(
|
||||
conversionContext.getTypeFactory(),
|
||||
conversionContext.getLocale() != null
|
||||
) );
|
||||
}
|
||||
return helpers;
|
||||
}
|
||||
|
||||
private void appendDecimalFormatter(StringBuilder sb, ConversionContext conversionContext) {
|
||||
sb.append( "createDecimalFormat( " );
|
||||
boolean withLocale = conversionContext.getLocale() != null;
|
||||
sb.append( "createDecimalFormat" );
|
||||
if ( withLocale ) {
|
||||
sb.append( "WithLocale" );
|
||||
}
|
||||
sb.append( "( " );
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
}
|
||||
if ( withLocale ) {
|
||||
sb.append( ", " ).append( locale( conversionContext ) ).append( ".forLanguageTag( \"" );
|
||||
sb.append( conversionContext.getLocale() );
|
||||
sb.append( "\" )" );
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import java.net.URL;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@ -279,4 +280,15 @@ public final class ConversionUtils {
|
||||
return typeReferenceName( conversionContext, URL.class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Name for {@link java.text.DecimalFormatSymbols}.
|
||||
*
|
||||
* @param conversionContext Conversion context
|
||||
*
|
||||
* @return Name or fully-qualified name.
|
||||
*/
|
||||
public static String decimalFormatSymbols(ConversionContext conversionContext) {
|
||||
return typeReferenceName( conversionContext, DecimalFormatSymbols.class );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -268,10 +268,10 @@ public class Conversions {
|
||||
if ( sourceType.isPrimitive() && targetType.isPrimitive() ) {
|
||||
register( sourceType, targetType, new PrimitiveToPrimitiveConversion( sourceType ) );
|
||||
}
|
||||
else if ( sourceType.isPrimitive() && !targetType.isPrimitive() ) {
|
||||
else if ( sourceType.isPrimitive() ) {
|
||||
register( sourceType, targetType, new PrimitiveToWrapperConversion( sourceType, targetType ) );
|
||||
}
|
||||
else if ( !sourceType.isPrimitive() && targetType.isPrimitive() ) {
|
||||
else if ( targetType.isPrimitive() ) {
|
||||
register( sourceType, targetType, inverse( new PrimitiveToWrapperConversion( targetType, sourceType ) ) );
|
||||
}
|
||||
else {
|
||||
@ -390,11 +390,7 @@ public class Conversions {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !Objects.equals( targetType, other.targetType ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Objects.equals( targetType, other.targetType );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,11 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
@ -16,6 +18,8 @@ import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.MappingMethodOptions;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* HelperMethod that creates a {@link java.text.DecimalFormat}
|
||||
*
|
||||
@ -27,13 +31,30 @@ import org.mapstruct.ap.internal.model.source.MappingMethodOptions;
|
||||
public class CreateDecimalFormat extends HelperMethod {
|
||||
|
||||
private final Parameter parameter;
|
||||
private final Parameter localeParameter;
|
||||
private final Type returnType;
|
||||
private final Set<Type> importTypes;
|
||||
|
||||
public CreateDecimalFormat(TypeFactory typeFactory) {
|
||||
public CreateDecimalFormat(TypeFactory typeFactory, boolean withLocale) {
|
||||
this.parameter = new Parameter( "numberFormat", typeFactory.getType( String.class ) );
|
||||
this.localeParameter = withLocale ? new Parameter( "locale", typeFactory.getType( Locale.class ) ) : null;
|
||||
this.returnType = typeFactory.getType( DecimalFormat.class );
|
||||
this.importTypes = asSet( parameter.getType(), returnType );
|
||||
if ( withLocale ) {
|
||||
this.importTypes = asSet(
|
||||
parameter.getType(),
|
||||
returnType,
|
||||
typeFactory.getType( DecimalFormatSymbols.class ),
|
||||
typeFactory.getType( Locale.class )
|
||||
);
|
||||
}
|
||||
else {
|
||||
this.importTypes = asSet( parameter.getType(), returnType );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return localeParameter == null ? "createDecimalFormat" : "createDecimalFormatWithLocale";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,4 +81,12 @@ public class CreateDecimalFormat extends HelperMethod {
|
||||
public String describe() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Parameter> getParameters() {
|
||||
if ( localeParameter == null ) {
|
||||
return super.getParameters();
|
||||
}
|
||||
return Arrays.asList( getParameter(), localeParameter );
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,18 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
import org.mapstruct.ap.internal.model.TypeConversion;
|
||||
import org.mapstruct.ap.internal.model.common.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.locale;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.simpleDateFormat;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* Conversion between {@link String} and {@link Date}.
|
||||
@ -29,7 +32,7 @@ public class DateToStringConversion implements ConversionProvider {
|
||||
|
||||
@Override
|
||||
public Assignment to(ConversionContext conversionContext) {
|
||||
return new TypeConversion( asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
||||
return new TypeConversion( getImportTypes( conversionContext ),
|
||||
Collections.emptyList(),
|
||||
getConversionExpression( conversionContext, "format" )
|
||||
);
|
||||
@ -37,8 +40,8 @@ public class DateToStringConversion implements ConversionProvider {
|
||||
|
||||
@Override
|
||||
public Assignment from(ConversionContext conversionContext) {
|
||||
return new TypeConversion( asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
||||
asList( conversionContext.getTypeFactory().getType( ParseException.class ) ),
|
||||
return new TypeConversion( getImportTypes( conversionContext ),
|
||||
Collections.singletonList( conversionContext.getTypeFactory().getType( ParseException.class ) ),
|
||||
getConversionExpression( conversionContext, "parse" )
|
||||
);
|
||||
}
|
||||
@ -48,6 +51,17 @@ public class DateToStringConversion implements ConversionProvider {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Set<Type> getImportTypes(ConversionContext conversionContext) {
|
||||
if ( conversionContext.getLocale() == null ) {
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) );
|
||||
}
|
||||
|
||||
return asSet(
|
||||
conversionContext.getTypeFactory().getType( SimpleDateFormat.class ),
|
||||
conversionContext.getTypeFactory().getType( Locale.class )
|
||||
);
|
||||
}
|
||||
|
||||
private String getConversionExpression(ConversionContext conversionContext, String method) {
|
||||
StringBuilder conversionString = new StringBuilder( "new " );
|
||||
conversionString.append( simpleDateFormat( conversionContext ) );
|
||||
@ -56,7 +70,16 @@ public class DateToStringConversion implements ConversionProvider {
|
||||
if ( conversionContext.getDateFormat() != null ) {
|
||||
conversionString.append( " \"" );
|
||||
conversionString.append( conversionContext.getDateFormat() );
|
||||
conversionString.append( "\" " );
|
||||
conversionString.append( "\"" );
|
||||
|
||||
if ( conversionContext.getLocale() != null ) {
|
||||
conversionString.append( ", " ).append( locale( conversionContext ) ).append( ".forLanguageTag( \"" );
|
||||
conversionString.append( conversionContext.getLocale() );
|
||||
conversionString.append( "\" ) " );
|
||||
}
|
||||
else {
|
||||
conversionString.append( " " );
|
||||
}
|
||||
}
|
||||
|
||||
conversionString.append( ")." );
|
||||
|
@ -7,11 +7,8 @@ package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.util.Collections;
|
||||
|
||||
/**
|
||||
* SimpleConversion for mapping {@link LocalDateTime} to
|
||||
@ -25,22 +22,9 @@ public class JavaLocalDateTimeToLocalDateConversion extends SimpleConversion {
|
||||
return "<SOURCE>.toLocalDate()";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Type> getToConversionImportTypes(ConversionContext conversionContext) {
|
||||
return Collections.asSet(
|
||||
conversionContext.getTypeFactory().getType( LocalDate.class )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromExpression(ConversionContext conversionContext) {
|
||||
return "<SOURCE>.atStartOfDay()";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
|
||||
return Collections.asSet(
|
||||
conversionContext.getTypeFactory().getType( LocalDateTime.class )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,9 @@
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
@ -15,6 +17,9 @@ import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.decimalFormat;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.decimalFormatSymbols;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.locale;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* Conversion between primitive types such as {@code byte} or {@code long} and
|
||||
@ -53,9 +58,15 @@ public class PrimitiveToStringConversion extends AbstractNumberToStringConversio
|
||||
@Override
|
||||
public Set<Type> getToConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
return Collections.singleton(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class )
|
||||
);
|
||||
if ( conversionContext.getLocale() != null ) {
|
||||
return asSet(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class ),
|
||||
conversionContext.getTypeFactory().getType( DecimalFormatSymbols.class ),
|
||||
conversionContext.getTypeFactory().getType( Locale.class )
|
||||
);
|
||||
}
|
||||
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
@ -80,9 +91,15 @@ public class PrimitiveToStringConversion extends AbstractNumberToStringConversio
|
||||
@Override
|
||||
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
return Collections.singleton(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class )
|
||||
);
|
||||
if ( conversionContext.getLocale() != null ) {
|
||||
return asSet(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class ),
|
||||
conversionContext.getTypeFactory().getType( DecimalFormatSymbols.class ),
|
||||
conversionContext.getTypeFactory().getType( Locale.class )
|
||||
);
|
||||
}
|
||||
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
@ -97,6 +114,16 @@ public class PrimitiveToStringConversion extends AbstractNumberToStringConversio
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
|
||||
if ( conversionContext.getLocale() != null ) {
|
||||
sb.append( ", " )
|
||||
.append( decimalFormatSymbols( conversionContext ) )
|
||||
.append( ".getInstance( " )
|
||||
.append( locale( conversionContext ) )
|
||||
.append( ".forLanguageTag( \"" )
|
||||
.append( conversionContext.getLocale() )
|
||||
.append( " \" ) )" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
|
@ -6,7 +6,9 @@
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
@ -15,6 +17,9 @@ import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.decimalFormat;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.decimalFormatSymbols;
|
||||
import static org.mapstruct.ap.internal.conversion.ConversionUtils.locale;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* Conversion between wrapper types such as {@link Integer} and {@link String}.
|
||||
@ -52,9 +57,15 @@ public class WrapperToStringConversion extends AbstractNumberToStringConversion
|
||||
@Override
|
||||
public Set<Type> getToConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
return Collections.singleton(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class )
|
||||
);
|
||||
if ( conversionContext.getLocale() != null ) {
|
||||
return asSet(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class ),
|
||||
conversionContext.getTypeFactory().getType( DecimalFormatSymbols.class ),
|
||||
conversionContext.getTypeFactory().getType( Locale.class )
|
||||
);
|
||||
}
|
||||
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
@ -79,9 +90,15 @@ public class WrapperToStringConversion extends AbstractNumberToStringConversion
|
||||
@Override
|
||||
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
return Collections.singleton(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class )
|
||||
);
|
||||
if ( conversionContext.getLocale() != null ) {
|
||||
return asSet(
|
||||
conversionContext.getTypeFactory().getType( DecimalFormat.class ),
|
||||
conversionContext.getTypeFactory().getType( DecimalFormatSymbols.class ),
|
||||
conversionContext.getTypeFactory().getType( Locale.class )
|
||||
);
|
||||
}
|
||||
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
@ -96,6 +113,16 @@ public class WrapperToStringConversion extends AbstractNumberToStringConversion
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
|
||||
if ( conversionContext.getLocale() != null ) {
|
||||
sb.append( ", " )
|
||||
.append( decimalFormatSymbols( conversionContext ) )
|
||||
.append( ".getInstance( " )
|
||||
.append( locale( conversionContext ) )
|
||||
.append( ".forLanguageTag( \"" )
|
||||
.append( conversionContext.getLocale() )
|
||||
.append( " \" ) )" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
|
@ -26,6 +26,8 @@ import org.mapstruct.MapMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MapperConfig;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Ignored;
|
||||
import org.mapstruct.IgnoredList;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.Named;
|
||||
@ -53,6 +55,8 @@ import org.mapstruct.tools.gem.GemDefinition;
|
||||
@GemDefinition(AnnotateWiths.class)
|
||||
@GemDefinition(Mapper.class)
|
||||
@GemDefinition(Mapping.class)
|
||||
@GemDefinition(Ignored.class)
|
||||
@GemDefinition(IgnoredList.class)
|
||||
@GemDefinition(Mappings.class)
|
||||
@GemDefinition(IterableMapping.class)
|
||||
@GemDefinition(BeanMapping.class)
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Assignment;
|
||||
@ -40,7 +41,7 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if MapStruct is allowed to generate an automatic sub-mapping between {@code sourceType} and @{code
|
||||
* Checks if MapStruct is allowed to generate an automatic sub-mapping between {@code sourceType} and {@code
|
||||
* targetType}.
|
||||
* This will evaluate to {@code true}, when:
|
||||
* <li>
|
||||
@ -65,7 +66,7 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
|
||||
|
||||
/**
|
||||
* Creates a forged assignment from the provided {@code sourceRHS} and {@code forgedMethod}. If a mapping method
|
||||
* for the {@code forgedMethod} already exists, then this method used for the assignment.
|
||||
* for the {@code forgedMethod} already exists, this method will be used for the assignment.
|
||||
*
|
||||
* @param sourceRHS that needs to be used for the assignment
|
||||
* @param forgedMethod the forged method for which we want to create an {@link Assignment}
|
||||
@ -74,16 +75,9 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
|
||||
*/
|
||||
Assignment createForgedAssignment(SourceRHS sourceRHS, BuilderType builderType, ForgedMethod forgedMethod) {
|
||||
|
||||
if ( ctx.getForgedMethodsUnderCreation().containsKey( forgedMethod ) ) {
|
||||
return createAssignment( sourceRHS, ctx.getForgedMethodsUnderCreation().get( forgedMethod ) );
|
||||
}
|
||||
else {
|
||||
ctx.getForgedMethodsUnderCreation().put( forgedMethod, forgedMethod );
|
||||
}
|
||||
|
||||
MappingMethod forgedMappingMethod;
|
||||
Supplier<MappingMethod> forgedMappingMethodCreator;
|
||||
if ( MappingMethodUtils.isEnumMapping( forgedMethod ) ) {
|
||||
forgedMappingMethod = new ValueMappingMethod.Builder()
|
||||
forgedMappingMethodCreator = () -> new ValueMappingMethod.Builder()
|
||||
.method( forgedMethod )
|
||||
.valueMappings( forgedMethod.getOptions().getValueMappings() )
|
||||
.enumMapping( forgedMethod.getOptions().getEnumMappingOptions() )
|
||||
@ -91,15 +85,31 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
|
||||
.build();
|
||||
}
|
||||
else {
|
||||
forgedMappingMethod = new BeanMappingMethod.Builder()
|
||||
forgedMappingMethodCreator = () -> new BeanMappingMethod.Builder()
|
||||
.forgedMethod( forgedMethod )
|
||||
.returnTypeBuilder( builderType )
|
||||
.mappingContext( ctx )
|
||||
.build();
|
||||
}
|
||||
|
||||
return getOrCreateForgedAssignment( sourceRHS, forgedMethod, forgedMappingMethodCreator );
|
||||
}
|
||||
|
||||
Assignment getOrCreateForgedAssignment(SourceRHS sourceRHS, ForgedMethod forgedMethod,
|
||||
Supplier<MappingMethod> mappingMethodCreator) {
|
||||
|
||||
if ( ctx.getForgedMethodsUnderCreation().containsKey( forgedMethod ) ) {
|
||||
return createAssignment( sourceRHS, ctx.getForgedMethodsUnderCreation().get( forgedMethod ) );
|
||||
}
|
||||
else {
|
||||
ctx.getForgedMethodsUnderCreation().put( forgedMethod, forgedMethod );
|
||||
}
|
||||
|
||||
MappingMethod forgedMappingMethod = mappingMethodCreator.get();
|
||||
|
||||
Assignment forgedAssignment = createForgedAssignment( sourceRHS, forgedMethod, forgedMappingMethod );
|
||||
ctx.getForgedMethodsUnderCreation().remove( forgedMethod );
|
||||
|
||||
return forgedAssignment;
|
||||
}
|
||||
|
||||
|
@ -36,14 +36,14 @@ public class AnnotatedConstructor extends ModelElement implements Constructor {
|
||||
if ( constructor instanceof NoArgumentConstructor ) {
|
||||
noArgumentConstructor = (NoArgumentConstructor) constructor;
|
||||
}
|
||||
NoArgumentConstructor noArgConstructorToInBecluded = null;
|
||||
NoArgumentConstructor noArgConstructorToBeIncluded = null;
|
||||
Set<SupportingConstructorFragment> fragmentsToBeIncluded = Collections.emptySet();
|
||||
if ( includeNoArgConstructor ) {
|
||||
if ( noArgumentConstructor != null ) {
|
||||
noArgConstructorToInBecluded = noArgumentConstructor;
|
||||
noArgConstructorToBeIncluded = noArgumentConstructor;
|
||||
}
|
||||
else {
|
||||
noArgConstructorToInBecluded = new NoArgumentConstructor( name, fragmentsToBeIncluded );
|
||||
noArgConstructorToBeIncluded = new NoArgumentConstructor( name, fragmentsToBeIncluded );
|
||||
}
|
||||
}
|
||||
else if ( noArgumentConstructor != null ) {
|
||||
@ -53,7 +53,7 @@ public class AnnotatedConstructor extends ModelElement implements Constructor {
|
||||
name,
|
||||
mapperReferences,
|
||||
annotations,
|
||||
noArgConstructorToInBecluded,
|
||||
noArgConstructorToBeIncluded,
|
||||
fragmentsToBeIncluded
|
||||
);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.AccessorType;
|
||||
import org.mapstruct.ap.internal.util.accessor.ParameterElementAccessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.ElementAccessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;
|
||||
|
||||
@ -100,6 +100,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
private final String finalizedResultName;
|
||||
private final List<LifecycleCallbackMethodReference> beforeMappingReferencesWithFinalizedReturnType;
|
||||
private final List<LifecycleCallbackMethodReference> afterMappingReferencesWithFinalizedReturnType;
|
||||
private final Type subclassExhaustiveException;
|
||||
|
||||
private final MappingReferences mappingReferences;
|
||||
|
||||
@ -152,7 +153,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
method( forgedMethod );
|
||||
mappingReferences = forgedMethod.getMappingReferences();
|
||||
Parameter sourceParameter = first( Parameter.getSourceParameters( forgedMethod.getParameters() ) );
|
||||
for ( MappingReference mappingReference: mappingReferences.getMappingReferences() ) {
|
||||
for ( MappingReference mappingReference : mappingReferences.getMappingReferences() ) {
|
||||
SourceReference sourceReference = mappingReference.getSourceReference();
|
||||
if ( sourceReference != null ) {
|
||||
mappingReference.setSourceReference( new SourceReference.BuilderFromSourceReference()
|
||||
@ -235,9 +236,10 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
|
||||
this.unprocessedTargetProperties = new LinkedHashMap<>( accessors );
|
||||
|
||||
boolean constructorAccessorHadError = false;
|
||||
if ( !method.isUpdateMethod() && !hasFactoryMethod ) {
|
||||
ConstructorAccessor constructorAccessor = getConstructorAccessor( resultTypeToMap );
|
||||
if ( constructorAccessor != null ) {
|
||||
if ( constructorAccessor != null && !constructorAccessor.hasError ) {
|
||||
|
||||
this.unprocessedConstructorProperties = constructorAccessor.constructorAccessors;
|
||||
|
||||
@ -250,8 +252,10 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
else {
|
||||
this.unprocessedConstructorProperties = new LinkedHashMap<>();
|
||||
}
|
||||
constructorAccessorHadError = constructorAccessor != null && constructorAccessor.hasError;
|
||||
|
||||
this.targetProperties.addAll( this.unprocessedConstructorProperties.keySet() );
|
||||
|
||||
this.unprocessedTargetProperties.putAll( this.unprocessedConstructorProperties );
|
||||
}
|
||||
else {
|
||||
@ -295,9 +299,11 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
}
|
||||
}
|
||||
|
||||
boolean applyImplicitMappings = !mappingReferences.isRestrictToDefinedMappings();
|
||||
// If defined mappings should not be handled then we should not apply implicit mappings
|
||||
boolean applyImplicitMappings =
|
||||
shouldHandledDefinedMappings && !mappingReferences.isRestrictToDefinedMappings();
|
||||
if ( applyImplicitMappings ) {
|
||||
applyImplicitMappings = beanMapping == null || !beanMapping.isignoreByDefault();
|
||||
applyImplicitMappings = beanMapping == null || !beanMapping.isIgnoredByDefault();
|
||||
}
|
||||
if ( applyImplicitMappings ) {
|
||||
|
||||
@ -320,7 +326,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
|
||||
// report errors on unmapped properties
|
||||
if ( shouldHandledDefinedMappings ) {
|
||||
reportErrorForUnmappedTargetPropertiesIfRequired();
|
||||
reportErrorForUnmappedTargetPropertiesIfRequired( resultTypeToMap, constructorAccessorHadError );
|
||||
reportErrorForUnmappedSourcePropertiesIfRequired();
|
||||
}
|
||||
reportErrorForMissingIgnoredSourceProperties();
|
||||
@ -373,6 +379,11 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
|
||||
}
|
||||
|
||||
TypeMirror subclassExhaustiveException = method.getOptions()
|
||||
.getBeanMapping()
|
||||
.getSubclassExhaustiveException();
|
||||
Type subclassExhaustiveExceptionType = ctx.getTypeFactory().getType( subclassExhaustiveException );
|
||||
|
||||
List<SubclassMapping> subclasses = new ArrayList<>();
|
||||
for ( SubclassMappingOptions subclassMappingOptions : method.getOptions().getSubclassMappings() ) {
|
||||
subclasses.add( createSubclassMapping( subclassMappingOptions ) );
|
||||
@ -406,9 +417,8 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
existingVariableNames
|
||||
) );
|
||||
|
||||
// remove methods without parameters as they are already being invoked
|
||||
removeMappingReferencesWithoutSourceParameters( beforeMappingReferencesWithFinalizedReturnType );
|
||||
removeMappingReferencesWithoutSourceParameters( afterMappingReferencesWithFinalizedReturnType );
|
||||
keepMappingReferencesUsingTarget( beforeMappingReferencesWithFinalizedReturnType, actualReturnType );
|
||||
keepMappingReferencesUsingTarget( afterMappingReferencesWithFinalizedReturnType, actualReturnType );
|
||||
}
|
||||
|
||||
Map<String, PresenceCheck> presenceChecksByParameter = new LinkedHashMap<>();
|
||||
@ -447,12 +457,37 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
finalizeMethod,
|
||||
mappingReferences,
|
||||
subclasses,
|
||||
presenceChecksByParameter
|
||||
presenceChecksByParameter,
|
||||
subclassExhaustiveExceptionType
|
||||
);
|
||||
}
|
||||
|
||||
private void removeMappingReferencesWithoutSourceParameters(List<LifecycleCallbackMethodReference> references) {
|
||||
references.removeIf( r -> r.getSourceParameters().isEmpty() && r.getReturnType().isVoid() );
|
||||
private void keepMappingReferencesUsingTarget(List<LifecycleCallbackMethodReference> references, Type type) {
|
||||
references.removeIf( reference -> {
|
||||
List<ParameterBinding> bindings = reference.getParameterBindings();
|
||||
if ( bindings.isEmpty() ) {
|
||||
return true;
|
||||
}
|
||||
for ( ParameterBinding binding : bindings ) {
|
||||
if ( binding.isMappingTarget() ) {
|
||||
if ( type.isAssignableTo( binding.getType() ) ) {
|
||||
// If the mapping target matches the type then we need to keep this
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( binding.isTargetType() ) {
|
||||
Type targetType = binding.getType();
|
||||
List<Type> targetTypeTypeParameters = targetType.getTypeParameters();
|
||||
if ( targetTypeTypeParameters.size() == 1 ) {
|
||||
if ( type.isAssignableTo( targetTypeTypeParameters.get( 0 ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} );
|
||||
}
|
||||
|
||||
private boolean doesNotAllowAbstractReturnTypeAndCanBeConstructed(Type returnTypeImpl) {
|
||||
@ -939,7 +974,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
)
|
||||
.collect( Collectors.joining( ", " ) )
|
||||
);
|
||||
return null;
|
||||
return new ConstructorAccessor( true, Collections.emptyList(), Collections.emptyMap() );
|
||||
}
|
||||
else {
|
||||
return getConstructorAccessor( type, accessibleConstructors.get( 0 ) );
|
||||
@ -998,7 +1033,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
GENERAL_CONSTRUCTOR_PROPERTIES_NOT_MATCHING_PARAMETERS,
|
||||
type
|
||||
);
|
||||
return null;
|
||||
return new ConstructorAccessor( true, Collections.emptyList(), Collections.emptyMap() );
|
||||
}
|
||||
else {
|
||||
Map<String, Accessor> constructorAccessors = new LinkedHashMap<>();
|
||||
@ -1032,7 +1067,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
existingVariableNames
|
||||
);
|
||||
existingVariableNames.add( safeParameterName );
|
||||
return new ParameterElementAccessor( element, accessedType, safeParameterName );
|
||||
return new ElementAccessor( element, accessedType, safeParameterName );
|
||||
}
|
||||
|
||||
private boolean hasDefaultAnnotationFromAnyPackage(Element element) {
|
||||
@ -1339,7 +1374,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
handledTargets.add( targetPropertyName );
|
||||
}
|
||||
|
||||
// its a constant
|
||||
// it's a constant
|
||||
// if we have an unprocessed target that means that it most probably is nested and we should
|
||||
// not generated any mapping for it now. Eventually it will be done though
|
||||
else if ( mapping.getConstant() != null ) {
|
||||
@ -1359,7 +1394,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
handledTargets.add( targetPropertyName );
|
||||
}
|
||||
|
||||
// its an expression
|
||||
// it's an expression
|
||||
// if we have an unprocessed target that means that it most probably is nested and we should
|
||||
// not generated any mapping for it now. Eventually it will be done though
|
||||
else if ( mapping.getJavaExpression() != null ) {
|
||||
@ -1375,7 +1410,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
.build();
|
||||
handledTargets.add( targetPropertyName );
|
||||
}
|
||||
// its a plain-old property mapping
|
||||
// it's a plain-old property mapping
|
||||
else {
|
||||
|
||||
SourceReference sourceRef = mappingRef.getSourceReference();
|
||||
@ -1697,7 +1732,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
return ReportingPolicyGem.IGNORE;
|
||||
}
|
||||
// If we have ignoreByDefault = true, unprocessed target properties are not an issue.
|
||||
if ( method.getOptions().getBeanMapping().isignoreByDefault() ) {
|
||||
if ( method.getOptions().getBeanMapping().isIgnoredByDefault() ) {
|
||||
return ReportingPolicyGem.IGNORE;
|
||||
}
|
||||
if ( method.getOptions().getBeanMapping() != null ) {
|
||||
@ -1706,36 +1741,45 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
return method.getOptions().getMapper().unmappedTargetPolicy();
|
||||
}
|
||||
|
||||
private void reportErrorForUnmappedTargetPropertiesIfRequired() {
|
||||
private void reportErrorForUnmappedTargetPropertiesIfRequired(Type resultType,
|
||||
boolean constructorAccessorHadError) {
|
||||
|
||||
// fetch settings from element to implement
|
||||
ReportingPolicyGem unmappedTargetPolicy = getUnmappedTargetPolicy();
|
||||
|
||||
if ( method instanceof ForgedMethod && targetProperties.isEmpty() ) {
|
||||
//TODO until we solve 1140 we report this error when the target properties are empty
|
||||
ForgedMethod forgedMethod = (ForgedMethod) method;
|
||||
if ( forgedMethod.getHistory() == null ) {
|
||||
Type sourceType = this.method.getParameters().get( 0 ).getType();
|
||||
Type targetType = this.method.getReturnType();
|
||||
ctx.getMessager().printMessage(
|
||||
this.method.getExecutable(),
|
||||
Message.PROPERTYMAPPING_FORGED_MAPPING_NOT_FOUND,
|
||||
sourceType.describe(),
|
||||
targetType.describe(),
|
||||
targetType.describe(),
|
||||
sourceType.describe()
|
||||
);
|
||||
if ( targetProperties.isEmpty() ) {
|
||||
if ( method instanceof ForgedMethod ) {
|
||||
ForgedMethod forgedMethod = (ForgedMethod) method;
|
||||
if ( forgedMethod.getHistory() == null ) {
|
||||
Type sourceType = this.method.getParameters().get( 0 ).getType();
|
||||
Type targetType = this.method.getReturnType();
|
||||
ctx.getMessager().printMessage(
|
||||
this.method.getExecutable(),
|
||||
Message.PROPERTYMAPPING_FORGED_MAPPING_NOT_FOUND,
|
||||
sourceType.describe(),
|
||||
targetType.describe(),
|
||||
targetType.describe(),
|
||||
sourceType.describe()
|
||||
);
|
||||
}
|
||||
else {
|
||||
ForgedMethodHistory history = forgedMethod.getHistory();
|
||||
ctx.getMessager().printMessage(
|
||||
this.method.getExecutable(),
|
||||
Message.PROPERTYMAPPING_FORGED_MAPPING_WITH_HISTORY_NOT_FOUND,
|
||||
history.createSourcePropertyErrorMessage(),
|
||||
history.getTargetType().describe(),
|
||||
history.createTargetPropertyName(),
|
||||
history.getTargetType().describe(),
|
||||
history.getSourceType().describe()
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ForgedMethodHistory history = forgedMethod.getHistory();
|
||||
else if ( !constructorAccessorHadError ) {
|
||||
ctx.getMessager().printMessage(
|
||||
this.method.getExecutable(),
|
||||
Message.PROPERTYMAPPING_FORGED_MAPPING_WITH_HISTORY_NOT_FOUND,
|
||||
history.createSourcePropertyErrorMessage(),
|
||||
history.getTargetType().describe(),
|
||||
history.createTargetPropertyName(),
|
||||
history.getTargetType().describe(),
|
||||
history.getSourceType().describe()
|
||||
method.getExecutable(),
|
||||
Message.PROPERTYMAPPING_TARGET_HAS_NO_TARGET_PROPERTIES,
|
||||
resultType.describe()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1755,7 +1799,8 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
reportErrorForUnmappedProperties(
|
||||
unprocessedTargetProperties,
|
||||
unmappedPropertiesMsg,
|
||||
unmappedForgedPropertiesMsg );
|
||||
unmappedForgedPropertiesMsg
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@ -1764,10 +1809,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
if ( mappingReferences.isForForgedMethods() ) {
|
||||
return ReportingPolicyGem.IGNORE;
|
||||
}
|
||||
// If we have ignoreByDefault = true, unprocessed source properties are not an issue.
|
||||
if ( method.getOptions().getBeanMapping().isignoreByDefault() ) {
|
||||
return ReportingPolicyGem.IGNORE;
|
||||
}
|
||||
return method.getOptions().getBeanMapping().unmappedSourcePolicy();
|
||||
}
|
||||
|
||||
@ -1886,12 +1927,19 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
}
|
||||
|
||||
private static class ConstructorAccessor {
|
||||
private final boolean hasError;
|
||||
private final List<ParameterBinding> parameterBindings;
|
||||
private final Map<String, Accessor> constructorAccessors;
|
||||
|
||||
private ConstructorAccessor(
|
||||
List<ParameterBinding> parameterBindings,
|
||||
Map<String, Accessor> constructorAccessors) {
|
||||
this( false, parameterBindings, constructorAccessors );
|
||||
}
|
||||
|
||||
private ConstructorAccessor(boolean hasError, List<ParameterBinding> parameterBindings,
|
||||
Map<String, Accessor> constructorAccessors) {
|
||||
this.hasError = hasError;
|
||||
this.parameterBindings = parameterBindings;
|
||||
this.constructorAccessors = constructorAccessors;
|
||||
}
|
||||
@ -1913,7 +1961,8 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
MethodReference finalizerMethod,
|
||||
MappingReferences mappingReferences,
|
||||
List<SubclassMapping> subclassMappings,
|
||||
Map<String, PresenceCheck> presenceChecksByParameter) {
|
||||
Map<String, PresenceCheck> presenceChecksByParameter,
|
||||
Type subclassExhaustiveException) {
|
||||
super(
|
||||
method,
|
||||
annotations,
|
||||
@ -1928,6 +1977,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
this.propertyMappings = propertyMappings;
|
||||
this.returnTypeBuilder = returnTypeBuilder;
|
||||
this.finalizerMethod = finalizerMethod;
|
||||
this.subclassExhaustiveException = subclassExhaustiveException;
|
||||
if ( this.finalizerMethod != null ) {
|
||||
this.finalizedResultName =
|
||||
Strings.getSafeVariableName( getResultName() + "Result", existingVariableNames );
|
||||
@ -1976,6 +2026,10 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
this.subclassMappings = subclassMappings;
|
||||
}
|
||||
|
||||
public Type getSubclassExhaustiveException() {
|
||||
return subclassExhaustiveException;
|
||||
}
|
||||
|
||||
public List<PropertyMapping> getConstantMappings() {
|
||||
return constantMappings;
|
||||
}
|
||||
|
@ -240,6 +240,7 @@ public class CollectionAssignmentBuilder {
|
||||
result,
|
||||
method.getThrownTypes(),
|
||||
targetType,
|
||||
nvpms,
|
||||
targetAccessorType.isFieldAssignment()
|
||||
);
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ public abstract class ContainerMappingMethod extends NormalTypeMappingMethod {
|
||||
afterMappingReferences );
|
||||
this.elementAssignment = parameterAssignment;
|
||||
this.loopVariableName = loopVariableName;
|
||||
this.selectionParameters = selectionParameters;
|
||||
this.selectionParameters = selectionParameters != null ? selectionParameters : SelectionParameters.empty();
|
||||
|
||||
this.index1Name = Strings.getSafeVariableName( "i", existingVariables );
|
||||
this.index2Name = Strings.getSafeVariableName( "j", existingVariables );
|
||||
|
||||
|
@ -7,14 +7,15 @@ package org.mapstruct.ap.internal.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.DecoratedWithGem;
|
||||
import org.mapstruct.ap.internal.model.common.Accessibility;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.gem.DecoratedWithGem;
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
|
||||
/**
|
||||
@ -33,6 +34,7 @@ public class Decorator extends GeneratedType {
|
||||
private String implName;
|
||||
private String implPackage;
|
||||
private boolean suppressGeneratorTimestamp;
|
||||
private Set<Annotation> customAnnotations;
|
||||
|
||||
public Builder() {
|
||||
super( Builder.class );
|
||||
@ -68,6 +70,11 @@ public class Decorator extends GeneratedType {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder additionalAnnotations(Set<Annotation> customAnnotations) {
|
||||
this.customAnnotations = customAnnotations;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Decorator build() {
|
||||
String implementationName = implName.replace( Mapper.CLASS_NAME_PLACEHOLDER,
|
||||
Mapper.getFlatName( mapperElement ) );
|
||||
@ -95,7 +102,8 @@ public class Decorator extends GeneratedType {
|
||||
suppressGeneratorTimestamp,
|
||||
Accessibility.fromModifiers( mapperElement.getModifiers() ),
|
||||
extraImportedTypes,
|
||||
decoratorConstructor
|
||||
decoratorConstructor,
|
||||
customAnnotations
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -110,7 +118,8 @@ public class Decorator extends GeneratedType {
|
||||
Options options, VersionInformation versionInformation,
|
||||
boolean suppressGeneratorTimestamp,
|
||||
Accessibility accessibility, SortedSet<Type> extraImports,
|
||||
DecoratorConstructor decoratorConstructor) {
|
||||
DecoratorConstructor decoratorConstructor,
|
||||
Set<Annotation> customAnnotations) {
|
||||
super(
|
||||
typeFactory,
|
||||
packageName,
|
||||
@ -128,6 +137,11 @@ public class Decorator extends GeneratedType {
|
||||
|
||||
this.decoratorType = decoratorType;
|
||||
this.mapperType = mapperType;
|
||||
|
||||
// Add custom annotations
|
||||
if ( customAnnotations != null ) {
|
||||
customAnnotations.forEach( this::addAnnotation );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -146,13 +146,30 @@ public class ForgedMethod implements Method {
|
||||
basedOn,
|
||||
history,
|
||||
mappingReferences == null ? MappingReferences.empty() : mappingReferences,
|
||||
forgedNameBased
|
||||
forgedNameBased,
|
||||
MappingMethodOptions.getSubclassForgedMethodInheritedOptions( basedOn.getOptions() )
|
||||
);
|
||||
}
|
||||
|
||||
private ForgedMethod(String name, Type sourceType, Type returnType, List<Parameter> additionalParameters,
|
||||
Method basedOn, ForgedMethodHistory history, MappingReferences mappingReferences,
|
||||
boolean forgedNameBased) {
|
||||
this(
|
||||
name,
|
||||
sourceType,
|
||||
returnType,
|
||||
additionalParameters,
|
||||
basedOn,
|
||||
history,
|
||||
mappingReferences,
|
||||
forgedNameBased,
|
||||
MappingMethodOptions.getForgedMethodInheritedOptions( basedOn.getOptions() )
|
||||
);
|
||||
}
|
||||
|
||||
private ForgedMethod(String name, Type sourceType, Type returnType, List<Parameter> additionalParameters,
|
||||
Method basedOn, ForgedMethodHistory history, MappingReferences mappingReferences,
|
||||
boolean forgedNameBased, MappingMethodOptions options) {
|
||||
|
||||
// establish name
|
||||
String sourceParamSafeName;
|
||||
@ -185,7 +202,7 @@ public class ForgedMethod implements Method {
|
||||
this.mappingReferences = mappingReferences;
|
||||
this.forgedNameBased = forgedNameBased;
|
||||
|
||||
this.options = MappingMethodOptions.getForgedMethodInheritedOptions( basedOn.getOptions() );
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,7 +133,7 @@ public final class LifecycleMethodResolver {
|
||||
MappingBuilderContext ctx, Set<String> existingVariableNames) {
|
||||
|
||||
MethodSelectors selectors =
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getMessager() );
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getMessager(), ctx.getOptions() );
|
||||
|
||||
List<SelectedMethod<SourceMethod>> matchingMethods = selectors.getMatchingMethods(
|
||||
callbackMethods,
|
||||
|
@ -259,7 +259,7 @@ public class MappingBuilderContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type that MapStruct wants to use to genrate an autoamtic sub-mapping for/from
|
||||
* @param type that MapStruct wants to use to generate an automatic sub-mapping for/from
|
||||
*
|
||||
* @return {@code true} if the type is not excluded from the {@link MappingExclusionProvider}
|
||||
*/
|
||||
|
@ -64,7 +64,7 @@ public class NestedTargetPropertyMappingHolder {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the targets that were hanled
|
||||
* @return all the targets that were handled
|
||||
*/
|
||||
public Set<String> getHandledTargets() {
|
||||
return handledTargets;
|
||||
@ -226,7 +226,7 @@ public class NestedTargetPropertyMappingHolder {
|
||||
handledTargets.add( entryByTP.getKey() );
|
||||
}
|
||||
|
||||
// For the nonNested mappings (assymetric) Mappings we also forge mappings
|
||||
// For the nonNested mappings (asymmetric) Mappings we also forge mappings
|
||||
// However, here we do not forge name based mappings and we only
|
||||
// do update on the defined Mappings.
|
||||
if ( !groupedSourceReferences.nonNested.isEmpty() ) {
|
||||
@ -362,7 +362,13 @@ public class NestedTargetPropertyMappingHolder {
|
||||
Map<String, Set<MappingReference>> singleTargetReferences = new LinkedHashMap<>();
|
||||
for ( MappingReference mapping : mappingReferences.getMappingReferences() ) {
|
||||
TargetReference targetReference = mapping.getTargetReference();
|
||||
String property = first( targetReference.getPropertyEntries() );
|
||||
List<String> propertyEntries = targetReference.getPropertyEntries();
|
||||
if ( propertyEntries.isEmpty() ) {
|
||||
// This can happen if the target property is target = ".",
|
||||
// this usually happens when doing a reverse mapping
|
||||
continue;
|
||||
}
|
||||
String property = first( propertyEntries );
|
||||
MappingReference newMapping = mapping.popTargetReference();
|
||||
if ( newMapping != null ) {
|
||||
// group properties on current name.
|
||||
@ -749,7 +755,7 @@ public class NestedTargetPropertyMappingHolder {
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to group Source references in respected to the nestings that they have.
|
||||
* This class is used to group Source references in respected to the nesting that they have.
|
||||
*
|
||||
* This class contains all groupings by Property Entries if they are nested, or a list of all the other options
|
||||
* that could not have been popped.
|
||||
|
@ -5,12 +5,9 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
|
||||
@ -26,6 +23,8 @@ import org.mapstruct.ap.internal.model.source.selector.SelectedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.selector.SelectionContext;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
@ -126,7 +125,7 @@ public class ObjectFactoryMethodResolver {
|
||||
MappingBuilderContext ctx) {
|
||||
|
||||
MethodSelectors selectors =
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getMessager() );
|
||||
new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getMessager(), null );
|
||||
|
||||
return selectors.getMatchingMethods(
|
||||
getAllAvailableMethods( method, ctx.getSourceModel() ),
|
||||
|
@ -119,7 +119,8 @@ public final class PresenceCheckMethodResolver {
|
||||
MethodSelectors selectors = new MethodSelectors(
|
||||
ctx.getTypeUtils(),
|
||||
ctx.getElementUtils(),
|
||||
ctx.getMessager()
|
||||
ctx.getMessager(),
|
||||
null
|
||||
);
|
||||
|
||||
return selectors.getMatchingMethods(
|
||||
|
@ -11,6 +11,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
@ -746,7 +747,7 @@ public class PropertyMapping extends ModelElement {
|
||||
targetType = targetType.withoutBounds();
|
||||
ForgedMethod methodRef = prepareForgedMethod( sourceType, targetType, source, "[]" );
|
||||
|
||||
ContainerMappingMethod iterableMappingMethod = builder
|
||||
Supplier<MappingMethod> mappingMethodCreator = () -> builder
|
||||
.mappingContext( ctx )
|
||||
.method( methodRef )
|
||||
.selectionParameters( selectionParameters )
|
||||
@ -754,7 +755,7 @@ public class PropertyMapping extends ModelElement {
|
||||
.positionHint( positionHint )
|
||||
.build();
|
||||
|
||||
return createForgedAssignment( source, methodRef, iterableMappingMethod );
|
||||
return getOrCreateForgedAssignment( source, methodRef, mappingMethodCreator );
|
||||
}
|
||||
|
||||
private ForgedMethod prepareForgedMethod(Type sourceType, Type targetType, SourceRHS source, String suffix) {
|
||||
@ -772,12 +773,12 @@ public class PropertyMapping extends ModelElement {
|
||||
ForgedMethod methodRef = prepareForgedMethod( sourceType, targetType, source, "{}" );
|
||||
|
||||
MapMappingMethod.Builder builder = new MapMappingMethod.Builder();
|
||||
MapMappingMethod mapMappingMethod = builder
|
||||
Supplier<MappingMethod> mapMappingMethodCreator = () -> builder
|
||||
.mappingContext( ctx )
|
||||
.method( methodRef )
|
||||
.build();
|
||||
|
||||
return createForgedAssignment( source, methodRef, mapMappingMethod );
|
||||
return getOrCreateForgedAssignment( source, methodRef, mapMappingMethodCreator );
|
||||
}
|
||||
|
||||
private Assignment forgeMapping(SourceRHS sourceRHS) {
|
||||
|
@ -274,7 +274,7 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
// Start to fill the mappings with the defined valuemappings
|
||||
// Start to fill the mappings with the defined valueMappings
|
||||
for ( ValueMappingOptions valueMapping : valueMappings.regularValueMappings ) {
|
||||
mappings.add( new MappingEntry( valueMapping.getSource(), valueMapping.getTarget() ) );
|
||||
unmappedSourceConstants.remove( valueMapping.getSource() );
|
||||
@ -305,7 +305,7 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
}
|
||||
Set<String> mappedSources = new LinkedHashSet<>();
|
||||
|
||||
// Start to fill the mappings with the defined valuemappings
|
||||
// Start to fill the mappings with the defined value mappings
|
||||
for ( ValueMappingOptions valueMapping : valueMappings.regularValueMappings ) {
|
||||
mappedSources.add( valueMapping.getSource() );
|
||||
mappings.add( new MappingEntry( valueMapping.getSource(), valueMapping.getTarget() ) );
|
||||
|
@ -9,9 +9,12 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem;
|
||||
import org.mapstruct.ap.internal.model.common.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.IGNORE;
|
||||
|
||||
/**
|
||||
* This wrapper handles the situation were an assignment must be done via a target getter method because there
|
||||
* is no setter available.
|
||||
@ -26,6 +29,14 @@ import org.mapstruct.ap.internal.model.common.Type;
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAndMaps {
|
||||
private final boolean ignoreMapNull;
|
||||
|
||||
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
|
||||
List<Type> thrownTypesToExclude,
|
||||
Type targetType,
|
||||
boolean fieldAssignment) {
|
||||
this( decoratedAssignment, thrownTypesToExclude, targetType, null, fieldAssignment );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param decoratedAssignment source RHS
|
||||
@ -36,6 +47,7 @@ public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAnd
|
||||
public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment,
|
||||
List<Type> thrownTypesToExclude,
|
||||
Type targetType,
|
||||
NullValuePropertyMappingStrategyGem nvpms,
|
||||
boolean fieldAssignment) {
|
||||
|
||||
super(
|
||||
@ -44,6 +56,7 @@ public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAnd
|
||||
targetType,
|
||||
fieldAssignment
|
||||
);
|
||||
this.ignoreMapNull = nvpms == IGNORE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -54,4 +67,8 @@ public class GetterWrapperForCollectionsAndMaps extends WrapperForCollectionsAnd
|
||||
}
|
||||
return imported;
|
||||
}
|
||||
|
||||
public boolean isIgnoreMapNull() {
|
||||
return ignoreMapNull;
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,37 @@ public class MappingReference {
|
||||
return false;
|
||||
}
|
||||
MappingReference that = (MappingReference) o;
|
||||
return mapping.equals( that.mapping );
|
||||
if ( ".".equals( that.mapping.getTargetName() ) ) {
|
||||
// target this will never be equal to any other target this or any other.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals( mapping.getTargetName(), that.mapping.getTargetName() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !Objects.equals( mapping.getConstant(), that.mapping.getConstant() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !Objects.equals( mapping.getJavaExpression(), that.mapping.getJavaExpression() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( sourceReference == null ) {
|
||||
return that.sourceReference == null;
|
||||
}
|
||||
|
||||
if ( that.sourceReference == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!Objects.equals( sourceReference.getPropertyEntries(), that.sourceReference.getPropertyEntries() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,6 +32,8 @@ public interface ConversionContext {
|
||||
|
||||
String getNumberFormat();
|
||||
|
||||
String getLocale();
|
||||
|
||||
TypeFactory getTypeFactory();
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public class DefaultConversionContext implements ConversionContext {
|
||||
private final FormattingParameters formattingParameters;
|
||||
private final String dateFormat;
|
||||
private final String numberFormat;
|
||||
private final String locale;
|
||||
private final TypeFactory typeFactory;
|
||||
|
||||
public DefaultConversionContext(TypeFactory typeFactory, FormattingMessager messager, Type sourceType,
|
||||
@ -32,6 +33,7 @@ public class DefaultConversionContext implements ConversionContext {
|
||||
this.formattingParameters = formattingParameters;
|
||||
this.dateFormat = this.formattingParameters.getDate();
|
||||
this.numberFormat = this.formattingParameters.getNumber();
|
||||
this.locale = this.formattingParameters.getLocale();
|
||||
validateDateFormat();
|
||||
}
|
||||
|
||||
@ -64,6 +66,11 @@ public class DefaultConversionContext implements ConversionContext {
|
||||
return numberFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocale() {
|
||||
return locale != null ? locale.toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDateFormat() {
|
||||
return dateFormat;
|
||||
|
@ -15,21 +15,23 @@ import javax.lang.model.element.Element;
|
||||
*/
|
||||
public class FormattingParameters {
|
||||
|
||||
public static final FormattingParameters EMPTY = new FormattingParameters( null, null, null, null, null );
|
||||
public static final FormattingParameters EMPTY = new FormattingParameters( null, null, null, null, null, null );
|
||||
|
||||
private final String date;
|
||||
private final String number;
|
||||
private final AnnotationMirror mirror;
|
||||
private final AnnotationValue dateAnnotationValue;
|
||||
private final Element element;
|
||||
private final String locale;
|
||||
|
||||
public FormattingParameters(String date, String number, AnnotationMirror mirror,
|
||||
AnnotationValue dateAnnotationValue, Element element) {
|
||||
AnnotationValue dateAnnotationValue, Element element, String locale) {
|
||||
this.date = date;
|
||||
this.number = number;
|
||||
this.mirror = mirror;
|
||||
this.dateAnnotationValue = dateAnnotationValue;
|
||||
this.element = element;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
@ -51,4 +53,8 @@ public class FormattingParameters {
|
||||
public Element getElement() {
|
||||
return element;
|
||||
}
|
||||
|
||||
public String getLocale() {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
|
@ -16,23 +16,34 @@ public class ImplementationType {
|
||||
private final Type type;
|
||||
private final boolean initialCapacityConstructor;
|
||||
private final boolean loadFactorAdjustment;
|
||||
private final String factoryMethodName;
|
||||
|
||||
private ImplementationType(Type type, boolean initialCapacityConstructor, boolean loadFactorAdjustment) {
|
||||
private ImplementationType(
|
||||
Type type,
|
||||
boolean initialCapacityConstructor,
|
||||
boolean loadFactorAdjustment,
|
||||
String factoryMethodName
|
||||
) {
|
||||
this.type = type;
|
||||
this.initialCapacityConstructor = initialCapacityConstructor;
|
||||
this.loadFactorAdjustment = loadFactorAdjustment;
|
||||
this.factoryMethodName = factoryMethodName;
|
||||
}
|
||||
|
||||
public static ImplementationType withDefaultConstructor(Type type) {
|
||||
return new ImplementationType( type, false, false );
|
||||
return new ImplementationType( type, false, false, null );
|
||||
}
|
||||
|
||||
public static ImplementationType withInitialCapacity(Type type) {
|
||||
return new ImplementationType( type, true, false );
|
||||
return new ImplementationType( type, true, false, null );
|
||||
}
|
||||
|
||||
public static ImplementationType withLoadFactorAdjustment(Type type) {
|
||||
return new ImplementationType( type, true, true );
|
||||
return new ImplementationType( type, true, true, null );
|
||||
}
|
||||
|
||||
public static ImplementationType withFactoryMethod(Type type, String factoryMethodName) {
|
||||
return new ImplementationType( type, true, false, factoryMethodName );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +55,7 @@ public class ImplementationType {
|
||||
* @return a new implementation type with the given {@code type}
|
||||
*/
|
||||
public ImplementationType createNew(Type type) {
|
||||
return new ImplementationType( type, initialCapacityConstructor, loadFactorAdjustment );
|
||||
return new ImplementationType( type, initialCapacityConstructor, loadFactorAdjustment, factoryMethodName );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,4 +82,8 @@ public class ImplementationType {
|
||||
public boolean isLoadFactorAdjustment() {
|
||||
return loadFactorAdjustment;
|
||||
}
|
||||
|
||||
public String getFactoryMethodName() {
|
||||
return factoryMethodName;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,10 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
@ -50,7 +54,7 @@ import org.mapstruct.ap.internal.util.Nouns;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.AccessorType;
|
||||
import org.mapstruct.ap.internal.util.accessor.FieldElementAccessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.ElementAccessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.MapValueAccessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor;
|
||||
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;
|
||||
@ -367,6 +371,15 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
return componentType != null;
|
||||
}
|
||||
|
||||
private boolean isType(Class<?> type) {
|
||||
return type.getName().equals( getFullyQualifiedName() );
|
||||
}
|
||||
|
||||
private boolean isOptionalType() {
|
||||
return isType( Optional.class ) || isType( OptionalInt.class ) || isType( OptionalDouble.class ) ||
|
||||
isType( OptionalLong.class );
|
||||
}
|
||||
|
||||
public boolean isTypeVar() {
|
||||
return (typeMirror.getKind() == TypeKind.TYPEVAR);
|
||||
}
|
||||
@ -783,6 +796,10 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
* @return an unmodifiable map of all write accessors indexed by property name
|
||||
*/
|
||||
public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrategyGem cmStrategy ) {
|
||||
if ( isRecord() ) {
|
||||
// Records do not have setters, so we return an empty map
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
// collect all candidate target accessors
|
||||
List<Accessor> candidates = new ArrayList<>( getSetters() );
|
||||
candidates.addAll( getAlternativeTargetAccessors() );
|
||||
@ -1047,7 +1064,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
List<Accessor> setterMethods = getSetters();
|
||||
List<Accessor> readAccessors = new ArrayList<>( getPropertyReadAccessors().values() );
|
||||
// All the fields are also alternative accessors
|
||||
readAccessors.addAll( filters.fieldsIn( getAllFields(), FieldElementAccessor::new ) );
|
||||
readAccessors.addAll( filters.fieldsIn( getAllFields(), ElementAccessor::new ) );
|
||||
|
||||
// there could be a read accessor (field or method) for a list/map that is not present as setter.
|
||||
// an accessor could substitute the setter in that case and act as setter.
|
||||
@ -1166,6 +1183,10 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
* FTL.
|
||||
*/
|
||||
public String getNull() {
|
||||
if ( isOptionalType() ) {
|
||||
return createReferenceName() + ".empty()";
|
||||
}
|
||||
|
||||
if ( !isPrimitive() || isArrayType() ) {
|
||||
return "null";
|
||||
}
|
||||
|
@ -38,26 +38,29 @@ import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
|
||||
import org.mapstruct.ap.internal.util.Collections;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.Extractor;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.JavaCollectionConstants;
|
||||
import org.mapstruct.ap.internal.util.JavaStreamConstants;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
import org.mapstruct.ap.internal.util.RoundContext;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
||||
import org.mapstruct.ap.spi.BuilderInfo;
|
||||
import org.mapstruct.ap.spi.MoreThanOneBuilderCreationMethodException;
|
||||
import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
|
||||
|
||||
import static org.mapstruct.ap.internal.model.common.ImplementationType.withDefaultConstructor;
|
||||
import static org.mapstruct.ap.internal.model.common.ImplementationType.withFactoryMethod;
|
||||
import static org.mapstruct.ap.internal.model.common.ImplementationType.withInitialCapacity;
|
||||
import static org.mapstruct.ap.internal.model.common.ImplementationType.withLoadFactorAdjustment;
|
||||
|
||||
@ -82,6 +85,8 @@ public class TypeFactory {
|
||||
sb.append( ')' );
|
||||
return sb.toString();
|
||||
};
|
||||
private static final String LINKED_HASH_SET_FACTORY_METHOD_NAME = "newLinkedHashSet";
|
||||
private static final String LINKED_HASH_MAP_FACTORY_METHOD_NAME = "newLinkedHashMap";
|
||||
|
||||
private final ElementUtils elementUtils;
|
||||
private final TypeUtils typeUtils;
|
||||
@ -100,7 +105,8 @@ public class TypeFactory {
|
||||
private final boolean loggingVerbose;
|
||||
|
||||
public TypeFactory(ElementUtils elementUtils, TypeUtils typeUtils, FormattingMessager messager,
|
||||
RoundContext roundContext, Map<String, String> notToBeImportedTypes, boolean loggingVerbose) {
|
||||
RoundContext roundContext, Map<String, String> notToBeImportedTypes, boolean loggingVerbose,
|
||||
VersionInformation versionInformation) {
|
||||
this.elementUtils = elementUtils;
|
||||
this.typeUtils = typeUtils;
|
||||
this.messager = messager;
|
||||
@ -118,11 +124,22 @@ public class TypeFactory {
|
||||
implementationTypes.put( Collection.class.getName(), withInitialCapacity( getType( ArrayList.class ) ) );
|
||||
implementationTypes.put( List.class.getName(), withInitialCapacity( getType( ArrayList.class ) ) );
|
||||
|
||||
implementationTypes.put( Set.class.getName(), withLoadFactorAdjustment( getType( LinkedHashSet.class ) ) );
|
||||
boolean sourceVersionAtLeast19 = versionInformation.isSourceVersionAtLeast19();
|
||||
implementationTypes.put(
|
||||
Set.class.getName(),
|
||||
sourceVersionAtLeast19 ?
|
||||
withFactoryMethod( getType( LinkedHashSet.class ), LINKED_HASH_SET_FACTORY_METHOD_NAME ) :
|
||||
withLoadFactorAdjustment( getType( LinkedHashSet.class ) )
|
||||
);
|
||||
implementationTypes.put( SortedSet.class.getName(), withDefaultConstructor( getType( TreeSet.class ) ) );
|
||||
implementationTypes.put( NavigableSet.class.getName(), withDefaultConstructor( getType( TreeSet.class ) ) );
|
||||
|
||||
implementationTypes.put( Map.class.getName(), withLoadFactorAdjustment( getType( LinkedHashMap.class ) ) );
|
||||
implementationTypes.put(
|
||||
Map.class.getName(),
|
||||
sourceVersionAtLeast19 ?
|
||||
withFactoryMethod( getType( LinkedHashMap.class ), LINKED_HASH_MAP_FACTORY_METHOD_NAME ) :
|
||||
withLoadFactorAdjustment( getType( LinkedHashMap.class ) )
|
||||
);
|
||||
implementationTypes.put( SortedMap.class.getName(), withDefaultConstructor( getType( TreeMap.class ) ) );
|
||||
implementationTypes.put( NavigableMap.class.getName(), withDefaultConstructor( getType( TreeMap.class ) ) );
|
||||
implementationTypes.put(
|
||||
@ -133,6 +150,18 @@ public class TypeFactory {
|
||||
ConcurrentNavigableMap.class.getName(),
|
||||
withDefaultConstructor( getType( ConcurrentSkipListMap.class ) )
|
||||
);
|
||||
implementationTypes.put(
|
||||
JavaCollectionConstants.SEQUENCED_SET_FQN,
|
||||
sourceVersionAtLeast19 ?
|
||||
withFactoryMethod( getType( LinkedHashSet.class ), LINKED_HASH_SET_FACTORY_METHOD_NAME ) :
|
||||
withLoadFactorAdjustment( getType( LinkedHashSet.class ) )
|
||||
);
|
||||
implementationTypes.put(
|
||||
JavaCollectionConstants.SEQUENCED_MAP_FQN,
|
||||
sourceVersionAtLeast19 ?
|
||||
withFactoryMethod( getType( LinkedHashMap.class ), LINKED_HASH_MAP_FACTORY_METHOD_NAME ) :
|
||||
withLoadFactorAdjustment( getType( LinkedHashMap.class ) )
|
||||
);
|
||||
|
||||
this.loggingVerbose = loggingVerbose;
|
||||
}
|
||||
@ -475,7 +504,11 @@ public class TypeFactory {
|
||||
if (accessor.getAccessorType().isFieldAssignment()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return extractTypes( ( (ExecutableElement) accessor.getElement() ).getThrownTypes() );
|
||||
Element element = accessor.getElement();
|
||||
if ( element instanceof ExecutableElement ) {
|
||||
return extractTypes( ( (ExecutableElement) element ).getThrownTypes() );
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private List<Type> extractTypes(List<? extends TypeMirror> typeMirrors) {
|
||||
|
@ -11,6 +11,7 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BeanMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.BuilderGem;
|
||||
@ -58,7 +59,7 @@ public class BeanMappingOptions extends DelegatingOptions {
|
||||
public static BeanMappingOptions forForgedMethods(BeanMappingOptions beanMapping) {
|
||||
BeanMappingOptions options = new BeanMappingOptions(
|
||||
beanMapping.selectionParameters != null ?
|
||||
SelectionParameters.withoutResultType( beanMapping.selectionParameters ) : null,
|
||||
SelectionParameters.withoutResultType( beanMapping.selectionParameters ) : SelectionParameters.empty(),
|
||||
Collections.emptyList(),
|
||||
beanMapping.beanMapping,
|
||||
beanMapping
|
||||
@ -66,8 +67,19 @@ public class BeanMappingOptions extends DelegatingOptions {
|
||||
return options;
|
||||
}
|
||||
|
||||
public static BeanMappingOptions forSubclassForgedMethods(BeanMappingOptions beanMapping) {
|
||||
|
||||
return new BeanMappingOptions(
|
||||
beanMapping.selectionParameters != null ?
|
||||
SelectionParameters.withoutResultType( beanMapping.selectionParameters ) : null,
|
||||
beanMapping.ignoreUnmappedSourceProperties,
|
||||
beanMapping.beanMapping,
|
||||
beanMapping
|
||||
);
|
||||
}
|
||||
|
||||
public static BeanMappingOptions empty(DelegatingOptions delegatingOptions) {
|
||||
return new BeanMappingOptions( null, Collections.emptyList(), null, delegatingOptions );
|
||||
return new BeanMappingOptions( SelectionParameters.empty(), Collections.emptyList(), null, delegatingOptions );
|
||||
}
|
||||
|
||||
public static BeanMappingOptions getInstanceOn(BeanMappingGem beanMapping, MapperOptions mapperOptions,
|
||||
@ -171,6 +183,14 @@ public class BeanMappingOptions extends DelegatingOptions {
|
||||
.orElse( next().getSubclassExhaustiveStrategy() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeMirror getSubclassExhaustiveException() {
|
||||
return Optional.ofNullable( beanMapping ).map( BeanMappingGem::subclassExhaustiveException )
|
||||
.filter( GemValue::hasValue )
|
||||
.map( GemValue::getValue )
|
||||
.orElse( next().getSubclassExhaustiveException() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportingPolicyGem unmappedTargetPolicy() {
|
||||
return Optional.ofNullable( beanMapping ).map( BeanMappingGem::unmappedTargetPolicy )
|
||||
@ -212,7 +232,7 @@ public class BeanMappingOptions extends DelegatingOptions {
|
||||
return selectionParameters;
|
||||
}
|
||||
|
||||
public boolean isignoreByDefault() {
|
||||
public boolean isIgnoredByDefault() {
|
||||
return Optional.ofNullable( beanMapping ).map( BeanMappingGem::ignoreByDefault )
|
||||
.map( GemValue::get )
|
||||
.orElse( false );
|
||||
|
@ -56,16 +56,18 @@ public class DefaultOptions extends DelegatingOptions {
|
||||
|
||||
@Override
|
||||
public ReportingPolicyGem unmappedTargetPolicy() {
|
||||
if ( options.getUnmappedTargetPolicy() != null ) {
|
||||
return options.getUnmappedTargetPolicy();
|
||||
ReportingPolicyGem unmappedTargetPolicy = options.getUnmappedTargetPolicy();
|
||||
if ( unmappedTargetPolicy != null ) {
|
||||
return unmappedTargetPolicy;
|
||||
}
|
||||
return ReportingPolicyGem.valueOf( mapper.unmappedTargetPolicy().getDefaultValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportingPolicyGem unmappedSourcePolicy() {
|
||||
if ( options.getUnmappedSourcePolicy() != null ) {
|
||||
return options.getUnmappedSourcePolicy();
|
||||
ReportingPolicyGem unmappedSourcePolicy = options.getUnmappedSourcePolicy();
|
||||
if ( unmappedSourcePolicy != null ) {
|
||||
return unmappedSourcePolicy;
|
||||
}
|
||||
return ReportingPolicyGem.valueOf( mapper.unmappedSourcePolicy().getDefaultValue() );
|
||||
}
|
||||
@ -77,8 +79,9 @@ public class DefaultOptions extends DelegatingOptions {
|
||||
|
||||
@Override
|
||||
public String componentModel() {
|
||||
if ( options.getDefaultComponentModel() != null ) {
|
||||
return options.getDefaultComponentModel();
|
||||
String defaultComponentModel = options.getDefaultComponentModel();
|
||||
if ( defaultComponentModel != null ) {
|
||||
return defaultComponentModel;
|
||||
}
|
||||
return mapper.componentModel().getDefaultValue();
|
||||
}
|
||||
@ -97,8 +100,9 @@ public class DefaultOptions extends DelegatingOptions {
|
||||
|
||||
@Override
|
||||
public InjectionStrategyGem getInjectionStrategy() {
|
||||
if ( options.getDefaultInjectionStrategy() != null ) {
|
||||
return InjectionStrategyGem.valueOf( options.getDefaultInjectionStrategy().toUpperCase() );
|
||||
String defaultInjectionStrategy = options.getDefaultInjectionStrategy();
|
||||
if ( defaultInjectionStrategy != null ) {
|
||||
return InjectionStrategyGem.valueOf( defaultInjectionStrategy.toUpperCase() );
|
||||
}
|
||||
return InjectionStrategyGem.valueOf( mapper.injectionStrategy().getDefaultValue() );
|
||||
}
|
||||
@ -131,6 +135,10 @@ public class DefaultOptions extends DelegatingOptions {
|
||||
return SubclassExhaustiveStrategyGem.valueOf( mapper.subclassExhaustiveStrategy().getDefaultValue() );
|
||||
}
|
||||
|
||||
public TypeMirror getSubclassExhaustiveException() {
|
||||
return mapper.subclassExhaustiveException().getDefaultValue();
|
||||
}
|
||||
|
||||
public NullValueMappingStrategyGem getNullValueIterableMappingStrategy() {
|
||||
NullValueMappingStrategyGem nullValueIterableMappingStrategy = options.getNullValueIterableMappingStrategy();
|
||||
if ( nullValueIterableMappingStrategy != null ) {
|
||||
|
@ -106,6 +106,10 @@ public abstract class DelegatingOptions {
|
||||
return next.getSubclassExhaustiveStrategy();
|
||||
}
|
||||
|
||||
public TypeMirror getSubclassExhaustiveException() {
|
||||
return next.getSubclassExhaustiveException();
|
||||
}
|
||||
|
||||
public NullValueMappingStrategyGem getNullValueIterableMappingStrategy() {
|
||||
return next.getNullValueIterableMappingStrategy();
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ package org.mapstruct.ap.internal.model.source;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.gem.IterableMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.NullValueMappingStrategyGem;
|
||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import org.mapstruct.tools.gem.GemValue;
|
||||
|
||||
/**
|
||||
@ -34,7 +34,12 @@ public class IterableMappingOptions extends DelegatingOptions {
|
||||
FormattingMessager messager, TypeUtils typeUtils) {
|
||||
|
||||
if ( iterableMapping == null || !isConsistent( iterableMapping, method, messager ) ) {
|
||||
IterableMappingOptions options = new IterableMappingOptions( null, null, null, mapperOptions );
|
||||
IterableMappingOptions options = new IterableMappingOptions(
|
||||
null,
|
||||
SelectionParameters.empty(),
|
||||
null,
|
||||
mapperOptions
|
||||
);
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -50,7 +55,8 @@ public class IterableMappingOptions extends DelegatingOptions {
|
||||
iterableMapping.numberFormat().get(),
|
||||
iterableMapping.mirror(),
|
||||
iterableMapping.dateFormat().getAnnotationValue(),
|
||||
method
|
||||
method,
|
||||
iterableMapping.locale().getValue()
|
||||
);
|
||||
|
||||
IterableMappingOptions options =
|
||||
|
@ -8,14 +8,14 @@ package org.mapstruct.ap.internal.model.source;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.gem.MapMappingGem;
|
||||
import org.mapstruct.ap.internal.gem.NullValueMappingStrategyGem;
|
||||
import org.mapstruct.ap.internal.model.common.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.util.ElementUtils;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.TypeUtils;
|
||||
import org.mapstruct.tools.gem.GemValue;
|
||||
|
||||
/**
|
||||
@ -38,15 +38,17 @@ public class MapMappingOptions extends DelegatingOptions {
|
||||
if ( mapMapping == null || !isConsistent( mapMapping, method, messager ) ) {
|
||||
MapMappingOptions options = new MapMappingOptions(
|
||||
null,
|
||||
SelectionParameters.empty(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
SelectionParameters.empty(),
|
||||
null,
|
||||
mapperOptions
|
||||
);
|
||||
return options;
|
||||
}
|
||||
|
||||
String locale = mapMapping.locale().getValue();
|
||||
|
||||
SelectionParameters keySelection = new SelectionParameters(
|
||||
mapMapping.keyQualifiedBy().get(),
|
||||
mapMapping.keyQualifiedByName().get(),
|
||||
@ -66,7 +68,8 @@ public class MapMappingOptions extends DelegatingOptions {
|
||||
mapMapping.keyNumberFormat().get(),
|
||||
mapMapping.mirror(),
|
||||
mapMapping.keyDateFormat().getAnnotationValue(),
|
||||
method
|
||||
method,
|
||||
locale
|
||||
);
|
||||
|
||||
FormattingParameters valueFormatting = new FormattingParameters(
|
||||
@ -74,7 +77,8 @@ public class MapMappingOptions extends DelegatingOptions {
|
||||
mapMapping.valueNumberFormat().get(),
|
||||
mapMapping.mirror(),
|
||||
mapMapping.valueDateFormat().getAnnotationValue(),
|
||||
method
|
||||
method,
|
||||
locale
|
||||
);
|
||||
|
||||
MapMappingOptions options = new MapMappingOptions(
|
||||
|
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