{@link MappingConstants#SUFFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
* suffix to the source enum
- *
{@link MappingConstants#STRIP_SUFFIX_TRANSFORMATION} - strips the the given {@link #configuration()}
+ *
{@link MappingConstants#STRIP_SUFFIX_TRANSFORMATION} - strips the given {@link #configuration()}
* from the end of the source enum
*
{@link MappingConstants#PREFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
* prefix to the source enum
diff --git a/core/src/main/java/org/mapstruct/InheritInverseConfiguration.java b/core/src/main/java/org/mapstruct/InheritInverseConfiguration.java
index ac582a5dfa..b659b7f37a 100644
--- a/core/src/main/java/org/mapstruct/InheritInverseConfiguration.java
+++ b/core/src/main/java/org/mapstruct/InheritInverseConfiguration.java
@@ -81,8 +81,8 @@
public @interface InheritInverseConfiguration {
/**
- * The name of the inverse mapping method to inherit the mappings from. Needs only to be specified in case more than
- * one inverse method with matching source and target type exists.
+ * The name of the inverse mapping method to inherit the mappings from. Needs to be specified only in case more than
+ * one inverse method exists with a matching source and target type exists.
*
* @return The name of the inverse mapping method to inherit the mappings from.
*/
diff --git a/core/src/main/java/org/mapstruct/Mapper.java b/core/src/main/java/org/mapstruct/Mapper.java
index 0436c0cf69..60725cc441 100644
--- a/core/src/main/java/org/mapstruct/Mapper.java
+++ b/core/src/main/java/org/mapstruct/Mapper.java
@@ -298,7 +298,7 @@ NullValuePropertyMappingStrategy nullValuePropertyMappingStrategy() default
* Can be configured by the {@link MapperConfig#disableSubMappingMethodsGeneration()} as well.
*
* Note: If you need to use {@code disableSubMappingMethodsGeneration} please contact the MapStruct team at
- * mapstruct.org or
+ * mapstruct.org or
* github.com/mapstruct/mapstruct to share what problem you
* are facing with the automatic sub-mapping generation.
*
diff --git a/core/src/main/java/org/mapstruct/MapperConfig.java b/core/src/main/java/org/mapstruct/MapperConfig.java
index 893801cdaa..915f3dd120 100644
--- a/core/src/main/java/org/mapstruct/MapperConfig.java
+++ b/core/src/main/java/org/mapstruct/MapperConfig.java
@@ -269,7 +269,7 @@ MappingInheritanceStrategy mappingInheritanceStrategy()
* Can be overridden by {@link Mapper#disableSubMappingMethodsGeneration()}
*
* Note: If you need to use {@code disableSubMappingMethodsGeneration} please contact the MapStruct team at
- * mapstruct.org or
+ * mapstruct.org or
* github.com/mapstruct/mapstruct to share what problem you
* are facing with the automatic sub-mapping generation.
*
diff --git a/core/src/main/java/org/mapstruct/MappingConstants.java b/core/src/main/java/org/mapstruct/MappingConstants.java
index ce2438298c..3d3d8a4c77 100644
--- a/core/src/main/java/org/mapstruct/MappingConstants.java
+++ b/core/src/main/java/org/mapstruct/MappingConstants.java
@@ -109,7 +109,12 @@ private ComponentModel() {
public static final String DEFAULT = "default";
/**
- * The generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
+ * The generated mapper is an application-scoped CDI bean and can be retrieved via @Inject.
+ * The annotations are either from {@code javax} or {@code jakarta}.
+ * Priority have the {@code javax} annotations.
+ * In case you want to only use Jakarta then use {@link #JAKARTA_CDI}.
+ *
+ * @see #JAKARTA_CDI
*/
public static final String CDI = "cdi";
@@ -138,6 +143,12 @@ private ComponentModel() {
*/
public static final String JAKARTA = "jakarta";
+ /**
+ * The generated mapper is an application-scoped Jakarta CDI bean and can be retrieved via @Inject.
+ * @see #CDI
+ */
+ public static final String JAKARTA_CDI = "jakarta-cdi";
+
}
}
diff --git a/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java b/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java
index 446b879d92..22dba7c58b 100644
--- a/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java
+++ b/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java
@@ -8,7 +8,7 @@
/**
* Strategy for dealing with null source values.
*
- * Note: This strategy is not in effect when the a specific source presence check method is defined
+ * Note: This strategy is not in effect when a specific source presence check method is defined
* in the service provider interface (SPI).
*
* Note: some types of mappings (collections, maps), in which MapStruct is instructed to use a getter or adder
diff --git a/core/src/main/java/org/mapstruct/package-info.java b/core/src/main/java/org/mapstruct/package-info.java
index 02f2b31a42..5a53b5a6d3 100644
--- a/core/src/main/java/org/mapstruct/package-info.java
+++ b/core/src/main/java/org/mapstruct/package-info.java
@@ -13,6 +13,6 @@
* This package contains several annotations which allow to configure how mapper interfaces are generated.
*
*
- * @see MapStruct reference documentation
+ * @see MapStruct reference documentation
*/
package org.mapstruct;
diff --git a/distribution/pom.xml b/distribution/pom.xml
index 9ceeb505ea..0655d1c1c3 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -12,7 +12,7 @@
org.mapstructmapstruct-parent
- 1.6.0-SNAPSHOT
+ 1.5.6-SNAPSHOT../parent/pom.xml
@@ -39,6 +39,13 @@
org.mapstruct.tools.gemgem-api
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ provided
+ true
+
@@ -93,7 +100,7 @@
MapStruct ${project.version}MapStruct ${project.version}
- MapStruct Authors; All rights reserved. Released under the Apache Software License 2.0.]]>
+ MapStruct Authors; All rights reserved. Released under the Apache Software License 2.0.]]>
@@ -187,7 +194,6 @@
javax.xml.bindjaxb-api
- 2.3.1providedtrue
diff --git a/documentation/pom.xml b/documentation/pom.xml
index 0a62a3ef3c..85b094ae0e 100644
--- a/documentation/pom.xml
+++ b/documentation/pom.xml
@@ -12,7 +12,7 @@
org.mapstructmapstruct-parent
- 1.6.0-SNAPSHOT
+ 1.5.6-SNAPSHOT../parent/pom.xml
diff --git a/documentation/src/main/asciidoc/chapter-10-advanced-mapping-options.asciidoc b/documentation/src/main/asciidoc/chapter-10-advanced-mapping-options.asciidoc
index 1cc19fcc3e..9c92745a22 100644
--- a/documentation/src/main/asciidoc/chapter-10-advanced-mapping-options.asciidoc
+++ b/documentation/src/main/asciidoc/chapter-10-advanced-mapping-options.asciidoc
@@ -292,7 +292,7 @@ The source presence checker name can be changed in the MapStruct service provide
[NOTE]
====
-Some types of mappings (collections, maps), in which MapStruct is instructed to use a getter or adder as target accessor see `CollectionMappingStrategy`, MapStruct will always generate a source property
+Some types of mappings (collections, maps), in which MapStruct is instructed to use a getter or adder as target accessor (see `CollectionMappingStrategy`), MapStruct will always generate a source property
null check, regardless the value of the `NullValueCheckStrategy` to avoid addition of `null` to the target collection or map.
====
diff --git a/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc b/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc
index d95983e840..e0603fffa6 100644
--- a/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc
+++ b/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc
@@ -130,7 +130,7 @@ You can find a complete example in the https://github.com/mapstruct/mapstruct-ex
The MapStruct code generator can be configured using _annotation processor options_.
-When invoking javac directly, these options are passed to the compiler in the form _-Akey=value_. When using MapStruct via Maven, any processor options can be passed using an `options` element within the configuration of the Maven processor plug-in like this:
+When invoking javac directly, these options are passed to the compiler in the form _-Akey=value_. When using MapStruct via Maven, any processor options can be passed using `compilerArgs` within the configuration of the Maven processor plug-in like this:
.Maven configuration
====
@@ -215,10 +215,11 @@ suppressGeneratorVersionInfoComment`
Supported values are:
* `default`: the mapper uses no component model, instances are typically retrieved via `Mappers#getMapper(Class)`
-* `cdi`: the generated mapper is an application-scoped CDI bean and can be retrieved via `@Inject`
+* `cdi`: the generated mapper is an application-scoped (from javax.enterprise.context or jakarta.enterprise.context, depending on which one is available with javax.inject having priority) CDI bean and can be retrieved via `@Inject`
* `spring`: the generated mapper is a singleton-scoped Spring bean and can be retrieved via `@Autowired`
* `jsr330`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from javax.inject or jakarta.inject, depending which one is available with javax.inject having priority), e.g. using Spring
* `jakarta`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from jakarta.inject), e.g. using Spring
+* `jakarta-cdi`: the generated mapper is an application-scoped (from jakarta.enterprise.context) CDI bean and can be retrieved via `@Inject`
If a component model is given for a specific mapper via `@Mapper#componentModel()`, the value from the annotation takes precedence.
|`default`
@@ -273,3 +274,28 @@ disableBuilders`
MapStruct can be used with Java 9 and higher versions.
To allow usage of the `@Generated` annotation `java.annotation.processing.Generated` (part of the `java.compiler` module) can be enabled.
+
+=== IDE Integration
+
+There are optional MapStruct plugins for IntelliJ and Eclipse that allow you to have additional completion support (and more) in the annotations.
+
+==== IntelliJ
+
+The https://plugins.jetbrains.com/plugin/10036-mapstruct-support[MapStruct IntelliJ] plugin offers assistance in projects that use MapStruct.
+
+Some features include:
+
+* Code completion in `target`, `source`, `expression`
+* Go To Declaration for properties in `target` and `source`
+* Find Usages of properties in `target` and `source`
+* Refactoring support
+* Errors and Quick Fixes
+
+==== Eclipse
+
+The https://marketplace.eclipse.org/content/mapstruct-eclipse-plugin[MapStruct Eclipse] Plugin offers assistance in projects that use MapStruct.
+
+Some features include:
+
+* Code completion in `target` and `source`
+* Quick Fixes
diff --git a/documentation/src/main/asciidoc/chapter-8-mapping-values.asciidoc b/documentation/src/main/asciidoc/chapter-8-mapping-values.asciidoc
index 24c7324f1d..2ffe1b80d6 100644
--- a/documentation/src/main/asciidoc/chapter-8-mapping-values.asciidoc
+++ b/documentation/src/main/asciidoc/chapter-8-mapping-values.asciidoc
@@ -65,7 +65,7 @@ public class OrderMapperImpl implements OrderMapper {
----
====
By default an error will be raised by MapStruct in case a constant of the source enum type does not have a corresponding constant with the same name in the target type and also is not mapped to another constant via `@ValueMapping`. This ensures that all constants are mapped in a safe and predictable manner. The generated
-mapping method will throw an IllegalStateException if for some reason an unrecognized source value occurs.
+mapping method will throw an `IllegalStateException` if for some reason an unrecognized source value occurs.
MapStruct also has a mechanism for mapping any remaining (unspecified) mappings to a default. This can be used only once in a set of value mappings and only applies to the source. It comes in two flavors: `` and ``. They cannot be used at the same time.
@@ -75,14 +75,18 @@ MapStruct will *not* attempt such name based mapping for `` and di
MapStruct is able to handle `null` sources and `null` targets by means of the `` keyword.
+In addition, the constant value `` can be used for throwing an exception for particular value mappings. This value is only applicable to `ValueMapping#target()` and not `ValueMapping#source()` since MapStruct can't map from exceptions.
+
[TIP]
====
-Constants for ``, `` and `` are available in the `MappingConstants` class.
+Constants for ``, ``, `` and `` are available in the `MappingConstants` class.
====
Finally `@InheritInverseConfiguration` and `@InheritConfiguration` can be used in combination with `@ValueMappings`. `` and `` will be ignored in that case.
-.Enum mapping method, and
+The following code snippets exemplify the use of the aforementioned constants.
+
+.Enum mapping method, `` and ``
====
[source, java, linenums]
[subs="verbatim,attributes"]
@@ -102,7 +106,7 @@ public interface SpecialOrderMapper {
----
====
-.Enum mapping method result, and
+.Enum mapping method result, `` and ``
====
[source, java, linenums]
[subs="verbatim,attributes"]
@@ -137,6 +141,55 @@ public class SpecialOrderMapperImpl implements SpecialOrderMapper {
*Note:* MapStruct would have refrained from mapping the `RETAIL` and `B2B` when `` was used instead of ``.
+.Enum mapping method with ``
+====
+[source, java, linenums]
+[subs="verbatim,attributes"]
+----
+@Mapper
+public interface SpecialOrderMapper {
+
+ SpecialOrderMapper INSTANCE = Mappers.getMapper( SpecialOrderMapper.class );
+
+ @ValueMappings({
+ @ValueMapping( source = "STANDARD", target = "DEFAULT" ),
+ @ValueMapping( source = "C2C", target = MappingConstants.THROW_EXCEPTION )
+ })
+ ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
+}
+----
+====
+
+.Enum mapping method with `` result
+====
+[source, java, linenums]
+[subs="verbatim,attributes"]
+----
+// GENERATED CODE
+public class SpecialOrderMapperImpl implements SpecialOrderMapper {
+
+ @Override
+ public ExternalOrderType orderTypeToExternalOrderType(OrderType orderType) {
+ if ( orderType == null ) {
+ return null;
+ }
+
+ ExternalOrderType externalOrderType;
+
+ switch ( orderType ) {
+ case STANDARD: externalOrderType = ExternalOrderType.DEFAULT;
+ break;
+ case C2C: throw new IllegalArgumentException( "Unexpected enum constant: " + orderType );
+ default: throw new IllegalArgumentException( "Unexpected enum constant: " + orderType );
+ }
+
+ return externalOrderType;
+ }
+}
+----
+====
+
+
[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.
@@ -152,6 +205,7 @@ MapStruct supports enum to a String mapping along the same lines as is described
2. Similarity: ` stops after handling defined mapping and proceeds to the switch/default clause value.
3. Difference: `` will result in an error. It acts on the premise that there is name similarity between enum constants in source and target which does not make sense for a String type.
4. Difference: Given 1. and 3. there will never be unmapped values.
+5. Similarity: `` can be used for throwing an exception for particular enum values.
*`String` to enum*
@@ -159,6 +213,7 @@ MapStruct supports enum to a String mapping along the same lines as is described
2. Similarity: ` stops after handling defined mapping and proceeds to the switch/default clause value.
3. Similarity: `` will create a mapping for each target enum constant and proceed to the switch/default clause value.
4. Difference: A switch/default value needs to be provided to have a determined outcome (enum has a limited set of values, `String` has unlimited options). Failing to specify `` or ` will result in a warning.
+5. Similarity: `` can be used for throwing an exception for any arbitrary `String` value.
=== Custom name transformation
diff --git a/integrationtest/pom.xml b/integrationtest/pom.xml
index 364faae643..e5b461e61b 100644
--- a/integrationtest/pom.xml
+++ b/integrationtest/pom.xml
@@ -12,7 +12,7 @@
org.mapstructmapstruct-parent
- 1.6.0-SNAPSHOT
+ 1.5.6-SNAPSHOT../parent/pom.xml
@@ -133,8 +133,8 @@
javax.xml.bindjaxb-api
- 2.3.1provided
+ true
diff --git a/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java b/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java
index c8bac6208c..4723e55e58 100644
--- a/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java
+++ b/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java
@@ -28,6 +28,14 @@ public Collection getAdditionalCommandLineArguments(ProcessorTest.Proces
additionalExcludes.add( "org/mapstruct/ap/test/bugs/_1801/*.java" );
switch ( currentJreVersion ) {
+ case JAVA_8:
+ if ( processorType == ProcessorTest.ProcessorType.ECLIPSE_JDT ) {
+ additionalExcludes.add(
+ "org/mapstruct/ap/test/selection/methodgenerics/wildcards/LifecycleIntersectionMapper.java" );
+ }
+ additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/cdi/**/*.java" );
+ additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/jakarta_cdi/**/*.java" );
+ break;
case JAVA_9:
// TODO find out why this fails:
additionalExcludes.add( "org/mapstruct/ap/test/collection/wildcard/BeanMapper.java" );
diff --git a/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java b/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
index 7d63ccf774..75513dd6c6 100644
--- a/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
+++ b/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
@@ -75,6 +75,10 @@ void java8Test() {
void jaxbTest() {
}
+ @ProcessorTest(baseDir = "jakartaJaxbTest")
+ void jakartaJaxbTest() {
+ }
+
@ProcessorTest(baseDir = "jsr330Test")
void jsr330Test() {
}
diff --git a/integrationtest/src/test/resources/fullFeatureTest/pom.xml b/integrationtest/src/test/resources/fullFeatureTest/pom.xml
index ec26f45ce2..ac69114bd6 100644
--- a/integrationtest/src/test/resources/fullFeatureTest/pom.xml
+++ b/integrationtest/src/test/resources/fullFeatureTest/pom.xml
@@ -64,6 +64,10 @@
jakarta.injectjakarta.inject-api
+
+ jakarta.enterprise
+ jakarta.enterprise.cdi-api
+
@@ -79,6 +83,13 @@
joda-timejoda-time
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ provided
+ true
+
@@ -89,14 +100,16 @@
- jakarta.xml.bind
- jakarta.xml.bind-api
- 2.3.2
+ javax.xml.bind
+ jaxb-api
+ provided
+ trueorg.glassfish.jaxbjaxb-runtime
- 2.3.2
+ provided
+ true
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/pom.xml b/integrationtest/src/test/resources/jakartaJaxbTest/pom.xml
new file mode 100644
index 0000000000..3aabc1c7ae
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/pom.xml
@@ -0,0 +1,64 @@
+
+
+
+ 4.0.0
+
+
+ org.mapstruct
+ mapstruct-it-parent
+ 1.0.0
+ ../pom.xml
+
+
+ jakartaJaxbTest
+ jar
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ provided
+ true
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ provided
+ true
+
+
+
+
+
+
+ org.codehaus.mojo
+ jaxb2-maven-plugin
+ 3.1.0
+
+
+ xjc
+ initialize
+
+ xjc
+
+
+
+
+
+ ${project.build.resources[0].directory}/binding
+
+
+ ${project.build.resources[0].directory}/schema
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderDetailsDto.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderDetailsDto.java
new file mode 100644
index 0000000000..e8500633e4
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderDetailsDto.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+import java.util.List;
+
+/**
+ * @author Sjaak Derksen
+ */
+public class OrderDetailsDto {
+
+ private String name;
+ private List description;
+ private OrderStatusDto status;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List getDescription() {
+ return description;
+ }
+
+ public void setDescription(List description) {
+ this.description = description;
+ }
+
+ public OrderStatusDto getStatus() {
+ return status;
+ }
+
+ public void setStatus(OrderStatusDto status) {
+ this.status = status;
+ }
+}
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderDto.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderDto.java
new file mode 100644
index 0000000000..f94d5362ef
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderDto.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+import java.util.Date;
+
+/**
+ * @author Sjaak Derksen
+ */
+public class OrderDto {
+
+ private Long orderNumber;
+ private Date orderDate;
+ private OrderDetailsDto orderDetails;
+ private ShippingAddressDto shippingAddress;
+
+ public Long getOrderNumber() {
+ return orderNumber;
+ }
+
+ public void setOrderNumber(Long orderNumber) {
+ this.orderNumber = orderNumber;
+ }
+
+ public Date getOrderDate() {
+ return orderDate;
+ }
+
+ public void setOrderDate(Date orderDate) {
+ this.orderDate = orderDate;
+ }
+
+ public OrderDetailsDto getOrderDetails() {
+ return orderDetails;
+ }
+
+ public void setOrderDetails(OrderDetailsDto orderDetails) {
+ this.orderDetails = orderDetails;
+ }
+
+ public ShippingAddressDto getShippingAddress() {
+ return shippingAddress;
+ }
+
+ public void setShippingAddress(ShippingAddressDto shippingAddress) {
+ this.shippingAddress = shippingAddress;
+ }
+
+}
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderStatusDto.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderStatusDto.java
new file mode 100644
index 0000000000..5da5d45c99
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/OrderStatusDto.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+/**
+ * @author Sjaak Derksen
+ */
+public enum OrderStatusDto {
+
+ ORDERED( "small" ),
+ PROCESSED( "medium" ),
+ DELIVERED( "large" );
+ private final String value;
+
+ OrderStatusDto(String v) {
+ value = v;
+ }
+
+ public String value() {
+ return value;
+ }
+
+ public static OrderStatusDto fromValue(String v) {
+ for ( OrderStatusDto c : OrderStatusDto.values() ) {
+ if ( c.value.equals( v ) ) {
+ return c;
+ }
+ }
+ throw new IllegalArgumentException( v );
+ }
+
+}
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/ShippingAddressDto.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/ShippingAddressDto.java
new file mode 100644
index 0000000000..6bc40a19b2
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/ShippingAddressDto.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+/**
+ * @author Sjaak Derksen
+ */
+public class ShippingAddressDto {
+
+ private String street;
+ private String houseNumber;
+ private String city;
+ private String country;
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getHouseNumber() {
+ return houseNumber;
+ }
+
+ public void setHouseNumber(String houseNumber) {
+ this.houseNumber = houseNumber;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+}
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SourceTargetMapper.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SourceTargetMapper.java
new file mode 100644
index 0000000000..3b76aad437
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SourceTargetMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+import org.mapstruct.itest.jakarta.jaxb.xsd.test1.OrderDetailsType;
+import org.mapstruct.itest.jakarta.jaxb.xsd.test1.OrderType;
+import org.mapstruct.itest.jakarta.jaxb.xsd.test2.OrderStatusType;
+import org.mapstruct.itest.jakarta.jaxb.xsd.test2.ShippingAddressType;
+import org.mapstruct.itest.jakarta.jaxb.xsd.underscores.SubType;
+
+
+/**
+ * @author Sjaak Derksen
+ */
+@Mapper(uses = {
+ org.mapstruct.itest.jakarta.jaxb.xsd.test1.ObjectFactory.class,
+ org.mapstruct.itest.jakarta.jaxb.xsd.test2.ObjectFactory.class,
+ org.mapstruct.itest.jakarta.jaxb.xsd.underscores.ObjectFactory.class
+})
+public interface SourceTargetMapper {
+
+ SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
+
+ // source 2 target methods
+ OrderDto sourceToTarget(OrderType source);
+
+ OrderDetailsDto detailsToDto(OrderDetailsType source);
+
+ OrderStatusDto statusToDto(OrderStatusType source);
+
+ ShippingAddressDto shippingAddressToDto(ShippingAddressType source);
+
+ SubTypeDto subTypeToDto(SubType source);
+
+ // target 2 source methods
+ OrderType targetToSource(OrderDto target);
+
+ OrderDetailsType dtoToDetails(OrderDetailsDto target);
+
+ OrderStatusType dtoToStatus(OrderStatusDto target);
+
+ ShippingAddressType dtoToShippingAddress(ShippingAddressDto source);
+
+ SubType dtoToSubType(SubTypeDto source);
+}
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SubTypeDto.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SubTypeDto.java
new file mode 100644
index 0000000000..88218c2771
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SubTypeDto.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+public class SubTypeDto extends SuperTypeDto {
+ private String declaredCamelCase;
+ private String declaredUnderscore;
+
+ public String getDeclaredCamelCase() {
+ return declaredCamelCase;
+ }
+
+ public void setDeclaredCamelCase(String declaredCamelCase) {
+ this.declaredCamelCase = declaredCamelCase;
+ }
+
+ public String getDeclaredUnderscore() {
+ return declaredUnderscore;
+ }
+
+ public void setDeclaredUnderscore(String declaredUnderscore) {
+ this.declaredUnderscore = declaredUnderscore;
+ }
+}
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SuperTypeDto.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SuperTypeDto.java
new file mode 100644
index 0000000000..cd0c6e22e7
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/java/org/mapstruct/itest/jakarta/jaxb/SuperTypeDto.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+public class SuperTypeDto {
+ private String inheritedCamelCase;
+ private String inheritedUnderscore;
+
+ public String getInheritedCamelCase() {
+ return inheritedCamelCase;
+ }
+
+ public void setInheritedCamelCase(String inheritedCamelCase) {
+ this.inheritedCamelCase = inheritedCamelCase;
+ }
+
+ public String getInheritedUnderscore() {
+ return inheritedUnderscore;
+ }
+
+ public void setInheritedUnderscore(String inheritedUnderscore) {
+ this.inheritedUnderscore = inheritedUnderscore;
+ }
+}
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/binding/binding.xjb b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/binding/binding.xjb
new file mode 100644
index 0000000000..8f26b1a1ea
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/binding/binding.xjb
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/test1.xsd b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/test1.xsd
new file mode 100644
index 0000000000..3433b01465
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/test1.xsd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/test2.xsd b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/test2.xsd
new file mode 100644
index 0000000000..f3b564a48e
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/test2.xsd
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/underscores.xsd b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/underscores.xsd
new file mode 100644
index 0000000000..b7f5904656
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/main/resources/schema/underscores.xsd
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/jakartaJaxbTest/src/test/java/org/mapstruct/itest/jakarta/jaxb/JakartaJaxbBasedMapperTest.java b/integrationtest/src/test/resources/jakartaJaxbTest/src/test/java/org/mapstruct/itest/jakarta/jaxb/JakartaJaxbBasedMapperTest.java
new file mode 100644
index 0000000000..b81c946d9c
--- /dev/null
+++ b/integrationtest/src/test/resources/jakartaJaxbTest/src/test/java/org/mapstruct/itest/jakarta/jaxb/JakartaJaxbBasedMapperTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.jakarta.jaxb;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBElement;
+import jakarta.xml.bind.JAXBException;
+import jakarta.xml.bind.Marshaller;
+
+import org.junit.Test;
+import org.mapstruct.itest.jakarta.jaxb.xsd.test1.ObjectFactory;
+import org.mapstruct.itest.jakarta.jaxb.xsd.test1.OrderType;
+import org.mapstruct.itest.jakarta.jaxb.xsd.underscores.SubType;
+
+/**
+ * Test for generation of Jakarta JAXB based mapper implementations.
+ *
+ * @author Iaroslav Bogdanchikov
+ */
+public class JakartaJaxbBasedMapperTest {
+
+ @Test
+ public void shouldMapJakartaJaxb() throws ParseException, JAXBException {
+
+ SourceTargetMapper mapper = SourceTargetMapper.INSTANCE;
+
+ OrderDto source1 = new OrderDto();
+ source1.setOrderDetails( new OrderDetailsDto() );
+ source1.setOrderNumber( 11L );
+ source1.setOrderDate( createDate( "31-08-1982 10:20:56" ) );
+ source1.setShippingAddress( new ShippingAddressDto() );
+ source1.getShippingAddress().setCity( "SmallTown" );
+ source1.getShippingAddress().setHouseNumber( "11a" );
+ source1.getShippingAddress().setStreet( "Awesome rd" );
+ source1.getShippingAddress().setCountry( "USA" );
+ source1.getOrderDetails().setDescription( new ArrayList() );
+ source1.getOrderDetails().setName( "Shopping list for a Mapper" );
+ source1.getOrderDetails().getDescription().add( "1 MapStruct" );
+ source1.getOrderDetails().getDescription().add( "3 Lines of Code" );
+ source1.getOrderDetails().getDescription().add( "1 Dose of Luck" );
+ source1.getOrderDetails().setStatus( OrderStatusDto.ORDERED );
+
+ // map to JAXB
+ OrderType target = mapper.targetToSource( source1 );
+
+ // do a pretty print
+ ObjectFactory of = new ObjectFactory();
+ System.out.println( toXml( of.createOrder( target ) ) );
+
+ // map back from JAXB
+ OrderDto source2 = mapper.sourceToTarget( target );
+
+ // verify that source1 and source 2 are equal
+ assertThat( source2.getOrderNumber() ).isEqualTo( source1.getOrderNumber() );
+ assertThat( source2.getOrderDate() ).isEqualTo( source1.getOrderDate() );
+ assertThat( source2.getOrderDetails().getDescription().size() ).isEqualTo(
+ source1.getOrderDetails().getDescription().size()
+ );
+ assertThat( source2.getOrderDetails().getDescription().get( 0 ) ).isEqualTo(
+ source1.getOrderDetails().getDescription().get( 0 )
+ );
+ assertThat( source2.getOrderDetails().getDescription().get( 1 ) ).isEqualTo(
+ source1.getOrderDetails().getDescription().get( 1 )
+ );
+ assertThat( source2.getOrderDetails().getDescription().get( 2 ) ).isEqualTo(
+ source1.getOrderDetails().getDescription().get( 2 )
+ );
+ assertThat( source2.getOrderDetails().getName() ).isEqualTo( source1.getOrderDetails().getName() );
+ assertThat( source2.getOrderDetails().getStatus() ).isEqualTo( source1.getOrderDetails().getStatus() );
+ }
+
+ @Test
+ public void underscores() throws ParseException, JAXBException {
+
+ SourceTargetMapper mapper = SourceTargetMapper.INSTANCE;
+
+ SubTypeDto source1 = new SubTypeDto();
+ source1.setInheritedCamelCase("InheritedCamelCase");
+ source1.setInheritedUnderscore("InheritedUnderscore");
+ source1.setDeclaredCamelCase("DeclaredCamelCase");
+ source1.setDeclaredUnderscore("DeclaredUnderscore");
+
+ SubType target = mapper.dtoToSubType( source1 );
+
+ SubTypeDto source2 = mapper.subTypeToDto( target );
+
+ assertThat( source2.getInheritedCamelCase() ).isEqualTo( source1.getInheritedCamelCase() );
+ assertThat( source2.getInheritedUnderscore() ).isEqualTo( source1.getInheritedUnderscore() );
+ assertThat( source2.getDeclaredCamelCase() ).isEqualTo( source1.getDeclaredCamelCase() );
+ assertThat( source2.getDeclaredUnderscore() ).isEqualTo( source1.getDeclaredUnderscore() );
+ }
+
+ private Date createDate(String date) throws ParseException {
+ SimpleDateFormat sdf = new SimpleDateFormat( "dd-M-yyyy hh:mm:ss" );
+ return sdf.parse( date );
+ }
+
+ private String toXml(JAXBElement> element) throws JAXBException {
+ JAXBContext jc = JAXBContext.newInstance( element.getValue().getClass() );
+ Marshaller marshaller = jc.createMarshaller();
+ marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ marshaller.marshal( element, baos );
+ return baos.toString();
+ }
+}
diff --git a/integrationtest/src/test/resources/jaxbTest/pom.xml b/integrationtest/src/test/resources/jaxbTest/pom.xml
index 000e7cf598..0e69e23e01 100644
--- a/integrationtest/src/test/resources/jaxbTest/pom.xml
+++ b/integrationtest/src/test/resources/jaxbTest/pom.xml
@@ -51,7 +51,7 @@
org.glassfish.jaxbjaxb-runtime
- 2.3.2
+ ${jaxb-runtime.version}
@@ -66,14 +66,16 @@
- jakarta.xml.bind
- jakarta.xml.bind-api
- 2.3.2
+ javax.xml.bind
+ jaxb-api
+ provided
+ trueorg.glassfish.jaxbjaxb-runtime
- 2.3.2
+ provided
+ true
diff --git a/parent/pom.xml b/parent/pom.xml
index 1c031a7b71..3a826570cc 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -11,12 +11,12 @@
org.mapstructmapstruct-parent
- 1.6.0-SNAPSHOT
+ 1.5.6-SNAPSHOTpomMapStruct ParentAn annotation processor for generating type-safe bean mappers
- http://mapstruct.org/
+ https://mapstruct.org/2012
@@ -42,6 +42,7 @@
-->
1.83.21.2
+ 2.3.2
@@ -70,7 +71,7 @@
scm:git:git://github.com/mapstruct/mapstruct.gitscm:git:git@github.com:mapstruct/mapstruct.githttps://github.com/mapstruct/mapstruct/
- HEAD
+ 1.5.5-SNAPSHOT
@@ -160,6 +161,11 @@
cdi-api2.0.SP1
+
+ jakarta.enterprise
+ jakarta.enterprise.cdi-api
+ 4.0.1
+ javax.injectjavax.inject
@@ -250,6 +256,30 @@
2.9
+
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.1
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ ${jaxb-runtime.version}
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ 3.0.1
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ 3.0.2
+
+
org.eclipse.tycho
@@ -483,12 +513,12 @@
org.codehaus.mojoanimal-sniffer-maven-plugin
- 1.17
+ 1.20org.ow2.asmasm
- 6.2.1
+ 7.0
diff --git a/pom.xml b/pom.xml
index 25a5ead6bc..26f4b4280a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
org.mapstructmapstruct-parent
- 1.6.0-SNAPSHOT
+ 1.5.6-SNAPSHOTparent/pom.xml
@@ -54,7 +54,7 @@
scm:git:git://github.com/mapstruct/mapstruct.gitscm:git:git@github.com:mapstruct/mapstruct.githttps://github.com/mapstruct/mapstruct/
- HEAD
+ 1.5.5-SNAPSHOT
diff --git a/processor/pom.xml b/processor/pom.xml
index 6f2bb6495c..4faf82f5e3 100644
--- a/processor/pom.xml
+++ b/processor/pom.xml
@@ -12,7 +12,7 @@
org.mapstructmapstruct-parent
- 1.6.0-SNAPSHOT
+ 1.5.6-SNAPSHOT../parent/pom.xml
@@ -89,6 +89,11 @@
jakarta.inject-apitest
+
+ jakarta.enterprise
+ jakarta.enterprise.cdi-api
+ test
+
@@ -132,6 +137,13 @@
joda-timetest
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ provided
+ true
+
@@ -370,7 +382,6 @@
javax.xml.bindjaxb-api
- 2.3.1providedtrue
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java
index 2f530618c9..3503a0e274 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/AbstractJavaTimeToStringConversion.java
@@ -21,15 +21,15 @@
*
*
* In general each type comes with a "parse" method to convert a string to this particular type.
- * For formatting a dedicated instance of {@link java.time.format.DateTimeFormatter} is used.
+ * For formatting a dedicated instance of {@link DateTimeFormatter} is used.
*
*
* If no date format for mapping is specified predefined ISO* formatters from
- * {@link java.time.format.DateTimeFormatter} are used.
+ * {@link DateTimeFormatter} are used.
*
*
- * An overview of date and time types shipped with Java 8 can be found at
- * http://docs.oracle.com/javase/tutorial/datetime/iso/index.html.
+ * An overview of date and time types shipped with Java 8 can be found at the
+ * Standard Calendar Tutorial
*
*/
public abstract class AbstractJavaTimeToStringConversion extends SimpleConversion {
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/gem/MappingConstantsGem.java b/processor/src/main/java/org/mapstruct/ap/internal/gem/MappingConstantsGem.java
index cb6d49c0cb..bc58024ca3 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/gem/MappingConstantsGem.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/gem/MappingConstantsGem.java
@@ -51,6 +51,8 @@ private ComponentModelGem() {
public static final String JSR330 = "jsr330";
public static final String JAKARTA = "jakarta";
+
+ public static final String JAKARTA_CDI = "jakarta-cdi";
}
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/gem/jakarta/JakartaGemGenerator.java b/processor/src/main/java/org/mapstruct/ap/internal/gem/jakarta/JakartaGemGenerator.java
new file mode 100644
index 0000000000..93bdebeaef
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/internal/gem/jakarta/JakartaGemGenerator.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.internal.gem.jakarta;
+
+import jakarta.xml.bind.annotation.XmlElementDecl;
+import jakarta.xml.bind.annotation.XmlElementRef;
+import org.mapstruct.tools.gem.GemDefinition;
+
+/**
+ * This class is a temporary solution to an issue in the Gem Tools library.
+ *
+ *
+ * This class can be merged with {@link org.mapstruct.ap.internal.gem.GemGenerator}
+ * after the mentioned issue is resolved.
+ *
+ *
+ * @see Gem Tools issue #10
+ * @author Iaroslav Bogdanchikov
+ */
+@GemDefinition(XmlElementDecl.class)
+@GemDefinition(XmlElementRef.class)
+class JakartaGemGenerator {
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java
index d17718370d..4833bd86ef 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java
@@ -340,6 +340,14 @@ else if ( !method.isUpdateMethod() ) {
if ( factoryMethod != null ) {
forgedMethod.addThrownTypes( factoryMethod.getThrownTypes() );
}
+ for ( LifecycleCallbackMethodReference beforeMappingMethod : beforeMappingMethods ) {
+ forgedMethod.addThrownTypes( beforeMappingMethod.getThrownTypes() );
+ }
+
+ for ( LifecycleCallbackMethodReference afterMappingMethod : afterMappingMethods ) {
+ forgedMethod.addThrownTypes( afterMappingMethod.getThrownTypes() );
+ }
+
for ( PropertyMapping propertyMapping : propertyMappings ) {
if ( propertyMapping.getAssignment() != null ) {
@@ -398,15 +406,13 @@ private SubclassMapping createSubclassMapping(SubclassMappingOptions subclassMap
"SubclassMapping for " + sourceType.getFullyQualifiedName() );
SelectionCriteria criteria =
SelectionCriteria
- .forMappingMethods(
+ .forSubclassMappingMethods(
new SelectionParameters(
Collections.emptyList(),
Collections.emptyList(),
subclassMappingOptions.getTarget(),
ctx.getTypeUtils() ).withSourceRHS( rightHandSide ),
- null,
- null,
- false );
+ subclassMappingOptions.getMappingControl( ctx.getElementUtils() ) );
Assignment assignment = ctx
.getMappingResolver()
.getTargetAssignment(
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/ForgedMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/ForgedMethod.java
index a1f5b091ce..a33bc7520e 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/ForgedMethod.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/ForgedMethod.java
@@ -196,7 +196,7 @@ private ForgedMethod(String name, Type sourceType, Type returnType, List();
+ this.thrownTypes = forgedMethod.thrownTypes;
this.history = forgedMethod.history;
this.sourceParameters = Parameter.getSourceParameters( parameters );
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java
index 134ab081dc..09bfa236b1 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java
@@ -257,8 +257,10 @@ protected void addIfImportRequired(Collection collection, Type typeToAdd)
return;
}
- if ( needsImportDeclaration( typeToAdd ) ) {
- collection.add( typeToAdd );
+ for ( Type type : typeToAdd.getImportTypes() ) {
+ if ( needsImportDeclaration( type ) ) {
+ collection.add( type );
+ }
}
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java
index 35b35aee73..6ff85c585f 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java
@@ -176,7 +176,7 @@ public boolean equals(Object obj) {
*
* @param parameter source
* @param returnType target
- * @return {@code true}, iff the the type variables match
+ * @return {@code true}, iff the type variables match
*/
public boolean doTypeVarsMatch(Type parameter, Type returnType) {
return true;
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleMethodResolver.java b/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleMethodResolver.java
index 87527e87f8..8b44dee254 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleMethodResolver.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleMethodResolver.java
@@ -141,7 +141,7 @@ private static List collectLifecycleCallbackMe
callbackMethods,
Collections.emptyList(),
targetType,
- method.getReturnType(),
+ method.getResultType(),
SelectionCriteria.forLifecycleMethods( selectionParameters ) );
return toLifecycleCallbackMethodRefs(
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/ExistingInstanceSetterWrapperForCollectionsAndMaps.java b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/ExistingInstanceSetterWrapperForCollectionsAndMaps.java
index 06a2712f00..2dd7f81a0b 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/ExistingInstanceSetterWrapperForCollectionsAndMaps.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/ExistingInstanceSetterWrapperForCollectionsAndMaps.java
@@ -22,7 +22,7 @@
/**
* This wrapper handles the situation where an assignment is done for an update method.
*
- * In case of a pre-existing target the wrapper checks if there is an collection or map initialized on the target bean
+ * In case of a pre-existing target the wrapper checks if there is a collection or map initialized on the target bean
* (not null). If so it uses the addAll (for collections) or putAll (for maps). The collection / map is cleared in case
* of a pre-existing target {@link org.mapstruct.MappingTarget }before adding the source entries.
*
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/GetterWrapperForCollectionsAndMaps.java b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/GetterWrapperForCollectionsAndMaps.java
index 40e195dcd0..d29a80b420 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/GetterWrapperForCollectionsAndMaps.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/GetterWrapperForCollectionsAndMaps.java
@@ -16,7 +16,7 @@
* This wrapper handles the situation were an assignment must be done via a target getter method because there
* is no setter available.
*
- * The wrapper checks if there is an collection or map initialized on the target bean (not null). If so it uses the
+ * The wrapper checks if there is a collection or map initialized on the target bean (not null). If so it uses the
* addAll (for collections) or putAll (for maps). The collection / map is cleared in case of a pre-existing target
* {@link org.mapstruct.MappingTarget }before adding the source entries. The goal is that the same collection / map
* is used as target.
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java
index cf0140e8ce..ff5089d6c2 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java
@@ -54,7 +54,7 @@ private static Type determineImplType(Assignment factoryMethod, Type targetType)
return targetType.getImplementationType();
}
- // no factory method means we create a new instance ourself and thus need to import the type
+ // no factory method means we create a new instance ourselves and thus need to import the type
return targetType;
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/PropertyEntry.java b/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/PropertyEntry.java
index cb6cd8af79..a3c8a74e3f 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/PropertyEntry.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/PropertyEntry.java
@@ -14,7 +14,7 @@
/**
* A PropertyEntry contains information on the name, readAccessor and presenceCheck (for source)
- * and return type of a property.
+ * and return type of property.
*/
public class PropertyEntry {
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java b/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java
index 8824f95901..4e7dad220c 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java
@@ -143,7 +143,7 @@ public SourceReference build() {
* the parameter name to avoid ambiguity
*
* consider: {@code Target map( Source1 source1 )}
- * entries in an @Mapping#source can be "source1.propx" or just "propx" to be valid
+ * entries in a @Mapping#source can be "source1.propx" or just "propx" to be valid
*
* @param segments the segments of @Mapping#source
* @param parameter the one and only parameter
@@ -213,7 +213,7 @@ private SourceReference buildFromMultipleSourceParameters(String[] segments, Par
* needs to match the parameter name to avoid ambiguity
*
* consider: {@code Target map( Source1 source1, Source2 source2 )}
- * entries in an @Mapping#source need to be "source1.propx" or "source2.propy.propz" to be valid
+ * entries in a @Mapping#source need to be "source1.propx" or "source2.propy.propz" to be valid
*
* @param segments the segments of @Mapping#source
* @return parameter that matches with first segment of @Mapping#source
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java
index ce82fff621..6d86aad452 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java
@@ -28,6 +28,7 @@
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
@@ -114,6 +115,7 @@ public class Type extends ModelElement implements Comparable {
private List alternativeTargetAccessors = null;
private Type boundingBase = null;
+ private List boundTypes = null;
private Type boxedEquivalent = null;
@@ -181,9 +183,16 @@ public Type(TypeUtils typeUtils, ElementUtils elementUtils, TypeFactory typeFact
this.loggingVerbose = loggingVerbose;
- // The top level type for an array type is the top level type of the component type
- TypeElement typeElementForTopLevel =
- this.componentType == null ? this.typeElement : this.componentType.getTypeElement();
+ TypeElement typeElementForTopLevel;
+ if ( Boolean.TRUE.equals( isToBeImported ) ) {
+ // If the is to be imported is explicitly set to true then we shouldn't look for the top level type
+ typeElementForTopLevel = null;
+ }
+ else {
+ // The top level type for an array type is the top level type of the component type
+ typeElementForTopLevel =
+ this.componentType == null ? this.typeElement : this.componentType.getTypeElement();
+ }
this.topLevelType = topLevelType( typeElementForTopLevel, this.typeFactory );
this.nameWithTopLevelTypeName = nameWithTopLevelTypeName( typeElementForTopLevel, this.name );
}
@@ -347,6 +356,10 @@ public boolean isTypeVar() {
return (typeMirror.getKind() == TypeKind.TYPEVAR);
}
+ public boolean isIntersection() {
+ return typeMirror.getKind() == TypeKind.INTERSECTION;
+ }
+
public boolean isJavaLangType() {
return packageName != null && packageName.startsWith( "java." );
}
@@ -1257,6 +1270,29 @@ public Type getTypeBound() {
return boundingBase;
}
+ public List getTypeBounds() {
+ if ( this.boundTypes != null ) {
+ return boundTypes;
+ }
+ Type bound = getTypeBound();
+ if ( bound == null ) {
+ this.boundTypes = Collections.emptyList();
+ }
+ else if ( !bound.isIntersection() ) {
+ this.boundTypes = Collections.singletonList( bound );
+ }
+ else {
+ List extends TypeMirror> bounds = ( (IntersectionType) bound.typeMirror ).getBounds();
+ this.boundTypes = new ArrayList<>( bounds.size() );
+ for ( TypeMirror mirror : bounds ) {
+ boundTypes.add( typeFactory.getType( mirror ) );
+ }
+ }
+
+ return this.boundTypes;
+
+ }
+
public boolean hasAccessibleConstructor() {
if ( hasAccessibleConstructor == null ) {
hasAccessibleConstructor = false;
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java
index b209626725..f28e0c687e 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java
@@ -193,7 +193,24 @@ public Type getType(TypeMirror mirror) {
return getType( mirror, false );
}
+ /**
+ * Return a type that is always going to be imported.
+ * This is useful when using it in {@code Mapper#imports}
+ * for types that should be used in expressions.
+ *
+ * @param mirror the type mirror for which we need a type
+ *
+ * @return the type
+ */
+ public Type getAlwaysImportedType(TypeMirror mirror) {
+ return getType( mirror, false, true );
+ }
+
private Type getType(TypeMirror mirror, boolean isLiteral) {
+ return getType( mirror, isLiteral, null );
+ }
+
+ private Type getType(TypeMirror mirror, boolean isLiteral, Boolean alwaysImport) {
if ( !canBeProcessed( mirror ) ) {
throw new TypeHierarchyErroneousException( mirror );
}
@@ -212,7 +229,7 @@ private Type getType(TypeMirror mirror, boolean isLiteral) {
String qualifiedName;
TypeElement typeElement;
Type componentType;
- Boolean toBeImported = null;
+ Boolean toBeImported = alwaysImport;
if ( mirror.getKind() == TypeKind.DECLARED ) {
DeclaredType declaredType = (DeclaredType) mirror;
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java
index cc03878362..e8f19f91f6 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/BeanMappingOptions.java
@@ -34,31 +34,48 @@
public class BeanMappingOptions extends DelegatingOptions {
private final SelectionParameters selectionParameters;
+ private final List ignoreUnmappedSourceProperties;
private final BeanMappingGem beanMapping;
/**
* creates a mapping for inheritance. Will set
*
* @param beanMapping the bean mapping options that should be used
+ * @param isInverse whether the inheritance is inverse
*
* @return new mapping
*/
- public static BeanMappingOptions forInheritance(BeanMappingOptions beanMapping) {
+ public static BeanMappingOptions forInheritance(BeanMappingOptions beanMapping, boolean isInverse) {
BeanMappingOptions options = new BeanMappingOptions(
SelectionParameters.forInheritance( beanMapping.selectionParameters ),
+ isInverse ? Collections.emptyList() : beanMapping.ignoreUnmappedSourceProperties,
beanMapping.beanMapping,
beanMapping
);
return options;
}
+ public static BeanMappingOptions forForgedMethods(BeanMappingOptions beanMapping) {
+ BeanMappingOptions options = new BeanMappingOptions(
+ beanMapping.selectionParameters != null ?
+ SelectionParameters.withoutResultType( beanMapping.selectionParameters ) : null,
+ Collections.emptyList(),
+ beanMapping.beanMapping,
+ beanMapping
+ );
+ return options;
+ }
+
+ public static BeanMappingOptions empty(DelegatingOptions delegatingOptions) {
+ return new BeanMappingOptions( null, Collections.emptyList(), null, delegatingOptions );
+ }
+
public static BeanMappingOptions getInstanceOn(BeanMappingGem beanMapping, MapperOptions mapperOptions,
ExecutableElement method, FormattingMessager messager,
TypeUtils typeUtils, TypeFactory typeFactory
) {
if ( beanMapping == null || !isConsistent( beanMapping, method, messager ) ) {
- BeanMappingOptions options = new BeanMappingOptions( null, null, mapperOptions );
- return options;
+ return empty( mapperOptions );
}
Objects.requireNonNull( method );
@@ -77,6 +94,7 @@ public static BeanMappingOptions getInstanceOn(BeanMappingGem beanMapping, Mappe
//TODO Do we want to add the reporting policy to the BeanMapping as well? To give more granular support?
BeanMappingOptions options = new BeanMappingOptions(
selectionParameters,
+ beanMapping.ignoreUnmappedSourceProperties().get(),
beanMapping,
mapperOptions
);
@@ -86,6 +104,7 @@ public static BeanMappingOptions getInstanceOn(BeanMappingGem beanMapping, Mappe
private static boolean isConsistent(BeanMappingGem gem, ExecutableElement method,
FormattingMessager messager) {
if ( !gem.resultType().hasValue()
+ && !gem.mappingControl().hasValue()
&& !gem.qualifiedBy().hasValue()
&& !gem.qualifiedByName().hasValue()
&& !gem.ignoreUnmappedSourceProperties().hasValue()
@@ -104,10 +123,12 @@ private static boolean isConsistent(BeanMappingGem gem, ExecutableElement method
}
private BeanMappingOptions(SelectionParameters selectionParameters,
+ List ignoreUnmappedSourceProperties,
BeanMappingGem beanMapping,
DelegatingOptions next) {
super( next );
this.selectionParameters = selectionParameters;
+ this.ignoreUnmappedSourceProperties = ignoreUnmappedSourceProperties;
this.beanMapping = beanMapping;
}
@@ -188,9 +209,7 @@ public boolean isignoreByDefault() {
}
public List getIgnoreUnmappedSourceProperties() {
- return Optional.ofNullable( beanMapping ).map( BeanMappingGem::ignoreUnmappedSourceProperties )
- .map( GemValue::get )
- .orElse( Collections.emptyList() );
+ return ignoreUnmappedSourceProperties;
}
public AnnotationMirror getMirror() {
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java
index 4a140c4fb9..2124dd974d 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodOptions.java
@@ -167,7 +167,7 @@ public void applyInheritedOptions(SourceMethod sourceMethod, SourceMethod templa
}
if ( !getBeanMapping().hasAnnotation() && templateOptions.getBeanMapping().hasAnnotation() ) {
- setBeanMapping( BeanMappingOptions.forInheritance( templateOptions.getBeanMapping( ) ) );
+ setBeanMapping( BeanMappingOptions.forInheritance( templateOptions.getBeanMapping( ), isInverse ) );
}
if ( !getEnumMappingOptions().hasAnnotation() && templateOptions.getEnumMappingOptions().hasAnnotation() ) {
@@ -365,7 +365,7 @@ public static MappingMethodOptions getForgedMethodInheritedOptions(MappingMethod
options.mappings,
options.iterableMapping,
options.mapMapping,
- options.beanMapping,
+ BeanMappingOptions.forForgedMethods( options.beanMapping ),
options.enumMappingOptions,
options.valueMappings,
Collections.emptySet(),
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java
index f0d9536799..3d8bfea135 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MethodMatcher.java
@@ -82,6 +82,17 @@ boolean matches(List sourceTypes, Type targetType) {
// (the relation target / target type, target type being a class)
if ( !analyser.candidateReturnType.isVoid() ) {
+ if ( targetType.isPrimitive() ) {
+ // If the target type is primitive
+ // then we are going to check if its boxed equivalent
+ // is assignable to the candidate return type
+ // This is done because primitives can be assigned from their own narrower counterparts
+ // directly without any casting.
+ // e.g. a Long is assignable to a primitive double
+ // However, in order not to lose information we are not going to allow this
+ return targetType.getBoxedEquivalent()
+ .isAssignableTo( analyser.candidateReturnType.getBoxedEquivalent() );
+ }
if ( !( analyser.candidateReturnType.isAssignableTo( targetType ) ) ) {
return false;
}
@@ -314,8 +325,7 @@ else if ( resolved.getParameter().isWildCardBoundByTypeVar()
*/
private boolean candidatesWithinBounds(Map methodParCandidates ) {
for ( Map.Entry entry : methodParCandidates.entrySet() ) {
- Type bound = entry.getKey().getTypeBound();
- if ( bound != null ) {
+ for ( Type bound : entry.getKey().getTypeBounds() ) {
for ( Type.ResolvedPair pair : entry.getValue().pairs ) {
if ( entry.getKey().hasUpperBound() ) {
if ( !pair.getMatch().asRawType().isAssignableTo( bound.asRawType() ) ) {
@@ -374,7 +384,9 @@ else if ( typeFromCandidateMethodTypeParameter.isWildCardBoundByTypeVar()
// something went wrong
return null;
}
- typeArgs[i] = matchingType.getTypeMirror();
+ // Use the boxed equivalent for the type arguments,
+ // because a primitive type cannot be a type argument
+ typeArgs[i] = matchingType.getBoxedEquivalent().getTypeMirror();
}
else {
// it is not a type var (e.g. Map ), String is not a type var
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java
index fb76c13629..7237668e2c 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SelectionParameters.java
@@ -39,6 +39,10 @@ public class SelectionParameters {
* @return the selection parameters based on the given ones
*/
public static SelectionParameters forInheritance(SelectionParameters selectionParameters) {
+ return withoutResultType( selectionParameters );
+ }
+
+ public static SelectionParameters withoutResultType(SelectionParameters selectionParameters) {
return new SelectionParameters(
selectionParameters.qualifiers,
selectionParameters.qualifyingNames,
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java
index 0edae7f10f..6cd1605b23 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMappingMethods.java
@@ -8,6 +8,7 @@
import java.util.ArrayList;
import java.util.List;
+import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.util.JaxbConstants;
import org.mapstruct.ap.internal.util.JodaTimeConstants;
@@ -24,7 +25,7 @@ public class BuiltInMappingMethods {
public BuiltInMappingMethods(TypeFactory typeFactory) {
boolean isXmlGregorianCalendarPresent = isXmlGregorianCalendarAvailable( typeFactory );
- builtInMethods = new ArrayList<>( 20 );
+ builtInMethods = new ArrayList<>( 21 );
if ( isXmlGregorianCalendarPresent ) {
builtInMethods.add( new DateToXmlGregorianCalendar( typeFactory ) );
builtInMethods.add( new XmlGregorianCalendarToDate( typeFactory ) );
@@ -39,8 +40,14 @@ public BuiltInMappingMethods(TypeFactory typeFactory) {
builtInMethods.add( new XmlGregorianCalendarToLocalDateTime( typeFactory ) );
}
- if ( isJaxbAvailable( typeFactory ) ) {
- builtInMethods.add( new JaxbElemToValue( typeFactory ) );
+ if ( isJavaxJaxbAvailable( typeFactory ) ) {
+ Type type = typeFactory.getType( JaxbConstants.JAVAX_JAXB_ELEMENT_FQN );
+ builtInMethods.add( new JaxbElemToValue( type ) );
+ }
+
+ if ( isJakartaJaxbAvailable( typeFactory ) ) {
+ Type type = typeFactory.getType( JaxbConstants.JAKARTA_JAXB_ELEMENT_FQN );
+ builtInMethods.add( new JaxbElemToValue( type ) );
}
builtInMethods.add( new ZonedDateTimeToCalendar( typeFactory ) );
@@ -58,8 +65,12 @@ public BuiltInMappingMethods(TypeFactory typeFactory) {
}
}
- private static boolean isJaxbAvailable(TypeFactory typeFactory) {
- return typeFactory.isTypeAvailable( JaxbConstants.JAXB_ELEMENT_FQN );
+ private static boolean isJavaxJaxbAvailable(TypeFactory typeFactory) {
+ return typeFactory.isTypeAvailable( JaxbConstants.JAVAX_JAXB_ELEMENT_FQN );
+ }
+
+ private static boolean isJakartaJaxbAvailable(TypeFactory typeFactory) {
+ return typeFactory.isTypeAvailable( JaxbConstants.JAKARTA_JAXB_ELEMENT_FQN );
}
private static boolean isXmlGregorianCalendarAvailable(TypeFactory typeFactory) {
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java
index f46b201576..6d41872159 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java
@@ -190,7 +190,7 @@ public boolean equals(Object obj) {
*
* @param parameter source
* @param returnType target
- * @return {@code true}, iff the the type variables match
+ * @return {@code true}, iff the type variables match
*/
public boolean doTypeVarsMatch(Type parameter, Type returnType) {
return true;
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/JaxbElemToValue.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/JaxbElemToValue.java
index 0d3d4c30af..2a5d1639e6 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/JaxbElemToValue.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/JaxbElemToValue.java
@@ -5,26 +5,23 @@
*/
package org.mapstruct.ap.internal.model.source.builtin;
-import static org.mapstruct.ap.internal.util.Collections.asSet;
-
import java.util.Set;
import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.Type;
-import org.mapstruct.ap.internal.model.common.TypeFactory;
-import org.mapstruct.ap.internal.util.JaxbConstants;
+
+import static org.mapstruct.ap.internal.util.Collections.asSet;
/**
* @author Sjaak Derksen
*/
-public class JaxbElemToValue extends BuiltInMethod {
+class JaxbElemToValue extends BuiltInMethod {
private final Parameter parameter;
private final Type returnType;
private final Set importTypes;
- public JaxbElemToValue(TypeFactory typeFactory) {
- Type type = typeFactory.getType( JaxbConstants.JAXB_ELEMENT_FQN );
+ JaxbElemToValue(Type type) {
this.parameter = new Parameter( "element", type );
this.returnType = type.getTypeParameters().get( 0 );
this.importTypes = asSet( parameter.getType() );
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/JakartaXmlElementDeclSelector.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/JakartaXmlElementDeclSelector.java
new file mode 100644
index 0000000000..df5cd848a5
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/JakartaXmlElementDeclSelector.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.internal.model.source.selector;
+
+import javax.lang.model.element.Element;
+
+import org.mapstruct.ap.internal.gem.jakarta.XmlElementDeclGem;
+import org.mapstruct.ap.internal.gem.jakarta.XmlElementRefGem;
+import org.mapstruct.ap.internal.util.TypeUtils;
+
+/**
+ * The concrete implementation of the {@link XmlElementDeclSelector} that
+ * works with {@link jakarta.xml.bind.annotation.XmlElementRef} and
+ * {@link jakarta.xml.bind.annotation.XmlElementDecl}.
+ *
+ * @author Iaroslav Bogdanchikov
+ */
+class JakartaXmlElementDeclSelector extends XmlElementDeclSelector {
+
+ JakartaXmlElementDeclSelector(TypeUtils typeUtils) {
+ super( typeUtils );
+ }
+
+ @Override
+ XmlElementDeclInfo getXmlElementDeclInfo(Element element) {
+ XmlElementDeclGem gem = XmlElementDeclGem.instanceOn( element );
+
+ if (gem == null) {
+ return null;
+ }
+
+ return new XmlElementDeclInfo( gem.name().get(), gem.scope().get() );
+ }
+
+ @Override
+ XmlElementRefInfo getXmlElementRefInfo(Element element) {
+ XmlElementRefGem gem = XmlElementRefGem.instanceOn( element );
+
+ if (gem == null) {
+ return null;
+ }
+
+ return new XmlElementRefInfo( gem.name().get(), gem.type().get() );
+ }
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/JavaxXmlElementDeclSelector.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/JavaxXmlElementDeclSelector.java
new file mode 100644
index 0000000000..1d02e97e90
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/JavaxXmlElementDeclSelector.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.internal.model.source.selector;
+
+import javax.lang.model.element.Element;
+
+import org.mapstruct.ap.internal.gem.XmlElementDeclGem;
+import org.mapstruct.ap.internal.gem.XmlElementRefGem;
+import org.mapstruct.ap.internal.util.TypeUtils;
+
+/**
+ * The concrete implementation of the {@link XmlElementDeclSelector} that
+ * works with {@link javax.xml.bind.annotation.XmlElementRef} and
+ * {@link javax.xml.bind.annotation.XmlElementDecl}.
+ *
+ * @author Iaroslav Bogdanchikov
+ */
+class JavaxXmlElementDeclSelector extends XmlElementDeclSelector {
+
+ JavaxXmlElementDeclSelector(TypeUtils typeUtils) {
+ super( typeUtils );
+ }
+
+ @Override
+ XmlElementDeclInfo getXmlElementDeclInfo(Element element) {
+ XmlElementDeclGem gem = XmlElementDeclGem.instanceOn( element );
+
+ if (gem == null) {
+ return null;
+ }
+
+ return new XmlElementDeclInfo( gem.name().get(), gem.scope().get() );
+ }
+
+ @Override
+ XmlElementRefInfo getXmlElementRefInfo(Element element) {
+ XmlElementRefGem gem = XmlElementRefGem.instanceOn( element );
+
+ if (gem == null) {
+ return null;
+ }
+
+ return new XmlElementRefInfo( gem.name().get(), gem.type().get() );
+ }
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java
index de429174da..519e1c3d6d 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/MethodSelectors.java
@@ -32,7 +32,8 @@ public MethodSelectors(TypeUtils typeUtils, ElementUtils elementUtils, TypeFacto
new TypeSelector( typeFactory, messager ),
new QualifierSelector( typeUtils, elementUtils ),
new TargetTypeSelector( typeUtils ),
- new XmlElementDeclSelector( typeUtils ),
+ new JavaxXmlElementDeclSelector( typeUtils ),
+ new JakartaXmlElementDeclSelector( typeUtils ),
new InheritanceSelector(),
new CreateOrUpdateSelector(),
new SourceRhsSelector(),
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/SelectionCriteria.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/SelectionCriteria.java
index da8bae365a..5a7c11b0d5 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/SelectionCriteria.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/SelectionCriteria.java
@@ -141,6 +141,10 @@ public boolean isAllow2Steps() {
return allow2Steps;
}
+ public boolean isSelfAllowed() {
+ return type != Type.SELF_NOT_ALLOWED;
+ }
+
public static SelectionCriteria forMappingMethods(SelectionParameters selectionParameters,
MappingControl mappingControl,
String targetPropertyName, boolean preferUpdateMapping) {
@@ -165,10 +169,16 @@ public static SelectionCriteria forPresenceCheckMethods(SelectionParameters sele
return new SelectionCriteria( selectionParameters, null, null, Type.PRESENCE_CHECK );
}
+ public static SelectionCriteria forSubclassMappingMethods(SelectionParameters selectionParameters,
+ MappingControl mappingControl) {
+ return new SelectionCriteria( selectionParameters, mappingControl, null, Type.SELF_NOT_ALLOWED );
+ }
+
public enum Type {
PREFER_UPDATE_MAPPING,
OBJECT_FACTORY,
LIFECYCLE_CALLBACK,
PRESENCE_CHECK,
+ SELF_NOT_ALLOWED,
}
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java
index 7bdae0b771..91b4b5ca10 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/selector/XmlElementDeclSelector.java
@@ -11,19 +11,17 @@
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
-import org.mapstruct.ap.internal.util.TypeUtils;
-import org.mapstruct.ap.internal.gem.XmlElementRefGem;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SourceMethod;
-import org.mapstruct.ap.internal.gem.XmlElementDeclGem;
+import org.mapstruct.ap.internal.util.TypeUtils;
/**
- * Finds the {@link javax.xml.bind.annotation.XmlElementRef} annotation on a field (of the mapping result type or its
+ * Finds the {@code XmlElementRef} annotation on a field (of the mapping result type or its
* super types) matching the
* target property name. Then selects those methods with matching {@code name} and {@code scope} attributes of the
- * {@link javax.xml.bind.annotation.XmlElementDecl} annotation, if that is present. Matching happens in the following
+ * {@code XmlElementDecl} annotation, if that is present. Matching happens in the following
* order:
*
*
Name and Scope matches
@@ -34,12 +32,15 @@
* the given method is not annotated with {@code XmlElementDecl} it will be considered as matching.
*
* @author Sjaak Derksen
+ *
+ * @see JavaxXmlElementDeclSelector
+ * @see JakartaXmlElementDeclSelector
*/
-public class XmlElementDeclSelector implements MethodSelector {
+abstract class XmlElementDeclSelector implements MethodSelector {
private final TypeUtils typeUtils;
- public XmlElementDeclSelector(TypeUtils typeUtils) {
+ XmlElementDeclSelector(TypeUtils typeUtils) {
this.typeUtils = typeUtils;
}
@@ -63,15 +64,14 @@ public List> getMatchingMethods(Method mapp
}
SourceMethod candidateMethod = (SourceMethod) candidate.getMethod();
- XmlElementDeclGem xmlElementDecl =
- XmlElementDeclGem.instanceOn( candidateMethod.getExecutable() );
+ XmlElementDeclInfo xmlElementDeclInfo = getXmlElementDeclInfo( candidateMethod.getExecutable() );
- if ( xmlElementDecl == null ) {
+ if ( xmlElementDeclInfo == null ) {
continue;
}
- String name = xmlElementDecl.name().get();
- TypeMirror scope = xmlElementDecl.scope().getValue();
+ String name = xmlElementDeclInfo.nameValue();
+ TypeMirror scope = xmlElementDeclInfo.scopeType();
boolean nameIsSetAndMatches = name != null && name.equals( xmlElementRefInfo.nameValue() );
boolean scopeIsSetAndMatches =
@@ -142,9 +142,9 @@ private XmlElementRefInfo findXmlElementRef(Type resultType, String targetProper
for ( Element enclosed : currentElement.getEnclosedElements() ) {
if ( enclosed.getKind().equals( ElementKind.FIELD )
&& enclosed.getSimpleName().contentEquals( targetPropertyName ) ) {
- XmlElementRefGem xmlElementRef = XmlElementRefGem.instanceOn( enclosed );
- if ( xmlElementRef != null ) {
- return new XmlElementRefInfo( xmlElementRef.name().get(), currentMirror );
+ XmlElementRefInfo xmlElementRefInfo = getXmlElementRefInfo( enclosed );
+ if ( xmlElementRefInfo != null ) {
+ return new XmlElementRefInfo( xmlElementRefInfo.nameValue(), currentMirror );
}
}
}
@@ -154,7 +154,11 @@ private XmlElementRefInfo findXmlElementRef(Type resultType, String targetProper
return defaultInfo;
}
- private static class XmlElementRefInfo {
+ abstract XmlElementDeclInfo getXmlElementDeclInfo(Element element);
+
+ abstract XmlElementRefInfo getXmlElementRefInfo(Element element);
+
+ static class XmlElementRefInfo {
private final String nameValue;
private final TypeMirror sourceType;
@@ -163,12 +167,37 @@ private static class XmlElementRefInfo {
this.sourceType = sourceType;
}
- public String nameValue() {
+ String nameValue() {
return nameValue;
}
- public TypeMirror sourceType() {
+ TypeMirror sourceType() {
return sourceType;
}
}
+
+ /**
+ * A class, whose purpose is to combine the use of
+ * {@link org.mapstruct.ap.internal.gem.XmlElementDeclGem}
+ * and
+ * {@link org.mapstruct.ap.internal.gem.jakarta.XmlElementDeclGem}.
+ */
+ static class XmlElementDeclInfo {
+
+ private final String nameValue;
+ private final TypeMirror scopeType;
+
+ XmlElementDeclInfo(String nameValue, TypeMirror scopeType) {
+ this.nameValue = nameValue;
+ this.scopeType = scopeType;
+ }
+
+ String nameValue() {
+ return nameValue;
+ }
+
+ TypeMirror scopeType() {
+ return scopeType;
+ }
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/CdiComponentProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/CdiComponentProcessor.java
index 74ff2b118b..d8f136034b 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/processor/CdiComponentProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/CdiComponentProcessor.java
@@ -12,6 +12,8 @@
import org.mapstruct.ap.internal.gem.MappingConstantsGem;
import org.mapstruct.ap.internal.model.Annotation;
import org.mapstruct.ap.internal.model.Mapper;
+import org.mapstruct.ap.internal.model.common.Type;
+import org.mapstruct.ap.internal.util.AnnotationProcessingException;
/**
* A {@link ModelElementProcessor} which converts the given {@link Mapper}
@@ -30,13 +32,13 @@ protected String getComponentModelIdentifier() {
@Override
protected List getTypeAnnotations(Mapper mapper) {
return Collections.singletonList(
- new Annotation( getTypeFactory().getType( "javax.enterprise.context.ApplicationScoped" ) )
+ new Annotation( getType( "ApplicationScoped" ) )
);
}
@Override
protected List getMapperReferenceAnnotations() {
- return Arrays.asList( new Annotation( getTypeFactory().getType( "javax.inject.Inject" ) ) );
+ return Arrays.asList( new Annotation( getType( "Inject" ) ) );
}
@Override
@@ -48,4 +50,24 @@ protected boolean requiresGenerationOfDecoratorClass() {
protected boolean additionalPublicEmptyConstructor() {
return true;
}
+
+ private Type getType(String simpleName) {
+ String javaxPrefix = "javax.inject.";
+ String jakartaPrefix = "jakarta.inject.";
+ if ( "ApplicationScoped".equals( simpleName ) ) {
+ javaxPrefix = "javax.enterprise.context.";
+ jakartaPrefix = "jakarta.enterprise.context.";
+ }
+ if ( getTypeFactory().isTypeAvailable( javaxPrefix + simpleName ) ) {
+ return getTypeFactory().getType( javaxPrefix + simpleName );
+ }
+
+ if ( getTypeFactory().isTypeAvailable( jakartaPrefix + simpleName ) ) {
+ return getTypeFactory().getType( jakartaPrefix + simpleName );
+ }
+
+ throw new AnnotationProcessingException(
+ "Couldn't find any of the CDI or Jakarta CDI Dependency types." +
+ " Are you missing a dependency on your classpath?" );
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/JakartaCdiComponentProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/JakartaCdiComponentProcessor.java
new file mode 100644
index 0000000000..11c765668e
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/JakartaCdiComponentProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.internal.processor;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.mapstruct.ap.internal.gem.MappingConstantsGem;
+import org.mapstruct.ap.internal.model.Annotation;
+import org.mapstruct.ap.internal.model.Mapper;
+
+/**
+ * A {@link ModelElementProcessor} which converts the given {@link Mapper}
+ * object into an application-scoped Jakarta CDI bean in case Jakarta CDI
+ * is configured as the target component model for this mapper.
+ *
+ * @author Filip Hrisafov
+ */
+public class JakartaCdiComponentProcessor extends AnnotationBasedComponentModelProcessor {
+
+ @Override
+ protected String getComponentModelIdentifier() {
+ return MappingConstantsGem.ComponentModelGem.JAKARTA_CDI;
+ }
+
+ @Override
+ protected List getTypeAnnotations(Mapper mapper) {
+ return Collections.singletonList(
+ new Annotation( getTypeFactory().getType( "jakarta.enterprise.context.ApplicationScoped" ) )
+ );
+ }
+
+ @Override
+ protected List getMapperReferenceAnnotations() {
+ return Arrays.asList( new Annotation( getTypeFactory().getType( "jakarta.inject.Inject" ) ) );
+ }
+
+ @Override
+ protected boolean requiresGenerationOfDecoratorClass() {
+ return false;
+ }
+
+ @Override
+ protected boolean additionalPublicEmptyConstructor() {
+ return true;
+ }
+
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java
index d8acb10398..579c0d3f77 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/MapperCreationProcessor.java
@@ -301,7 +301,7 @@ private SortedSet getExtraImports(TypeElement element, MapperOptions mapp
for ( TypeMirror extraImport : mapperOptions.imports() ) {
- Type type = typeFactory.getType( extraImport );
+ Type type = typeFactory.getAlwaysImportedType( extraImport );
extraImports.add( type );
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java
index 2e2a760bf4..12b345d238 100755
--- a/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/creation/MappingResolverImpl.java
@@ -196,7 +196,6 @@ private ResolvingAttempt(List sourceModel, Method mappingMethod, ForgedM
this.mappingMethod = mappingMethod;
this.description = description;
- this.methods = filterPossibleCandidateMethods( sourceModel );
this.formattingParameters =
formattingParameters == null ? FormattingParameters.EMPTY : formattingParameters;
this.sourceRHS = sourceRHS;
@@ -207,13 +206,14 @@ private ResolvingAttempt(List sourceModel, Method mappingMethod, ForgedM
this.builtIns = builtIns;
this.messager = messager;
this.reportingLimitAmbiguous = verboseLogging ? Integer.MAX_VALUE : LIMIT_REPORTING_AMBIGUOUS;
+ this.methods = filterPossibleCandidateMethods( sourceModel, mappingMethod );
}
// CHECKSTYLE:ON
- private List filterPossibleCandidateMethods(List candidateMethods) {
+ private List filterPossibleCandidateMethods(List candidateMethods, T mappingMethod) {
List result = new ArrayList<>( candidateMethods.size() );
for ( T candidate : candidateMethods ) {
- if ( isCandidateForMapping( candidate ) ) {
+ if ( isCandidateForMapping( candidate ) && isNotSelfOrSelfAllowed( mappingMethod, candidate )) {
result.add( candidate );
}
}
@@ -221,6 +221,10 @@ private List filterPossibleCandidateMethods(List candid
return result;
}
+ private boolean isNotSelfOrSelfAllowed(T mappingMethod, T candidate) {
+ return selectionCriteria == null || selectionCriteria.isSelfAllowed() || !candidate.equals( mappingMethod );
+ }
+
private Assignment getTargetAssignment(Type sourceType, Type targetType) {
Assignment assignment;
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/JaxbConstants.java b/processor/src/main/java/org/mapstruct/ap/internal/util/JaxbConstants.java
index db18673ba2..c89877062e 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/util/JaxbConstants.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/util/JaxbConstants.java
@@ -10,7 +10,8 @@
*/
public final class JaxbConstants {
- public static final String JAXB_ELEMENT_FQN = "javax.xml.bind.JAXBElement";
+ public static final String JAVAX_JAXB_ELEMENT_FQN = "javax.xml.bind.JAXBElement";
+ public static final String JAKARTA_JAXB_ELEMENT_FQN = "jakarta.xml.bind.JAXBElement";
private JaxbConstants() {
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java
index 4e1c0302fa..0b1d7ae40b 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java
@@ -159,7 +159,7 @@ public enum Message {
RETRIEVAL_NO_INPUT_ARGS( "Can't generate mapping method with no input arguments." ),
RETRIEVAL_DUPLICATE_MAPPING_TARGETS( "Can't generate mapping method with more than one @MappingTarget parameter." ),
RETRIEVAL_VOID_MAPPING_METHOD( "Can't generate mapping method with return type void." ),
- RETRIEVAL_NON_ASSIGNABLE_RESULTTYPE( "The result type is not assignable to the the return type." ),
+ RETRIEVAL_NON_ASSIGNABLE_RESULTTYPE( "The result type is not assignable to the return type." ),
RETRIEVAL_ITERABLE_TO_NON_ITERABLE( "Can't generate mapping method from iterable type from java stdlib to non-iterable type." ),
RETRIEVAL_MAPPING_HAS_TARGET_TYPE_PARAMETER( "Can't generate mapping method that has a parameter annotated with @TargetType." ),
RETRIEVAL_NON_ITERABLE_TO_ITERABLE( "Can't generate mapping method from non-iterable type to iterable type from java stdlib." ),
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/RoundContext.java b/processor/src/main/java/org/mapstruct/ap/internal/util/RoundContext.java
index 78e61fbf29..e34d013bc5 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/util/RoundContext.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/util/RoundContext.java
@@ -41,7 +41,7 @@ public void addTypeReadyForProcessing(TypeMirror type) {
/**
* Whether the given type has been found to be ready for further processing or not. This is the case if the type's
- * hierarchy is complete (no super-types need to be generated by other processors) an no processors have signaled
+ * hierarchy is complete (no super-types need to be generated by other processors) and no processors have signaled
* the intention to amend the given type.
*
* @param type the typed to be checked for its readiness
diff --git a/processor/src/main/java/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java b/processor/src/main/java/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java
index 8ac41395bf..6b9e079523 100644
--- a/processor/src/main/java/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java
@@ -15,7 +15,7 @@
*