diff --git a/core/src/main/java/org/mapstruct/DecoratedWith.java b/core/src/main/java/org/mapstruct/DecoratedWith.java index 8a644f4b2..b4ca05f3d 100644 --- a/core/src/main/java/org/mapstruct/DecoratedWith.java +++ b/core/src/main/java/org/mapstruct/DecoratedWith.java @@ -103,12 +103,12 @@ import java.lang.annotation.Target; * private PersonMapper personMapper; // injects the decorator, with the injected original mapper * * - *

3. Component model 'jsr330'

+ *

3. Component model 'jsr330' or 'jakarta'

*

Referencing the original mapper

*

- * JSR 330 doesn't specify qualifiers and only allows to specifically name the beans. Hence, the generated - * implementation of the original mapper is annotated with - * {@code @javax.inject.Named("fully-qualified-name-of-generated-impl")} and {@code @Singleton} (please note that when + * JSR 330 / Jakarta Inject doesn't specify qualifiers and only allows to specifically name the beans. Hence, + * the generated implementation of the original mapper is annotated with + * {@code @Named("fully-qualified-name-of-generated-impl")} and {@code @Singleton} (please note that when * using a decorator, the class name of the mapper implementation ends with an underscore). To inject that bean in your * decorator, add the same annotation to the delegate field (e.g. by copy/pasting it from the generated class): * diff --git a/core/src/main/java/org/mapstruct/InjectionStrategy.java b/core/src/main/java/org/mapstruct/InjectionStrategy.java index 84baa8afa..b84166767 100644 --- a/core/src/main/java/org/mapstruct/InjectionStrategy.java +++ b/core/src/main/java/org/mapstruct/InjectionStrategy.java @@ -7,7 +7,7 @@ package org.mapstruct; /** * Strategy for handling injection. This is only used on annotated based component models such as CDI, Spring and - * JSR330. + * JSR330 / Jakarta. * * @author Kevin Grüneberg */ diff --git a/core/src/main/java/org/mapstruct/Mapper.java b/core/src/main/java/org/mapstruct/Mapper.java index c5aed661f..0436c0cf6 100644 --- a/core/src/main/java/org/mapstruct/Mapper.java +++ b/core/src/main/java/org/mapstruct/Mapper.java @@ -142,7 +142,12 @@ public @interface Mapper { * can be retrieved via {@code @Autowired} *

  • * {@code jsr330}: the generated mapper is annotated with {@code @javax.inject.Named} and - * {@code @Singleton}, and can be retrieved via {@code @Inject}
  • + * {@code @Singleton}, and can be retrieved via {@code @Inject}. + * The annotations will either be from javax.inject or jakarta.inject, + * depending on which one is available, with javax.inject having precedence. + *
  • + * {@code jakarta}: the generated mapper is annotated with {@code @jakarta.inject.Named} and + * {@code @Singleton}, and can be retrieved via {@code @Inject}.
  • * * The method overrides a componentModel set in a central configuration set * by {@link #config() } diff --git a/core/src/main/java/org/mapstruct/MapperConfig.java b/core/src/main/java/org/mapstruct/MapperConfig.java index 757a4ab0a..893801cda 100644 --- a/core/src/main/java/org/mapstruct/MapperConfig.java +++ b/core/src/main/java/org/mapstruct/MapperConfig.java @@ -131,7 +131,12 @@ public @interface MapperConfig { * can be retrieved via {@code @Autowired} *
  • * {@code jsr330}: the generated mapper is annotated with {@code @javax.inject.Named} and - * {@code @Singleton}, and can be retrieved via {@code @Inject}
  • + * {@code @Singleton}, and can be retrieved via {@code @Inject}. + * The annotations will either be from javax.inject or jakarta.inject, + * depending on which one is available, with javax.inject having precedence. + *
  • + * {@code jakarta}: the generated mapper is annotated with {@code @jakarta.inject.Named} and + * {@code @Singleton}, and can be retrieved via {@code @Inject}.
  • * * * @return The component model for the generated mapper. diff --git a/core/src/main/java/org/mapstruct/MappingConstants.java b/core/src/main/java/org/mapstruct/MappingConstants.java index 002f00529..ce2438298 100644 --- a/core/src/main/java/org/mapstruct/MappingConstants.java +++ b/core/src/main/java/org/mapstruct/MappingConstants.java @@ -120,11 +120,24 @@ public final class MappingConstants { public static final String SPRING = "spring"; /** - * The generated mapper is annotated with @javax.inject.Named and @Singleton, and can be retrieved via @Inject + * The generated mapper is annotated with @Named and @Singleton, and can be retrieved via @Inject. + * The annotations are either from {@code javax.inject} or {@code jakarta.inject}. + * Priority have the {@code javax.inject} annotations. + * In case you want to only use Jakarta then use {@link #JAKARTA}. * + * @see #JAKARTA */ public static final String JSR330 = "jsr330"; + /** + * The generated mapper is annotated with @Named and @Singleton, and can be retrieved via @Inject. + * The annotations are from {@code jakarta.inject}. + * In case you want to use {@code javax.inject} then use {@link #JSR330}. + * + * @see #JSR330 + */ + public static final String JAKARTA = "jakarta"; + } } diff --git a/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc b/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc index 54906f789..d95983e84 100644 --- a/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc +++ b/documentation/src/main/asciidoc/chapter-2-set-up.asciidoc @@ -217,7 +217,8 @@ 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` * `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`, e.g. using Spring +* `jsr330`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from javax.inject or jakarta.inject, depending which one is available with javax.inject having priority), e.g. using Spring +* `jakarta`: the generated mapper is annotated with {@code @Named} and can be retrieved via `@Inject` (from jakarta.inject), e.g. using Spring If a component model is given for a specific mapper via `@Mapper#componentModel()`, the value from the annotation takes precedence. |`default` diff --git a/integrationtest/src/test/resources/fullFeatureTest/pom.xml b/integrationtest/src/test/resources/fullFeatureTest/pom.xml index ebf4590d3..ec26f45ce 100644 --- a/integrationtest/src/test/resources/fullFeatureTest/pom.xml +++ b/integrationtest/src/test/resources/fullFeatureTest/pom.xml @@ -60,6 +60,10 @@ javax.inject javax.inject + + jakarta.inject + jakarta.inject-api + diff --git a/parent/pom.xml b/parent/pom.xml index 21413dcef..1f75e9d6d 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -159,6 +159,11 @@ javax.inject 1 + + jakarta.inject + jakarta.inject-api + 2.0.1 + org.jboss.arquillian arquillian-bom diff --git a/processor/pom.xml b/processor/pom.xml index 4f2476ceb..2a3c38abf 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -83,6 +83,11 @@ javax.inject test + + jakarta.inject + jakarta.inject-api + test + 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 b49b9d17e..cb6d49c0c 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 @@ -49,6 +49,8 @@ public final class MappingConstantsGem { public static final String SPRING = "spring"; public static final String JSR330 = "jsr330"; + + public static final String JAKARTA = "jakarta"; } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/JakartaComponentProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/JakartaComponentProcessor.java new file mode 100644 index 000000000..5161ea689 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/JakartaComponentProcessor.java @@ -0,0 +1,78 @@ +/* + * 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 a Jakarta Inject style bean in case "jakarta" is configured as the + * target component model for this mapper. + * + * @author Filip Hrisafov + */ +public class JakartaComponentProcessor extends AnnotationBasedComponentModelProcessor { + @Override + protected String getComponentModelIdentifier() { + return MappingConstantsGem.ComponentModelGem.JAKARTA; + } + + @Override + protected List getTypeAnnotations(Mapper mapper) { + if ( mapper.getDecorator() == null ) { + return Arrays.asList( singleton(), named() ); + } + else { + return Arrays.asList( singleton(), namedDelegate( mapper ) ); + } + } + + @Override + protected List getDecoratorAnnotations() { + return Arrays.asList( singleton(), named() ); + } + + @Override + protected List getDelegatorReferenceAnnotations(Mapper mapper) { + return Arrays.asList( inject(), namedDelegate( mapper ) ); + } + + @Override + protected List getMapperReferenceAnnotations() { + return Collections.singletonList( inject() ); + } + + @Override + protected boolean requiresGenerationOfDecoratorClass() { + return true; + } + + private Annotation singleton() { + return new Annotation( getTypeFactory().getType( "jakarta.inject.Singleton" ) ); + } + + private Annotation named() { + return new Annotation( getTypeFactory().getType( "jakarta.inject.Named" ) ); + } + + private Annotation namedDelegate(Mapper mapper) { + return new Annotation( + getTypeFactory().getType( "jakarta.inject.Named" ), + Collections.singletonList( '"' + mapper.getPackageName() + "." + mapper.getName() + '"' ) + ); + } + + private Annotation inject() { + return new Annotation( getTypeFactory().getType( "jakarta.inject.Inject" ) ); + } + +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/processor/Jsr330ComponentProcessor.java b/processor/src/main/java/org/mapstruct/ap/internal/processor/Jsr330ComponentProcessor.java index 18a6e4f69..6a6cc1658 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/processor/Jsr330ComponentProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/processor/Jsr330ComponentProcessor.java @@ -12,6 +12,8 @@ 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; +import org.mapstruct.ap.internal.model.common.Type; +import org.mapstruct.ap.internal.util.AnnotationProcessingException; /** * A {@link ModelElementProcessor} which converts the given {@link Mapper} @@ -58,21 +60,35 @@ public class Jsr330ComponentProcessor extends AnnotationBasedComponentModelProce } private Annotation singleton() { - return new Annotation( getTypeFactory().getType( "javax.inject.Singleton" ) ); + return new Annotation( getType( "Singleton" ) ); } private Annotation named() { - return new Annotation( getTypeFactory().getType( "javax.inject.Named" ) ); + return new Annotation( getType( "Named" ) ); } private Annotation namedDelegate(Mapper mapper) { return new Annotation( - getTypeFactory().getType( "javax.inject.Named" ), + getType( "Named" ), Collections.singletonList( '"' + mapper.getPackageName() + "." + mapper.getName() + '"' ) ); } private Annotation inject() { - return new Annotation( getTypeFactory().getType( "javax.inject.Inject" ) ); + return new Annotation( getType( "Inject" ) ); + } + + private Type getType(String simpleName) { + if ( getTypeFactory().isTypeAvailable( "javax.inject." + simpleName ) ) { + return getTypeFactory().getType( "javax.inject." + simpleName ); + } + + if ( getTypeFactory().isTypeAvailable( "jakarta.inject." + simpleName ) ) { + return getTypeFactory().getType( "jakarta.inject." + simpleName ); + } + + throw new AnnotationProcessingException( + "Couldn't find any of the JSR330 or Jakarta Dependency Inject types." + + " Are you missing a dependency on your classpath?" ); } } diff --git a/processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor b/processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor index 7b27e54fa..cab1d83ed 100644 --- a/processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor +++ b/processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor @@ -4,6 +4,7 @@ org.mapstruct.ap.internal.processor.CdiComponentProcessor org.mapstruct.ap.internal.processor.Jsr330ComponentProcessor +org.mapstruct.ap.internal.processor.JakartaComponentProcessor org.mapstruct.ap.internal.processor.MapperCreationProcessor org.mapstruct.ap.internal.processor.MapperRenderingProcessor org.mapstruct.ap.internal.processor.MethodRetrievalProcessor diff --git a/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/JakartaJsr330DecoratorTest.java b/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/JakartaJsr330DecoratorTest.java new file mode 100644 index 000000000..2e0dfcec0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/JakartaJsr330DecoratorTest.java @@ -0,0 +1,55 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.decorator.jakarta.jsr330; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.decorator.Address; +import org.mapstruct.ap.test.decorator.AddressDto; +import org.mapstruct.ap.test.decorator.Person; +import org.mapstruct.ap.test.decorator.PersonDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +@WithClasses({ + Person.class, + PersonDto.class, + Address.class, + AddressDto.class, + PersonMapper.class, + PersonMapperDecorator.class +}) +@IssueKey("2567") +@WithJakartaInject +// We can't use Spring for testing since Spring 5 does not support Jakarta Inject +// However, we can test the generated source code +public class JakartaJsr330DecoratorTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void hasCorrectImports() { + // check the decorator + generatedSource.forMapper( PersonMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "@Singleton" + lineSeparator() + "@Named" ) + .doesNotContain( "javax.inject" ); + // check the plain mapper + generatedSource.forDecoratedMapper( PersonMapper.class ).content() + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "@Singleton" + lineSeparator() + "@Named" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/PersonMapper.java b/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/PersonMapper.java new file mode 100644 index 000000000..74ef38439 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/PersonMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.decorator.jakarta.jsr330; + +import org.mapstruct.DecoratedWith; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingConstants; +import org.mapstruct.ap.test.decorator.Address; +import org.mapstruct.ap.test.decorator.AddressDto; +import org.mapstruct.ap.test.decorator.Person; +import org.mapstruct.ap.test.decorator.PersonDto; + +@Mapper(componentModel = MappingConstants.ComponentModel.JSR330) +@DecoratedWith(PersonMapperDecorator.class) +public interface PersonMapper { + + @Mapping( target = "name", ignore = true ) + PersonDto personToPersonDto(Person person); + + AddressDto addressToAddressDto(Address address); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/PersonMapperDecorator.java b/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/PersonMapperDecorator.java new file mode 100644 index 000000000..f16a9f8c1 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/decorator/jakarta/jsr330/PersonMapperDecorator.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.ap.test.decorator.jakarta.jsr330; + +import jakarta.inject.Inject; +import jakarta.inject.Named; + +import org.mapstruct.ap.test.decorator.Person; +import org.mapstruct.ap.test.decorator.PersonDto; + +public abstract class PersonMapperDecorator implements PersonMapper { + + @Inject + @Named("org.mapstruct.ap.test.decorator.jakarta.jsr330.PersonMapperImpl_") + private PersonMapper delegate; + + @Override + public PersonDto personToPersonDto(Person person) { + PersonDto dto = delegate.personToPersonDto( person ); + dto.setName( person.getFirstName() + " " + person.getLastName() ); + + return dto; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/gem/ConstantTest.java b/processor/src/test/java/org/mapstruct/ap/test/gem/ConstantTest.java index e3a5b7c26..548ee61f2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/gem/ConstantTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/gem/ConstantTest.java @@ -40,5 +40,7 @@ public class ConstantTest { assertThat( MappingConstants.ComponentModel.CDI ).isEqualTo( MappingConstantsGem.ComponentModelGem.CDI ); assertThat( MappingConstants.ComponentModel.SPRING ).isEqualTo( MappingConstantsGem.ComponentModelGem.SPRING ); assertThat( MappingConstants.ComponentModel.JSR330 ).isEqualTo( MappingConstantsGem.ComponentModelGem.JSR330 ); + assertThat( MappingConstants.ComponentModel.JAKARTA ) + .isEqualTo( MappingConstantsGem.ComponentModelGem.JAKARTA ); } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/CustomerJakartaDefaultCompileOptionFieldMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/CustomerJakartaDefaultCompileOptionFieldMapper.java new file mode 100644 index 000000000..2fb6ae0d0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/CustomerJakartaDefaultCompileOptionFieldMapper.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta._default; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; + +/** + * @author Filip Hrisafov + */ +@Mapper(componentModel = MappingConstants.ComponentModel.JAKARTA, + uses = GenderJakartaDefaultCompileOptionFieldMapper.class) +public interface CustomerJakartaDefaultCompileOptionFieldMapper { + + CustomerDto asTarget(CustomerEntity customerEntity); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/GenderJakartaDefaultCompileOptionFieldMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/GenderJakartaDefaultCompileOptionFieldMapper.java new file mode 100644 index 000000000..da3409ef4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/GenderJakartaDefaultCompileOptionFieldMapper.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.test.injectionstrategy.jakarta._default; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ValueMapping; +import org.mapstruct.ValueMappings; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; + +/** + * @author Filip Hrisafov + */ +@Mapper(componentModel = MappingConstants.ComponentModel.JAKARTA) +public interface GenderJakartaDefaultCompileOptionFieldMapper { + + @ValueMappings({ + @ValueMapping(source = "MALE", target = "M"), + @ValueMapping(source = "FEMALE", target = "F") + }) + GenderDto mapToDto(Gender gender); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/JakartaAndJsr330DefaultCompileOptionFieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/JakartaAndJsr330DefaultCompileOptionFieldMapperTest.java new file mode 100644 index 000000000..c647605e6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/JakartaAndJsr330DefaultCompileOptionFieldMapperTest.java @@ -0,0 +1,55 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta._default; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.WithJavaxInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * Test field injection for component model jakarta. + * Default value option mapstruct.defaultInjectionStrategy is "field" + * + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJakartaDefaultCompileOptionFieldMapper.class, + GenderJakartaDefaultCompileOptionFieldMapper.class +}) +@WithJakartaInject +@WithJavaxInject +public class JakartaAndJsr330DefaultCompileOptionFieldMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerJakartaDefaultCompileOptionFieldMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "@Inject" + lineSeparator() + " private GenderJakartaDefaultCompileOptionFieldMapper" ) + .doesNotContain( "public CustomerJakartaDefaultCompileOptionFieldMapperImpl(" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/JakartaDefaultCompileOptionFieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/JakartaDefaultCompileOptionFieldMapperTest.java new file mode 100644 index 000000000..01b43c5b4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/_default/JakartaDefaultCompileOptionFieldMapperTest.java @@ -0,0 +1,53 @@ +/* + * 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.test.injectionstrategy.jakarta._default; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * Test field injection for component model jakarta. + * Default value option mapstruct.defaultInjectionStrategy is "field" + * + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJakartaDefaultCompileOptionFieldMapper.class, + GenderJakartaDefaultCompileOptionFieldMapper.class +}) +@WithJakartaInject +public class JakartaDefaultCompileOptionFieldMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerJakartaDefaultCompileOptionFieldMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "@Inject" + lineSeparator() + " private GenderJakartaDefaultCompileOptionFieldMapper" ) + .doesNotContain( "public CustomerJakartaDefaultCompileOptionFieldMapperImpl(" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/CustomerJakartaCompileOptionConstructorMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/CustomerJakartaCompileOptionConstructorMapper.java new file mode 100644 index 000000000..9775d05c8 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/CustomerJakartaCompileOptionConstructorMapper.java @@ -0,0 +1,24 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.compileoptionconstructor; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingConstants; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; + +/** + * @author Filip Hrisafov + */ +@Mapper( componentModel = MappingConstants.ComponentModel.JAKARTA, + uses = GenderJakartaCompileOptionConstructorMapper.class ) +public interface CustomerJakartaCompileOptionConstructorMapper { + + @Mapping(target = "gender", source = "gender") + CustomerDto asTarget(CustomerEntity customerEntity); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/GenderJakartaCompileOptionConstructorMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/GenderJakartaCompileOptionConstructorMapper.java new file mode 100644 index 000000000..4539bb1c6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/GenderJakartaCompileOptionConstructorMapper.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.test.injectionstrategy.jakarta.compileoptionconstructor; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ValueMapping; +import org.mapstruct.ValueMappings; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; + +/** + * @author Filip Hrisafov + */ +@Mapper(componentModel = MappingConstants.ComponentModel.JAKARTA) +public interface GenderJakartaCompileOptionConstructorMapper { + + @ValueMappings({ + @ValueMapping(source = "MALE", target = "M"), + @ValueMapping(source = "FEMALE", target = "F") + }) + GenderDto mapToDto(Gender gender); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/JakartaAndJsr330CompileOptionConstructorMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/JakartaAndJsr330CompileOptionConstructorMapperTest.java new file mode 100644 index 000000000..c897891b1 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/JakartaAndJsr330CompileOptionConstructorMapperTest.java @@ -0,0 +1,59 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.compileoptionconstructor; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.WithJavaxInject; +import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * Test constructor injection for component model jakarta with compile option + * mapstruct.defaultInjectionStrategy=constructor + * + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJakartaCompileOptionConstructorMapper.class, + GenderJakartaCompileOptionConstructorMapper.class +}) +@ProcessorOption(name = "mapstruct.defaultInjectionStrategy", value = "constructor") +@WithJakartaInject +@WithJavaxInject +public class JakartaAndJsr330CompileOptionConstructorMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerJakartaCompileOptionConstructorMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "private final GenderJakartaCompileOptionConstructorMapper" ) + .contains( "@Inject" + lineSeparator() + + " public CustomerJakartaCompileOptionConstructorMapperImpl" + + "(GenderJakartaCompileOptionConstructorMapper" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/JakartaCompileOptionConstructorMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/JakartaCompileOptionConstructorMapperTest.java new file mode 100644 index 000000000..cc36591bb --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/compileoptionconstructor/JakartaCompileOptionConstructorMapperTest.java @@ -0,0 +1,57 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.compileoptionconstructor; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * Test constructor injection for component model jakarta with compile option + * mapstruct.defaultInjectionStrategy=constructor + * + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJakartaCompileOptionConstructorMapper.class, + GenderJakartaCompileOptionConstructorMapper.class +}) +@ProcessorOption(name = "mapstruct.defaultInjectionStrategy", value = "constructor") +@WithJakartaInject +public class JakartaCompileOptionConstructorMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerJakartaCompileOptionConstructorMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "private final GenderJakartaCompileOptionConstructorMapper" ) + .contains( "@Inject" + lineSeparator() + + " public CustomerJakartaCompileOptionConstructorMapperImpl" + + "(GenderJakartaCompileOptionConstructorMapper" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/ConstructorJakartaConfig.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/ConstructorJakartaConfig.java new file mode 100644 index 000000000..0bc9bb16e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/ConstructorJakartaConfig.java @@ -0,0 +1,18 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.constructor; + +import org.mapstruct.InjectionStrategy; +import org.mapstruct.MapperConfig; +import org.mapstruct.MappingConstants; + +/** + * @author Filip Hrisafov + */ +@MapperConfig(componentModel = MappingConstants.ComponentModel.JAKARTA, + injectionStrategy = InjectionStrategy.CONSTRUCTOR) +public interface ConstructorJakartaConfig { +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/CustomerJakartaConstructorMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/CustomerJakartaConstructorMapper.java new file mode 100644 index 000000000..73d201cbf --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/CustomerJakartaConstructorMapper.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.test.injectionstrategy.jakarta.constructor; + +import org.mapstruct.InjectionStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingConstants; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; + +/** + * @author Filip Hrisafov + */ +@Mapper( componentModel = MappingConstants.ComponentModel.JAKARTA, + uses = GenderJakartaConstructorMapper.class, + injectionStrategy = InjectionStrategy.CONSTRUCTOR ) +public interface CustomerJakartaConstructorMapper { + + @Mapping(target = "gender", source = "gender") + CustomerDto asTarget(CustomerEntity customerEntity); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/GenderJakartaConstructorMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/GenderJakartaConstructorMapper.java new file mode 100644 index 000000000..7cbd0bb3d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/GenderJakartaConstructorMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.constructor; + +import org.mapstruct.Mapper; +import org.mapstruct.ValueMapping; +import org.mapstruct.ValueMappings; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; + +/** + * @author Filip Hrisafov + */ +@Mapper(config = ConstructorJakartaConfig.class) +public interface GenderJakartaConstructorMapper { + + @ValueMappings({ + @ValueMapping(source = "MALE", target = "M"), + @ValueMapping(source = "FEMALE", target = "F") + }) + GenderDto mapToDto(Gender gender); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/JakartaAndJsr330ConstructorMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/JakartaAndJsr330ConstructorMapperTest.java new file mode 100644 index 000000000..03b5dcf2b --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/JakartaAndJsr330ConstructorMapperTest.java @@ -0,0 +1,58 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.constructor; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.WithJavaxInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import static java.lang.System.lineSeparator; + +/** + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJakartaConstructorMapper.class, + GenderJakartaConstructorMapper.class, + ConstructorJakartaConfig.class +}) +@ComponentScan(basePackageClasses = CustomerJakartaConstructorMapper.class) +@Configuration +@WithJakartaInject +@WithJavaxInject +public class JakartaAndJsr330ConstructorMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerJakartaConstructorMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "private final GenderJakartaConstructorMapper" ) + .contains( "@Inject" + lineSeparator() + + " public CustomerJakartaConstructorMapperImpl(GenderJakartaConstructorMapper" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/JakartaConstructorMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/JakartaConstructorMapperTest.java new file mode 100644 index 000000000..45ea7efca --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/constructor/JakartaConstructorMapperTest.java @@ -0,0 +1,56 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.constructor; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import static java.lang.System.lineSeparator; + +/** + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJakartaConstructorMapper.class, + GenderJakartaConstructorMapper.class, + ConstructorJakartaConfig.class +}) +@ComponentScan(basePackageClasses = CustomerJakartaConstructorMapper.class) +@Configuration +@WithJakartaInject +public class JakartaConstructorMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerJakartaConstructorMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "private final GenderJakartaConstructorMapper" ) + .contains( "@Inject" + lineSeparator() + + " public CustomerJakartaConstructorMapperImpl(GenderJakartaConstructorMapper" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/CustomerFieldMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/CustomerFieldMapper.java new file mode 100644 index 000000000..550d4ee94 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/CustomerFieldMapper.java @@ -0,0 +1,22 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.field; + +import org.mapstruct.InjectionStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; + +/** + * @author Filip Hrisafov + */ +@Mapper(componentModel = MappingConstants.ComponentModel.JAKARTA, uses = GenderJakartaFieldMapper.class, + injectionStrategy = InjectionStrategy.FIELD) +public interface CustomerFieldMapper { + + CustomerDto asTarget(CustomerEntity customerEntity); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/FieldJakartaConfig.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/FieldJakartaConfig.java new file mode 100644 index 000000000..b3ad9474c --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/FieldJakartaConfig.java @@ -0,0 +1,17 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.field; + +import org.mapstruct.InjectionStrategy; +import org.mapstruct.MapperConfig; +import org.mapstruct.MappingConstants; + +/** + * @author Filip Hrisafov + */ +@MapperConfig(componentModel = MappingConstants.ComponentModel.JAKARTA, injectionStrategy = InjectionStrategy.FIELD) +public interface FieldJakartaConfig { +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/GenderJakartaFieldMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/GenderJakartaFieldMapper.java new file mode 100644 index 000000000..ee5b95930 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/GenderJakartaFieldMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.field; + +import org.mapstruct.Mapper; +import org.mapstruct.ValueMapping; +import org.mapstruct.ValueMappings; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; + +/** + * @author Filip Hrisafov + */ +@Mapper(config = FieldJakartaConfig.class) +public interface GenderJakartaFieldMapper { + + @ValueMappings({ + @ValueMapping(source = "MALE", target = "M"), + @ValueMapping(source = "FEMALE", target = "F") + }) + GenderDto mapToDto(Gender gender); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/JakartaAndJsr330FieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/JakartaAndJsr330FieldMapperTest.java new file mode 100644 index 000000000..56ea53557 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/JakartaAndJsr330FieldMapperTest.java @@ -0,0 +1,53 @@ +/* + * 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.test.injectionstrategy.jakarta.field; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.WithJavaxInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * @author Filip Hrisafov + */ +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerFieldMapper.class, + GenderJakartaFieldMapper.class, + FieldJakartaConfig.class +}) +@IssueKey("2567") +@WithJakartaInject +@WithJavaxInject +public class JakartaAndJsr330FieldMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerFieldMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "@Inject" + lineSeparator() + " private GenderJakartaFieldMapper" ) + .doesNotContain( "public CustomerJakartaFieldMapperImpl(" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/JakartaFieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/JakartaFieldMapperTest.java new file mode 100644 index 000000000..2257bcb7b --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jakarta/field/JakartaFieldMapperTest.java @@ -0,0 +1,51 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jakarta.field; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * @author Filip Hrisafov + */ +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerFieldMapper.class, + GenderJakartaFieldMapper.class, + FieldJakartaConfig.class +}) +@IssueKey("2567") +@WithJakartaInject +public class JakartaFieldMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerFieldMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "@Inject" + lineSeparator() + " private GenderJakartaFieldMapper" ) + .doesNotContain( "public CustomerJakartaFieldMapperImpl(" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/_default/Jsr330DefaultCompileOptionFieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/_default/Jsr330DefaultCompileOptionFieldMapperTest.java index dd639684b..6b92d9815 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/_default/Jsr330DefaultCompileOptionFieldMapperTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/_default/Jsr330DefaultCompileOptionFieldMapperTest.java @@ -87,6 +87,9 @@ public class Jsr330DefaultCompileOptionFieldMapperTest { public void shouldHaveFieldInjection() { generatedSource.forMapper( CustomerJsr330DefaultCompileOptionFieldMapper.class ) .content() + .contains( "import javax.inject.Inject;" ) + .contains( "import javax.inject.Named;" ) + .contains( "import javax.inject.Singleton;" ) .contains( "@Inject" + lineSeparator() + " private GenderJsr330DefaultCompileOptionFieldMapper" ) .doesNotContain( "public CustomerJsr330DefaultCompileOptionFieldMapperImpl(" ); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/compileoptionconstructor/Jsr330CompileOptionConstructorMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/compileoptionconstructor/Jsr330CompileOptionConstructorMapperTest.java index 24bfba551..fe9cf295f 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/compileoptionconstructor/Jsr330CompileOptionConstructorMapperTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/compileoptionconstructor/Jsr330CompileOptionConstructorMapperTest.java @@ -86,6 +86,9 @@ public class Jsr330CompileOptionConstructorMapperTest { public void shouldHaveConstructorInjectionFromCompileOption() { generatedSource.forMapper( CustomerJsr330CompileOptionConstructorMapper.class ) .content() + .contains( "import javax.inject.Inject;" ) + .contains( "import javax.inject.Named;" ) + .contains( "import javax.inject.Singleton;" ) .contains( "private final GenderJsr330CompileOptionConstructorMapper" ) .contains( "@Inject" + lineSeparator() + " public CustomerJsr330CompileOptionConstructorMapperImpl" + diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/constructor/Jsr330ConstructorMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/constructor/Jsr330ConstructorMapperTest.java index 8543d57e3..a5cfce5c2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/constructor/Jsr330ConstructorMapperTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/constructor/Jsr330ConstructorMapperTest.java @@ -86,6 +86,9 @@ public class Jsr330ConstructorMapperTest { public void shouldHaveConstructorInjection() { generatedSource.forMapper( CustomerJsr330ConstructorMapper.class ) .content() + .contains( "import javax.inject.Inject;" ) + .contains( "import javax.inject.Named;" ) + .contains( "import javax.inject.Singleton;" ) .contains( "private final GenderJsr330ConstructorMapper" ) .contains( "@Inject" + lineSeparator() + " public CustomerJsr330ConstructorMapperImpl(GenderJsr330ConstructorMapper" ); diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/field/Jsr330FieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/field/Jsr330FieldMapperTest.java index d8cf0c392..84e67f63a 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/field/Jsr330FieldMapperTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/field/Jsr330FieldMapperTest.java @@ -89,6 +89,9 @@ public class Jsr330FieldMapperTest { public void shouldHaveFieldInjection() { generatedSource.forMapper( CustomerJsr330FieldMapper.class ) .content() + .contains( "import javax.inject.Inject;" ) + .contains( "import javax.inject.Named;" ) + .contains( "import javax.inject.Singleton;" ) .contains( "@Inject" + lineSeparator() + " private GenderJsr330FieldMapper" ) .doesNotContain( "public CustomerJsr330FieldMapperImpl(" ); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/CustomerJsr330DefaultCompileOptionFieldMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/CustomerJsr330DefaultCompileOptionFieldMapper.java new file mode 100644 index 000000000..80f5c60ef --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/CustomerJsr330DefaultCompileOptionFieldMapper.java @@ -0,0 +1,21 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jsr330.jakarta; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; + +/** + * @author Andrei Arlou + */ +@Mapper(componentModel = MappingConstants.ComponentModel.JSR330, + uses = GenderJsr330DefaultCompileOptionFieldMapper.class) +public interface CustomerJsr330DefaultCompileOptionFieldMapper { + + CustomerDto asTarget(CustomerEntity customerEntity); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/GenderJsr330DefaultCompileOptionFieldMapper.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/GenderJsr330DefaultCompileOptionFieldMapper.java new file mode 100644 index 000000000..4a9b56c1b --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/GenderJsr330DefaultCompileOptionFieldMapper.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.test.injectionstrategy.jsr330.jakarta; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ValueMapping; +import org.mapstruct.ValueMappings; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; + +/** + * @author Andrei Arlou + */ +@Mapper(componentModel = MappingConstants.ComponentModel.JSR330) +public interface GenderJsr330DefaultCompileOptionFieldMapper { + + @ValueMappings({ + @ValueMapping(source = "MALE", target = "M"), + @ValueMapping(source = "FEMALE", target = "F") + }) + GenderDto mapToDto(Gender gender); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/JakartaAndJsr330DefaultCompileOptionFieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/JakartaAndJsr330DefaultCompileOptionFieldMapperTest.java new file mode 100644 index 000000000..da7176fc7 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/JakartaAndJsr330DefaultCompileOptionFieldMapperTest.java @@ -0,0 +1,55 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.injectionstrategy.jsr330.jakarta; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.WithJavaxInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * Test field injection for component model jsr330. + * Default value option mapstruct.defaultInjectionStrategy is "field" + * + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJsr330DefaultCompileOptionFieldMapper.class, + GenderJsr330DefaultCompileOptionFieldMapper.class +}) +@WithJakartaInject +@WithJavaxInject +public class JakartaAndJsr330DefaultCompileOptionFieldMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJavaxInjection() { + generatedSource.forMapper( CustomerJsr330DefaultCompileOptionFieldMapper.class ) + .content() + .contains( "import javax.inject.Inject;" ) + .contains( "import javax.inject.Named;" ) + .contains( "import javax.inject.Singleton;" ) + .contains( "@Inject" + lineSeparator() + " private GenderJsr330DefaultCompileOptionFieldMapper" ) + .doesNotContain( "public CustomerJsr330DefaultCompileOptionFieldMapperImpl(" ) + .doesNotContain( "jakarta.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/JakartaJsr330DefaultCompileOptionFieldMapperTest.java b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/JakartaJsr330DefaultCompileOptionFieldMapperTest.java new file mode 100644 index 000000000..f78721fb1 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/injectionstrategy/jsr330/jakarta/JakartaJsr330DefaultCompileOptionFieldMapperTest.java @@ -0,0 +1,53 @@ +/* + * 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.test.injectionstrategy.jsr330.jakarta; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerDto; +import org.mapstruct.ap.test.injectionstrategy.shared.CustomerEntity; +import org.mapstruct.ap.test.injectionstrategy.shared.Gender; +import org.mapstruct.ap.test.injectionstrategy.shared.GenderDto; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.WithJakartaInject; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import static java.lang.System.lineSeparator; + +/** + * Test field injection for component model jsr330. + * Default value option mapstruct.defaultInjectionStrategy is "field" + * + * @author Filip Hrisafov + */ +@IssueKey("2567") +@WithClasses({ + CustomerDto.class, + CustomerEntity.class, + Gender.class, + GenderDto.class, + CustomerJsr330DefaultCompileOptionFieldMapper.class, + GenderJsr330DefaultCompileOptionFieldMapper.class +}) +@WithJakartaInject +public class JakartaJsr330DefaultCompileOptionFieldMapperTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource(); + + @ProcessorTest + public void shouldHaveJakartaInjection() { + generatedSource.forMapper( CustomerJsr330DefaultCompileOptionFieldMapper.class ) + .content() + .contains( "import jakarta.inject.Inject;" ) + .contains( "import jakarta.inject.Named;" ) + .contains( "import jakarta.inject.Singleton;" ) + .contains( "@Inject" + lineSeparator() + " private GenderJsr330DefaultCompileOptionFieldMapper" ) + .doesNotContain( "public CustomerJsr330DefaultCompileOptionFieldMapperImpl(" ) + .doesNotContain( "javax.inject" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/WithJakartaInject.java b/processor/src/test/java/org/mapstruct/ap/testutil/WithJakartaInject.java new file mode 100644 index 000000000..ccb0b030a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/testutil/WithJakartaInject.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.ap.testutil; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Meta annotation that adds the needed Spring Dependencies + * + * @author Filip Hrisafov + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@WithTestDependency({ + "jakarta.inject-api", +}) +public @interface WithJakartaInject { + +}