From 9cf813b07f99d71ded32c3ff748a8fff0b54d79a Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 2 Mar 2023 00:52:50 -0500 Subject: [PATCH 01/17] #674 Support for native Java 8 Optional mapping --- .../internal/model/OptionalMappingMethod.java | 127 +++++++++ .../ap/internal/model/PropertyMapping.java | 21 ++ .../ap/internal/model/common/Type.java | 11 +- .../ap/internal/model/common/TypeFactory.java | 22 +- .../internal/model/OptionalMappingMethod.ftl | 39 +++ .../DateFormatValidatorFactoryTest.java | 1 + .../common/DefaultConversionContextTest.java | 1 + .../optionalmapping/OptionalMappingTest.java | 248 ++++++++++++++++++ .../optionalmapping/OptionalTestMapper.java | 29 ++ .../ap/test/optionalmapping/Source.java | 106 ++++++++ .../ap/test/optionalmapping/Target.java | 106 ++++++++ .../testutil/assertions/JavaFileAssert.java | 2 +- .../OptionalTestMapperImpl.java | 154 +++++++++++ 13 files changed, 849 insertions(+), 18 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java create mode 100644 processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java new file mode 100644 index 0000000000..4f4487d093 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java @@ -0,0 +1,127 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.internal.model; + +import org.mapstruct.ap.internal.model.common.Assignment; +import org.mapstruct.ap.internal.model.common.Type; +import org.mapstruct.ap.internal.model.source.Method; +import org.mapstruct.ap.internal.model.source.SelectionParameters; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import static org.mapstruct.ap.internal.util.Collections.first; + +/** + * Maps from a source to a target where one or the other (or both) are an {@link Optional} type. + * + * @author Ken Wang + */ +public class OptionalMappingMethod extends ContainerMappingMethod { + + public static class Builder extends ContainerMappingMethodBuilder { + + public Builder() { + super( Builder.class, "optional element" ); + } + + @Override + protected Type getElementType(Type parameterType) { + if ( parameterType.isOptionalType() ) { + return parameterType.getTypeParameters().get(0); + } + else { + return parameterType; + } + } + + @Override + protected Assignment getWrapper(Assignment assignment, Method method) { + return assignment; + } + + @Override + protected OptionalMappingMethod instantiateMappingMethod(Method method, + Collection existingVariables, + Assignment assignment, + MethodReference factoryMethod, + boolean mapNullToDefault, + String loopVariableName, + List beforeMappingMethods, + List afterMappingMethods, + SelectionParameters selectionParameters) { + return new OptionalMappingMethod( + method, + getMethodAnnotations(), + existingVariables, + assignment, + factoryMethod, + mapNullToDefault, + loopVariableName, + beforeMappingMethods, + afterMappingMethods, + selectionParameters + ); + } + } + + private OptionalMappingMethod(Method method, + List annotations, + Collection existingVariables, + Assignment parameterAssignment, + MethodReference factoryMethod, + boolean mapNullToDefault, + String loopVariableName, + List beforeMappingReferences, + List afterMappingReferences, + SelectionParameters selectionParameters) { + super( + method, + annotations, + existingVariables, + parameterAssignment, + factoryMethod, + mapNullToDefault, + loopVariableName, + beforeMappingReferences, + afterMappingReferences, + selectionParameters + ); + } + + @Override + public Set getImportTypes() { + Set types = super.getImportTypes(); + + types.add( getSourceElementType() ); + return types; + } + + public Type getSourceElementType() { + Type sourceParameterType = getSourceParameter().getType(); + + if ( sourceParameterType.isOptionalType() ) { + return first( sourceParameterType.determineTypeArguments( Optional.class ) ).getTypeBound(); + } + else { + return sourceParameterType; + } + } + + @Override + public Type getResultElementType() { + Type resultParameterType = getResultType(); + + if ( resultParameterType.isOptionalType() ) { + return first( resultParameterType.determineTypeArguments( Optional.class ) ); + } + else { + return resultParameterType; + } + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java index 50f23ecbff..29fab5fef5 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java @@ -316,6 +316,9 @@ else if ( ( sourceType.isIterableType() && targetType.isStreamType() ) || ( sourceType.isStreamType() && targetType.isIterableType() ) ) { assignment = forgeStreamMapping( sourceType, targetType, rightHandSide ); } + else if ( sourceType.isOptionalType() || targetType.isOptionalType() ) { + assignment = forgeOptionalMapping( sourceType, targetType, rightHandSide ); + } else { assignment = forgeMapping( rightHandSide ); } @@ -755,6 +758,24 @@ private Assignment forgeWithElementMapping(Type sourceType, Type targetType, Sou return createForgedAssignment( source, methodRef, iterableMappingMethod ); } + private Assignment forgeOptionalMapping(Type sourceType, Type targetType, SourceRHS source) { + + targetType = targetType.withoutBounds(); + ForgedMethod methodRef = prepareForgedMethod( sourceType, targetType, source, "?" ); + + OptionalMappingMethod.Builder builder = new OptionalMappingMethod.Builder(); + + ContainerMappingMethod optionalMappingMethod = builder + .mappingContext( ctx ) + .method( methodRef ) + .selectionParameters( selectionParameters ) + .callingContextTargetPropertyName( targetPropertyName ) + .positionHint( positionHint ) + .build(); + + return createForgedAssignment( source, methodRef, optionalMappingMethod ); + } + private ForgedMethod prepareForgedMethod(Type sourceType, Type targetType, SourceRHS source, String suffix) { String name = getName( sourceType, targetType ); name = Strings.getSafeVariableName( name, ctx.getReservedNames() ); 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 f742e1ba0f..1c685a3e9c 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 @@ -108,6 +108,8 @@ public class Type extends ModelElement implements Comparable { private final boolean isMapType; private final boolean isVoid; private final boolean isStream; + + private final boolean isOptional; private final boolean isLiteral; private final boolean loggingVerbose; @@ -146,7 +148,7 @@ public Type(TypeUtils typeUtils, ElementUtils elementUtils, TypeFactory typeFact String packageName, String name, String qualifiedName, boolean isInterface, boolean isEnumType, boolean isIterableType, boolean isCollectionType, boolean isMapType, boolean isStreamType, - Map toBeImportedTypes, + boolean isOptionalType, Map toBeImportedTypes, Map notToBeImportedTypes, Boolean isToBeImported, boolean isLiteral, boolean loggingVerbose) { @@ -172,6 +174,7 @@ public Type(TypeUtils typeUtils, ElementUtils elementUtils, TypeFactory typeFact this.isCollectionType = isCollectionType; this.isMapType = isMapType; this.isStream = isStreamType; + this.isOptional = isOptionalType; this.isVoid = typeMirror.getKind() == TypeKind.VOID; this.isLiteral = isLiteral; @@ -392,6 +395,10 @@ public boolean isStreamType() { return isStream; } + public boolean isOptionalType() { + return isOptional; + } + /** * A wild card type can have two types of bounds (mutual exclusive): extends and super. * @@ -554,6 +561,7 @@ public Type erasure() { isCollectionType, isMapType, isStream, + isOptional, toBeImportedTypes, notToBeImportedTypes, isToBeImported, @@ -597,6 +605,7 @@ public Type withoutBounds() { isCollectionType, isMapType, isStream, + isOptional, toBeImportedTypes, notToBeImportedTypes, isToBeImported, 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 f28e0c687e..6c792615a5 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 @@ -5,22 +5,7 @@ */ package org.mapstruct.ap.internal.model.common; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.NavigableMap; -import java.util.NavigableSet; -import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.TreeMap; -import java.util.TreeSet; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentNavigableMap; @@ -92,6 +77,7 @@ public class TypeFactory { private final TypeMirror collectionType; private final TypeMirror mapType; private final TypeMirror streamType; + private final TypeMirror optionalType; private final Map implementationTypes = new HashMap<>(); private final Map toBeImportedTypes = new HashMap<>(); @@ -113,6 +99,7 @@ public TypeFactory(ElementUtils elementUtils, TypeUtils typeUtils, FormattingMes mapType = typeUtils.erasure( elementUtils.getTypeElement( Map.class.getCanonicalName() ).asType() ); TypeElement streamTypeElement = elementUtils.getTypeElement( JavaStreamConstants.STREAM_FQN ); streamType = streamTypeElement == null ? null : typeUtils.erasure( streamTypeElement.asType() ); + optionalType = typeUtils.erasure( elementUtils.getTypeElement( Optional.class.getCanonicalName() ).asType() ); implementationTypes.put( Iterable.class.getName(), withInitialCapacity( getType( ArrayList.class ) ) ); implementationTypes.put( Collection.class.getName(), withInitialCapacity( getType( ArrayList.class ) ) ); @@ -221,6 +208,7 @@ private Type getType(TypeMirror mirror, boolean isLiteral, Boolean alwaysImport) boolean isCollectionType = typeUtils.isSubtypeErased( mirror, collectionType ); boolean isMapType = typeUtils.isSubtypeErased( mirror, mapType ); boolean isStreamType = streamType != null && typeUtils.isSubtypeErased( mirror, streamType ); + boolean isOptionalType = typeUtils.isSubtypeErased( mirror, optionalType ); boolean isEnumType; boolean isInterface; @@ -330,6 +318,7 @@ else if ( mirror.getKind() == TypeKind.TYPEVAR ) { isCollectionType, isMapType, isStreamType, + isOptionalType, toBeImportedTypes, notToBeImportedTypes, toBeImported, @@ -556,6 +545,7 @@ private ImplementationType getImplementationType(TypeMirror mirror) { implementationType.isCollectionType(), implementationType.isMapType(), implementationType.isStreamType(), + implementationType.isOptionalType(), toBeImportedTypes, notToBeImportedTypes, null, diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl new file mode 100644 index 0000000000..8dcdf333ce --- /dev/null +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl @@ -0,0 +1,39 @@ +<#-- + + Copyright MapStruct Authors. + + Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + +--> +<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.OptionalMappingMethod" --> +<#if overridden>@Override +<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, )<@throws/> { + if ( ${sourceParameter.name} == null ) { + <#if resultType.optionalType> + <#-- regardless of mapNullToDefault value, never return null for Optional resultType --> + return Optional.empty(); + <#else> + <#if !mapNullToDefault> + return null; + <#else> + <#-- TODO: this should return the default value for whatever the returnType is --> + return null; + + + } + + <#if sourceParameter.type.optionalType> + return ${sourceParameter.name}.map( ${loopVariableName} -> <@includeModel object=elementAssignment/> )<#if !returnType.optionalType>.orElse( null ); + <#else> + <@includeModel object=sourceElementType/> ${loopVariableName} = ${sourceParameter.name}; + return Optional.ofNullable( <@includeModel object=elementAssignment/> ); + +} +<#macro throws> + <#if (thrownTypes?size > 0)><#lt> throws <@compress single_line=true> + <#list thrownTypes as exceptionType> + <@includeModel object=exceptionType/> + <#if exceptionType_has_next>, <#t> + + + \ No newline at end of file diff --git a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java index 646f898063..2194c04d99 100755 --- a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java +++ b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DateFormatValidatorFactoryTest.java @@ -174,6 +174,7 @@ private Type typeWithFQN(String fullQualifiedName) { false, false, false, + false, new HashMap<>( ), new HashMap<>( ), false, diff --git a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java index ce2f895e0f..91b1c87f5a 100755 --- a/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java +++ b/processor/src/test/java/org/mapstruct/ap/internal/model/common/DefaultConversionContextTest.java @@ -122,6 +122,7 @@ private Type typeWithFQN(String fullQualifiedName) { false, false, false, + false, new HashMap<>( ), new HashMap<>( ), false, diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java new file mode 100644 index 0000000000..58daf576b1 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java @@ -0,0 +1,248 @@ +/* + * 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.optionalmapping; + +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test for mapping logic from {@link org.mapstruct.ap.internal.model.OptionalMappingMethod}. + * + * @author Ken Wang + */ +@WithClasses({ + OptionalTestMapper.class, + Source.class, + Target.class +}) +public class OptionalMappingTest { + + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalTestMapper.class ); + + @ProcessorTest + public void testMappingSimpleOptionalToNonOptional() { + Source source = new Source(); + source.setOptionalToNonOptional( Optional.of( "some value" ) ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalToNonOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void testMappingEmptySimpleOptionalToNonOptional() { + Source source = new Source(); + source.setOptionalToNonOptional( Optional.empty() ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromNonOptional() { + Target target = new Target(); + target.setOptionalToNonOptional( "some value" ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalToNonOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromNullNonOptional() { + Target target = new Target(); + target.setOptionalToNonOptional( null ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalToNonOptional() ).isEmpty(); + } + + @ProcessorTest + public void testMappingNonOptionalToSimpleOptional() { + Source source = new Source(); + source.setNonOptionalToOptional( "some value" ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getNonOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testMappingNullNonOptionalToSimpleOptional() { + Source source = new Source(); + source.setNonOptionalToOptional( null ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromSimpleOptional() { + Target target = new Target(); + target.setNonOptionalToOptional( Optional.of( "some value" ) ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getNonOptionalToOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromEmptySimpleOptional() { + Target target = new Target(); + target.setNonOptionalToOptional( Optional.empty() ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getNonOptionalToOptional() ).isNull(); + } + + @ProcessorTest + public void testMappingSimpleOptionalToOptional() { + Source source = new Source(); + source.setOptionalToOptional( Optional.of( "some value" ) ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testMappingEmptySimpleOptionalToOptional() { + Source source = new Source(); + source.setOptionalToOptional( Optional.empty() ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromOptional() { + Target target = new Target(); + target.setOptionalToOptional( Optional.of( "some value" ) ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromEmptyOptional() { + Target target = new Target(); + target.setOptionalToOptional( Optional.empty() ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testMappingSubTypeOptionalToNonOptional() { + Source source = new Source(); + source.setOptionalSubTypeToNonOptional( Optional.of( new Source.SubType( 94, "test" ) ) ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalSubTypeToNonOptional() ).isEqualTo( new Target.SubType( 94, "test" ) ); + } + + @ProcessorTest + public void testMappingEmptySubTypeOptionalToNonOptional() { + Source source = new Source(); + source.setOptionalSubTypeToNonOptional( Optional.empty() ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalSubTypeToNonOptional() ).isNull(); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromNonOptional() { + Target target = new Target(); + target.setOptionalSubTypeToNonOptional( new Target.SubType( 94, "test" ) ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalSubTypeToNonOptional() ).contains( new Source.SubType( 94, "test" ) ); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromNullNonOptional() { + Target target = new Target(); + target.setOptionalSubTypeToNonOptional( null ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalSubTypeToNonOptional() ).isEmpty(); + } + + @ProcessorTest + public void testMappingNonOptionalToSubTypeOptional() { + Source source = new Source(); + source.setNonOptionalSubTypeToOptional( new Source.SubType( 94, "test" ) ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getNonOptionalSubTypeToOptional() ).contains( new Target.SubType( 94, "test" ) ); + } + + @ProcessorTest + public void testMappingNullNonOptionalToSubTypeOptional() { + Source source = new Source(); + source.setNonOptionalSubTypeToOptional( null ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getNonOptionalSubTypeToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromSubTypeOptional() { + Target target = new Target(); + target.setNonOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94, "test" ) ) ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getNonOptionalSubTypeToOptional() ).isEqualTo( new Source.SubType( 94, "test" ) ); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromEmptySubTypeOptional() { + Target target = new Target(); + target.setNonOptionalSubTypeToOptional( Optional.empty() ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getNonOptionalSubTypeToOptional() ).isNull(); + } + + @ProcessorTest + public void testMappingSubTypeOptionalToOptional() { + Source source = new Source(); + source.setOptionalSubTypeToOptional( Optional.of( new Source.SubType( 94, "test" ) ) ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalSubTypeToOptional() ).contains( new Target.SubType( 94, "test" ) ); + } + + @ProcessorTest + public void testMappingEmptySubTypeOptionalToOptional() { + Source source = new Source(); + source.setOptionalSubTypeToOptional( Optional.empty() ); + + Target target = OptionalTestMapper.INSTANCE.map( source ); + assertThat( target.getOptionalSubTypeToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromOptional() { + Target target = new Target(); + target.setOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94, "test" ) ) ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalSubTypeToOptional() ).contains( new Source.SubType( 94, "test" ) ); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromEmptyOptional() { + Target target = new Target(); + target.setOptionalSubTypeToOptional( Optional.empty() ); + + Source source = OptionalTestMapper.INSTANCE.map( target ); + assertThat( source.getOptionalSubTypeToOptional() ).isEmpty(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java new file mode 100644 index 0000000000..c6e8e3f0d3 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping; + +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface OptionalTestMapper { + + OptionalTestMapper INSTANCE = Mappers.getMapper( OptionalTestMapper.class ); + + Target map(Source source); + + @InheritInverseConfiguration + Source map(Target target); + + @Mapping(source = "a", target = "b") + Target.SubType map(Source.SubType source); + + @InheritInverseConfiguration + Source.SubType map(Target.SubType source); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java new file mode 100644 index 0000000000..a66a6f71ec --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java @@ -0,0 +1,106 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping; + +import java.util.Objects; +import java.util.Optional; + +public class Source { + + private Optional optionalToNonOptional; + private String nonOptionalToOptional; + private Optional optionalToOptional; + + private Optional optionalSubTypeToNonOptional; + private SubType nonOptionalSubTypeToOptional; + private Optional optionalSubTypeToOptional; + + public Optional getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(Optional optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public String getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(String nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public Optional getOptionalSubTypeToNonOptional() { + return optionalSubTypeToNonOptional; + } + + public void setOptionalSubTypeToNonOptional(Optional optionalSubTypeToNonOptional) { + this.optionalSubTypeToNonOptional = optionalSubTypeToNonOptional; + } + + public SubType getNonOptionalSubTypeToOptional() { + return nonOptionalSubTypeToOptional; + } + + public void setNonOptionalSubTypeToOptional(SubType nonOptionalSubTypeToOptional) { + this.nonOptionalSubTypeToOptional = nonOptionalSubTypeToOptional; + } + + public Optional getOptionalSubTypeToOptional() { + return optionalSubTypeToOptional; + } + + public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOptional) { + this.optionalSubTypeToOptional = optionalSubTypeToOptional; + } + + public static class SubType { + + private final int value; + private final String a; + + public SubType(int value, String a) { + this.value = value; + this.a = a; + } + + public int getValue() { + return value; + } + + public String getA() { + return a; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return value == subType.value && Objects.equals( a, subType.a ); + } + + @Override + public int hashCode() { + return Objects.hash( value, a ); + } + + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java new file mode 100644 index 0000000000..11cee32af6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java @@ -0,0 +1,106 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping; + +import java.util.Objects; +import java.util.Optional; + +public class Target { + + private String optionalToNonOptional; + private Optional nonOptionalToOptional; + private Optional optionalToOptional; + + private SubType optionalSubTypeToNonOptional; + private Optional nonOptionalSubTypeToOptional; + private Optional optionalSubTypeToOptional; + + public String getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(String optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public Optional getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public SubType getOptionalSubTypeToNonOptional() { + return optionalSubTypeToNonOptional; + } + + public void setOptionalSubTypeToNonOptional(SubType optionalSubTypeToNonOptional) { + this.optionalSubTypeToNonOptional = optionalSubTypeToNonOptional; + } + + public Optional getNonOptionalSubTypeToOptional() { + return nonOptionalSubTypeToOptional; + } + + public void setNonOptionalSubTypeToOptional(Optional nonOptionalSubTypeToOptional) { + this.nonOptionalSubTypeToOptional = nonOptionalSubTypeToOptional; + } + + public Optional getOptionalSubTypeToOptional() { + return optionalSubTypeToOptional; + } + + public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOptional) { + this.optionalSubTypeToOptional = optionalSubTypeToOptional; + } + + public static class SubType { + + private final int value; + private final String b; + + public SubType(int value, String b) { + this.value = value; + this.b = b; + } + + public int getValue() { + return value; + } + + public String getB() { + return b; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return value == subType.value && Objects.equals( b, subType.b ); + } + + @Override + public int hashCode() { + return Objects.hash( value, b ); + } + + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java b/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java index e6eabd9f84..3ceb58fbc9 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java @@ -33,7 +33,7 @@ public class JavaFileAssert extends FileAssert { private static final String FIRST_LINE_LICENSE_REGEX = ".*Copyright MapStruct Authors.*"; private static final String GENERATED_DATE_REGEX = "\\s+date = " + - "\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{4}\","; + "\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]\\d{4}\","; private static final String GENERATED_COMMENTS_REGEX = "\\s+comments = \"version: , compiler: .*, environment: " + ".*\""; private static final String IMPORT_GENERATED_ANNOTATION_REGEX = "import javax\\.annotation\\.(processing\\.)?" + diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java new file mode 100644 index 0000000000..4bb8cef311 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java @@ -0,0 +1,154 @@ +/* + * 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.optionalmapping; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-03-02T00:33:34-0500", + comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" +) +public class OptionalTestMapperImpl implements OptionalTestMapper { + + @Override + public Target map(Source source) { + if ( source == null ) { + return null; + } + + Target target = new Target(); + + target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); + target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); + target.setOptionalToOptional( source.getOptionalToOptional() ); + target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); + target.setNonOptionalSubTypeToOptional( subTypeToSubTypeOptional( source.getNonOptionalSubTypeToOptional() ) ); + target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); + + return target; + } + + @Override + public Source map(Target target) { + if ( target == null ) { + return null; + } + + Source source = new Source(); + + source.setOptionalToNonOptional( stringToStringOptional( target.getOptionalToNonOptional() ) ); + source.setNonOptionalToOptional( stringOptionalToString( target.getNonOptionalToOptional() ) ); + source.setOptionalToOptional( target.getOptionalToOptional() ); + source.setOptionalSubTypeToNonOptional( subTypeToSubTypeOptional1( target.getOptionalSubTypeToNonOptional() ) ); + source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); + source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); + + return source; + } + + @Override + public Target.SubType map(Source.SubType source) { + if ( source == null ) { + return null; + } + + String b = null; + int value = 0; + + b = source.getA(); + value = source.getValue(); + + Target.SubType subType = new Target.SubType( value, b ); + + return subType; + } + + @Override + public Source.SubType map(Target.SubType source) { + if ( source == null ) { + return null; + } + + String a = null; + int value = 0; + + a = source.getB(); + value = source.getValue(); + + Source.SubType subType = new Source.SubType( value, a ); + + return subType; + } + + protected String stringOptionalToString(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( string -> string ).orElse( null ); + } + + protected Optional stringToStringOptional(String string) { + if ( string == null ) { + return Optional.empty(); + } + + String string1 = string; + return Optional.ofNullable( string1 ); + } + + protected Target.SubType subTypeOptionalToSubType(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( subType -> map( subType ) ).orElse( null ); + } + + protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Source.SubType subType1 = subType; + return Optional.ofNullable( map( subType1 ) ); + } + + protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + if ( optional == null ) { + return Optional.empty(); + } + + return optional.map( subType -> map( subType ) ); + } + + protected Optional subTypeToSubTypeOptional1(Target.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Target.SubType subType1 = subType; + return Optional.ofNullable( map( subType1 ) ); + } + + protected Source.SubType subTypeOptionalToSubType1(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( subType -> map( subType ) ).orElse( null ); + } + + protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { + if ( optional == null ) { + return Optional.empty(); + } + + return optional.map( subType -> map( subType ) ); + } +} From 71c87b377a0d7de6d202bca568b04816fa8d60f6 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 2 Mar 2023 01:44:39 -0500 Subject: [PATCH 02/17] fix formatting --- .../internal/model/OptionalMappingMethod.java | 15 +++++---------- .../ap/internal/model/common/TypeFactory.java | 18 +++++++++++++++++- .../optionalmapping/OptionalMappingTest.java | 6 +++--- .../ap/test/optionalmapping/Source.java | 6 +++--- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java index 4f4487d093..abc7cd3225 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/OptionalMappingMethod.java @@ -33,7 +33,7 @@ public Builder() { @Override protected Type getElementType(Type parameterType) { if ( parameterType.isOptionalType() ) { - return parameterType.getTypeParameters().get(0); + return parameterType.getTypeParameters().get( 0 ); } else { return parameterType; @@ -46,15 +46,10 @@ protected Assignment getWrapper(Assignment assignment, Method method) { } @Override - protected OptionalMappingMethod instantiateMappingMethod(Method method, - Collection existingVariables, - Assignment assignment, - MethodReference factoryMethod, - boolean mapNullToDefault, - String loopVariableName, - List beforeMappingMethods, - List afterMappingMethods, - SelectionParameters selectionParameters) { + protected OptionalMappingMethod instantiateMappingMethod(Method method, Collection existingVariables, + Assignment assignment, MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName, + List beforeMappingMethods, + List afterMappingMethods, SelectionParameters selectionParameters) { return new OptionalMappingMethod( method, getMethodAnnotations(), 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 6c792615a5..97d6212c64 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 @@ -5,7 +5,23 @@ */ package org.mapstruct.ap.internal.model.common; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Optional; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentNavigableMap; diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java index 58daf576b1..d0dafe5879 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java @@ -100,12 +100,12 @@ public void testReverseMappingNonOptionalFromEmptySimpleOptional() { Source source = OptionalTestMapper.INSTANCE.map( target ); assertThat( source.getNonOptionalToOptional() ).isNull(); } - + @ProcessorTest public void testMappingSimpleOptionalToOptional() { Source source = new Source(); source.setOptionalToOptional( Optional.of( "some value" ) ); - + Target target = OptionalTestMapper.INSTANCE.map( source ); assertThat( target.getOptionalToOptional() ).contains( "some value" ); } @@ -136,7 +136,7 @@ public void testReverseMappingSimpleOptionalFromEmptyOptional() { Source source = OptionalTestMapper.INSTANCE.map( target ); assertThat( source.getOptionalToOptional() ).isEmpty(); } - + @ProcessorTest public void testMappingSubTypeOptionalToNonOptional() { Source source = new Source(); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java index a66a6f71ec..3e27dbbb02 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java @@ -67,7 +67,7 @@ public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOpti } public static class SubType { - + private final int value; private final String a; @@ -100,7 +100,7 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash( value, a ); } - + } - + } From 2dd531b6b0580ac25c80653346e566d1de5cf374 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 2 Mar 2023 03:12:02 -0500 Subject: [PATCH 03/17] Default to `Optional.empty() when null checking --- .../ap/internal/model/common/Type.java | 3 + .../ap/internal/model/macro/CommonMacros.ftl | 4 +- .../BaseOptionalMappingTest.java | 434 ++++++++++++++++++ .../BaseOptionalTestMapper.java | 9 + ...ullValueCheckAlwaysOptionalTestMapper.java | 14 + .../optionalmapping/OptionalMappingTest.java | 234 +--------- .../optionalmapping/OptionalTestMapper.java | 29 -- .../SimpleOptionalTestMapper.java | 13 + .../ap/test/optionalmapping/Source.java | 58 ++- .../ap/test/optionalmapping/Target.java | 58 ++- .../OptionalTestMapperImpl.java | 154 ------- 11 files changed, 588 insertions(+), 422 deletions(-) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java delete mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java 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 1c685a3e9c..52139727a1 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 @@ -1209,6 +1209,9 @@ public String getSensibleDefault() { else if ( "String".equals( getName() ) ) { return "\"\""; } + else if ( isOptionalType() ) { + return "Optional.empty()"; + } else { if ( isNative() ) { // must be boxed, since primitive is already checked diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl index bce28ebe19..55db5176ed 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl @@ -40,9 +40,9 @@ else { <@handeDefaultAssigment/> } - <#elseif setExplicitlyToDefault || setExplicitlyToNull> + <#elseif setExplicitlyToDefault || setExplicitlyToNull || ext.targetType.optionalType> else { - <#if ext.targetBeanName?has_content>${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if setExplicitlyToDefault><@lib.initTargetObject/><#else>null; + <#if ext.targetBeanName?has_content>${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if setExplicitlyToDefault || ext.targetType.optionalType><@lib.initTargetObject/><#else>null; } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java new file mode 100644 index 0000000000..4f96432227 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java @@ -0,0 +1,434 @@ +package org.mapstruct.ap.test.optionalmapping; + +import java.util.Optional; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.factory.Mappers; + +import static org.assertj.core.api.Assertions.assertThat; + +public abstract class BaseOptionalMappingTest { + + private final Class mapperClass; + private BaseOptionalTestMapper mapper; + + protected BaseOptionalMappingTest(Class mapperClass) { + this.mapperClass = mapperClass; + } + + private BaseOptionalTestMapper getMapper() { + if (this.mapper == null) { + this.mapper = Mappers.getMapper(mapperClass); + } + return this.mapper; + } + + @ProcessorTest + public void testMappingSimpleOptionalToNonOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalToNonOptional( Optional.of( "some value" ) ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void testMappingEmptySimpleOptionalToNonOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalToNonOptional( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromNonOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalToNonOptional( "some value" ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalToNonOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromNullNonOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalToNonOptional( null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalToNonOptional() ).isEmpty(); + } + + @ProcessorTest + public void testMappingNonOptionalToSimpleOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setNonOptionalToOptional( "some value" ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testMappingNullNonOptionalToSimpleOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setNonOptionalToOptional( null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromSimpleOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setNonOptionalToOptional( Optional.of( "some value" ) ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getNonOptionalToOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromEmptySimpleOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setNonOptionalToOptional( Optional.empty() ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getNonOptionalToOptional() ).isNull(); + } + + @ProcessorTest + public void testMappingSimpleOptionalToOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalToOptional( Optional.of( "some value" ) ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testMappingEmptySimpleOptionalToOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalToOptional( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalToOptional( Optional.of( "some value" ) ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testReverseMappingSimpleOptionalFromEmptyOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalToOptional( Optional.empty() ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testMappingSubTypeOptionalToNonOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalSubTypeToNonOptional( Optional.of( new Source.SubType( 94 ) ) ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalSubTypeToNonOptional() ).isEqualTo( new Target.SubType( 94 ) ); + } + + @ProcessorTest + public void testMappingEmptySubTypeOptionalToNonOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalSubTypeToNonOptional( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalSubTypeToNonOptional() ).isNull(); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromNonOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalSubTypeToNonOptional( new Target.SubType( 94 ) ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalSubTypeToNonOptional() ).contains( new Source.SubType( 94 ) ); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromNullNonOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalSubTypeToNonOptional( null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalSubTypeToNonOptional() ).isEmpty(); + } + + @ProcessorTest + public void testMappingNonOptionalToSubTypeOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setNonOptionalSubTypeToOptional( new Source.SubType( 94 ) ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getNonOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); + } + + @ProcessorTest + public void testMappingNullNonOptionalToSubTypeOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setNonOptionalSubTypeToOptional( null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getNonOptionalSubTypeToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromSubTypeOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setNonOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94 ) ) ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getNonOptionalSubTypeToOptional() ).isEqualTo( new Source.SubType( 94 ) ); + } + + @ProcessorTest + public void testReverseMappingNonOptionalFromEmptySubTypeOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setNonOptionalSubTypeToOptional( Optional.empty() ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getNonOptionalSubTypeToOptional() ).isNull(); + } + + @ProcessorTest + public void testMappingSubTypeOptionalToOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalSubTypeToOptional( Optional.of( new Source.SubType( 94 ) ) ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); + } + + @ProcessorTest + public void testMappingEmptySubTypeOptionalToOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.setOptionalSubTypeToOptional( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getOptionalSubTypeToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94 ) ) ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalSubTypeToOptional() ).contains( new Source.SubType( 94 ) ); + } + + @ProcessorTest + public void testReverseMappingSubTypeOptionalFromEmptyOptional() { + Target target = new Target( null, null, null, null, null, null ); + target.setOptionalSubTypeToOptional( Optional.empty() ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getOptionalSubTypeToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testConstructorMappingSimpleOptionalToNonOptional() { + Source source = new Source( Optional.of( "some value" ), null, null, null, null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void testConstructorMappingEmptySimpleOptionalToNonOptional() { + Source source = new Source( Optional.empty(), null, null, null, null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void testReverseConstructorMappingSimpleOptionalFromNonOptional() { + Target target = new Target( "some value", null, null, null, null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalToNonOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testReverseConstructorMappingSimpleOptionalFromNullNonOptional() { + Target target = new Target( null, null, null, null, null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalToNonOptional() ).isEmpty(); + } + + @ProcessorTest + public void testConstructorMappingNonOptionalToSimpleOptional() { + Source source = new Source( null, "some value", null, null, null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testConstructorMappingNullNonOptionalToSimpleOptional() { + Source source = new Source( null, null, null, null, null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseConstructorMappingNonOptionalFromSimpleOptional() { + Target target = new Target( null, Optional.of( "some value" ), null, null, null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorNonOptionalToOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void testReverseConstructorMappingNonOptionalFromEmptySimpleOptional() { + Target target = new Target( null, Optional.empty(), null, null, null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorNonOptionalToOptional() ).isNull(); + } + + @ProcessorTest + public void testConstructorMappingSimpleOptionalToOptional() { + Source source = new Source( null, null, Optional.of( "some value" ), null, null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testConstructorMappingEmptySimpleOptionalToOptional() { + Source source = new Source( null, null, Optional.empty(), null, null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseConstructorMappingSimpleOptionalFromOptional() { + Target target = new Target( null, null, Optional.of( "some value" ), null, null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void testReverseConstructorMappingSimpleOptionalFromEmptyOptional() { + Target target = new Target( null, null, Optional.empty(), null, null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testConstructorMappingSubTypeOptionalToNonOptional() { + Source source = new Source( null, null, null, Optional.of( new Source.SubType( 94 ) ), null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalSubTypeToNonOptional() ).isEqualTo( new Target.SubType( 94 ) ); + } + + @ProcessorTest + public void testConstructorMappingEmptySubTypeOptionalToNonOptional() { + Source source = new Source( null, null, null, Optional.empty(), null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalSubTypeToNonOptional() ).isNull(); + } + + @ProcessorTest + public void testReverseConstructorMappingSubTypeOptionalFromNonOptional() { + Target target = new Target( null, null, null, new Target.SubType( 94 ), null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalSubTypeToNonOptional() ).contains( new Source.SubType( 94 ) ); + } + + @ProcessorTest + public void testReverseConstructorMappingSubTypeOptionalFromNullNonOptional() { + Target target = new Target( null, null, null, null, null, null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalSubTypeToNonOptional() ).isEmpty(); + } + + @ProcessorTest + public void testConstructorMappingNonOptionalToSubTypeOptional() { + Source source = new Source( null, null, null, null, new Source.SubType( 94 ), null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorNonOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); + } + + @ProcessorTest + public void testConstructorMappingNullNonOptionalToSubTypeOptional() { + Source source = new Source( null, null, null, null, null, null ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorNonOptionalSubTypeToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseConstructorMappingNonOptionalFromSubTypeOptional() { + Target target = new Target( null, null, null, null, Optional.of( new Target.SubType( 94 ) ), null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorNonOptionalSubTypeToOptional() ).isEqualTo( new Source.SubType( 94 ) ); + } + + @ProcessorTest + public void testReverseConstructorMappingNonOptionalFromEmptySubTypeOptional() { + Target target = new Target( null, null, null, null, Optional.empty(), null ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorNonOptionalSubTypeToOptional() ).isNull(); + } + + @ProcessorTest + public void testConstructorMappingSubTypeOptionalToOptional() { + Source source = new Source( null, null, null, null, null, Optional.of( new Source.SubType( 94 ) ) ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); + } + + @ProcessorTest + public void testConstructorMappingEmptySubTypeOptionalToOptional() { + Source source = new Source( null, null, null, null, null, Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getConstructorOptionalSubTypeToOptional() ).isEmpty(); + } + + @ProcessorTest + public void testReverseConstructorMappingSubTypeOptionalFromOptional() { + Target target = new Target( null, null, null, null, null, Optional.of( new Target.SubType( 94 ) ) ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalSubTypeToOptional() ).contains( new Source.SubType( 94 ) ); + } + + @ProcessorTest + public void testReverseConstructorMappingSubTypeOptionalFromEmptyOptional() { + Target target = new Target( null, null, null, null, null, Optional.empty() ); + + Source source = getMapper().fromTarget( target ); + assertThat( source.getConstructorOptionalSubTypeToOptional() ).isEmpty(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java new file mode 100644 index 0000000000..693240a24d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java @@ -0,0 +1,9 @@ +package org.mapstruct.ap.test.optionalmapping; + +public interface BaseOptionalTestMapper { + + Target toTarget(Source source); + + Source fromTarget(Target target); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java new file mode 100644 index 0000000000..a2bb736167 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java @@ -0,0 +1,14 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping; + +import org.mapstruct.Mapper; +import org.mapstruct.NullValueCheckStrategy; + +@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +public interface NullValueCheckAlwaysOptionalTestMapper extends BaseOptionalTestMapper { + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java index d0dafe5879..0c9eb0965a 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java @@ -5,10 +5,9 @@ */ package org.mapstruct.ap.test.optionalmapping; -import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.Nested; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; -import org.mapstruct.ap.testutil.runner.GeneratedSource; import java.util.Optional; @@ -19,230 +18,27 @@ * * @author Ken Wang */ -@WithClasses({ - OptionalTestMapper.class, - Source.class, - Target.class -}) public class OptionalMappingTest { - @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalTestMapper.class ); +// @RegisterExtension +// final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalTestMapper.class ); - @ProcessorTest - public void testMappingSimpleOptionalToNonOptional() { - Source source = new Source(); - source.setOptionalToNonOptional( Optional.of( "some value" ) ); + @Nested + @WithClasses({ SimpleOptionalTestMapper.class, BaseOptionalTestMapper.class, Source.class, Target.class }) + class SimpleTests extends BaseOptionalMappingTest { - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalToNonOptional() ).isEqualTo( "some value" ); + protected SimpleTests() { + super( SimpleOptionalTestMapper.class ); + } } - @ProcessorTest - public void testMappingEmptySimpleOptionalToNonOptional() { - Source source = new Source(); - source.setOptionalToNonOptional( Optional.empty() ); + @Nested + @WithClasses({ NullValueCheckAlwaysOptionalTestMapper.class, BaseOptionalTestMapper.class, Source.class, Target.class }) + class NullValueCheckAlwaysTests extends BaseOptionalMappingTest { - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalToNonOptional() ).isNull(); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromNonOptional() { - Target target = new Target(); - target.setOptionalToNonOptional( "some value" ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalToNonOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromNullNonOptional() { - Target target = new Target(); - target.setOptionalToNonOptional( null ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalToNonOptional() ).isEmpty(); - } - - @ProcessorTest - public void testMappingNonOptionalToSimpleOptional() { - Source source = new Source(); - source.setNonOptionalToOptional( "some value" ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getNonOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testMappingNullNonOptionalToSimpleOptional() { - Source source = new Source(); - source.setNonOptionalToOptional( null ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getNonOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromSimpleOptional() { - Target target = new Target(); - target.setNonOptionalToOptional( Optional.of( "some value" ) ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getNonOptionalToOptional() ).isEqualTo( "some value" ); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromEmptySimpleOptional() { - Target target = new Target(); - target.setNonOptionalToOptional( Optional.empty() ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getNonOptionalToOptional() ).isNull(); - } - - @ProcessorTest - public void testMappingSimpleOptionalToOptional() { - Source source = new Source(); - source.setOptionalToOptional( Optional.of( "some value" ) ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testMappingEmptySimpleOptionalToOptional() { - Source source = new Source(); - source.setOptionalToOptional( Optional.empty() ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromOptional() { - Target target = new Target(); - target.setOptionalToOptional( Optional.of( "some value" ) ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromEmptyOptional() { - Target target = new Target(); - target.setOptionalToOptional( Optional.empty() ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testMappingSubTypeOptionalToNonOptional() { - Source source = new Source(); - source.setOptionalSubTypeToNonOptional( Optional.of( new Source.SubType( 94, "test" ) ) ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalSubTypeToNonOptional() ).isEqualTo( new Target.SubType( 94, "test" ) ); - } - - @ProcessorTest - public void testMappingEmptySubTypeOptionalToNonOptional() { - Source source = new Source(); - source.setOptionalSubTypeToNonOptional( Optional.empty() ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalSubTypeToNonOptional() ).isNull(); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromNonOptional() { - Target target = new Target(); - target.setOptionalSubTypeToNonOptional( new Target.SubType( 94, "test" ) ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalSubTypeToNonOptional() ).contains( new Source.SubType( 94, "test" ) ); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromNullNonOptional() { - Target target = new Target(); - target.setOptionalSubTypeToNonOptional( null ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalSubTypeToNonOptional() ).isEmpty(); - } - - @ProcessorTest - public void testMappingNonOptionalToSubTypeOptional() { - Source source = new Source(); - source.setNonOptionalSubTypeToOptional( new Source.SubType( 94, "test" ) ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getNonOptionalSubTypeToOptional() ).contains( new Target.SubType( 94, "test" ) ); - } - - @ProcessorTest - public void testMappingNullNonOptionalToSubTypeOptional() { - Source source = new Source(); - source.setNonOptionalSubTypeToOptional( null ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getNonOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromSubTypeOptional() { - Target target = new Target(); - target.setNonOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94, "test" ) ) ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getNonOptionalSubTypeToOptional() ).isEqualTo( new Source.SubType( 94, "test" ) ); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromEmptySubTypeOptional() { - Target target = new Target(); - target.setNonOptionalSubTypeToOptional( Optional.empty() ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getNonOptionalSubTypeToOptional() ).isNull(); - } - - @ProcessorTest - public void testMappingSubTypeOptionalToOptional() { - Source source = new Source(); - source.setOptionalSubTypeToOptional( Optional.of( new Source.SubType( 94, "test" ) ) ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalSubTypeToOptional() ).contains( new Target.SubType( 94, "test" ) ); - } - - @ProcessorTest - public void testMappingEmptySubTypeOptionalToOptional() { - Source source = new Source(); - source.setOptionalSubTypeToOptional( Optional.empty() ); - - Target target = OptionalTestMapper.INSTANCE.map( source ); - assertThat( target.getOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromOptional() { - Target target = new Target(); - target.setOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94, "test" ) ) ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalSubTypeToOptional() ).contains( new Source.SubType( 94, "test" ) ); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromEmptyOptional() { - Target target = new Target(); - target.setOptionalSubTypeToOptional( Optional.empty() ); - - Source source = OptionalTestMapper.INSTANCE.map( target ); - assertThat( source.getOptionalSubTypeToOptional() ).isEmpty(); + protected NullValueCheckAlwaysTests() { + super( NullValueCheckAlwaysOptionalTestMapper.class ); + } } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java deleted file mode 100644 index c6e8e3f0d3..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalTestMapper.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.optionalmapping; - -import org.mapstruct.InheritInverseConfiguration; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface OptionalTestMapper { - - OptionalTestMapper INSTANCE = Mappers.getMapper( OptionalTestMapper.class ); - - Target map(Source source); - - @InheritInverseConfiguration - Source map(Target target); - - @Mapping(source = "a", target = "b") - Target.SubType map(Source.SubType source); - - @InheritInverseConfiguration - Source.SubType map(Target.SubType source); - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java new file mode 100644 index 0000000000..1ed77e0f70 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java @@ -0,0 +1,13 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping; + +import org.mapstruct.Mapper; + +@Mapper +public interface SimpleOptionalTestMapper extends BaseOptionalTestMapper { + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java index 3e27dbbb02..061d19d13b 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java @@ -10,6 +10,14 @@ public class Source { + private final Optional constructorOptionalToNonOptional; + private final String constructorNonOptionalToOptional; + private final Optional constructorOptionalToOptional; + + private final Optional constructorOptionalSubTypeToNonOptional; + private final SubType constructorNonOptionalSubTypeToOptional; + private final Optional constructorOptionalSubTypeToOptional; + private Optional optionalToNonOptional; private String nonOptionalToOptional; private Optional optionalToOptional; @@ -18,6 +26,44 @@ public class Source { private SubType nonOptionalSubTypeToOptional; private Optional optionalSubTypeToOptional; + public Source(Optional constructorOptionalToNonOptional, + String constructorNonOptionalToOptional, + Optional constructorOptionalToOptional, + Optional constructorOptionalSubTypeToNonOptional, + SubType constructorNonOptionalSubTypeToOptional, + Optional constructorOptionalSubTypeToOptional) { + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalSubTypeToNonOptional = constructorOptionalSubTypeToNonOptional; + this.constructorNonOptionalSubTypeToOptional = constructorNonOptionalSubTypeToOptional; + this.constructorOptionalSubTypeToOptional = constructorOptionalSubTypeToOptional; + } + + public Optional getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public String getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public Optional getConstructorOptionalSubTypeToNonOptional() { + return constructorOptionalSubTypeToNonOptional; + } + + public SubType getConstructorNonOptionalSubTypeToOptional() { + return constructorNonOptionalSubTypeToOptional; + } + + public Optional getConstructorOptionalSubTypeToOptional() { + return constructorOptionalSubTypeToOptional; + } + public Optional getOptionalToNonOptional() { return optionalToNonOptional; } @@ -69,21 +115,15 @@ public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOpti public static class SubType { private final int value; - private final String a; - public SubType(int value, String a) { + public SubType(int value) { this.value = value; - this.a = a; } public int getValue() { return value; } - public String getA() { - return a; - } - @Override public boolean equals(Object o) { if ( this == o ) { @@ -93,12 +133,12 @@ public boolean equals(Object o) { return false; } SubType subType = (SubType) o; - return value == subType.value && Objects.equals( a, subType.a ); + return value == subType.value; } @Override public int hashCode() { - return Objects.hash( value, a ); + return Objects.hash( value ); } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java index 11cee32af6..5b5522ad2e 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java @@ -10,6 +10,14 @@ public class Target { + private final String constructorOptionalToNonOptional; + private final Optional constructorNonOptionalToOptional; + private final Optional constructorOptionalToOptional; + + private final SubType constructorOptionalSubTypeToNonOptional; + private final Optional constructorNonOptionalSubTypeToOptional; + private final Optional constructorOptionalSubTypeToOptional; + private String optionalToNonOptional; private Optional nonOptionalToOptional; private Optional optionalToOptional; @@ -18,6 +26,44 @@ public class Target { private Optional nonOptionalSubTypeToOptional; private Optional optionalSubTypeToOptional; + public Target(String constructorOptionalToNonOptional, + Optional constructorNonOptionalToOptional, + Optional constructorOptionalToOptional, + SubType constructorOptionalSubTypeToNonOptional, + Optional constructorNonOptionalSubTypeToOptional, + Optional constructorOptionalSubTypeToOptional) { + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalSubTypeToNonOptional = constructorOptionalSubTypeToNonOptional; + this.constructorNonOptionalSubTypeToOptional = constructorNonOptionalSubTypeToOptional; + this.constructorOptionalSubTypeToOptional = constructorOptionalSubTypeToOptional; + } + + public String getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public Optional getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public SubType getConstructorOptionalSubTypeToNonOptional() { + return constructorOptionalSubTypeToNonOptional; + } + + public Optional getConstructorNonOptionalSubTypeToOptional() { + return constructorNonOptionalSubTypeToOptional; + } + + public Optional getConstructorOptionalSubTypeToOptional() { + return constructorOptionalSubTypeToOptional; + } + public String getOptionalToNonOptional() { return optionalToNonOptional; } @@ -69,21 +115,15 @@ public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOpti public static class SubType { private final int value; - private final String b; - public SubType(int value, String b) { + public SubType(int value) { this.value = value; - this.b = b; } public int getValue() { return value; } - public String getB() { - return b; - } - @Override public boolean equals(Object o) { if ( this == o ) { @@ -93,12 +133,12 @@ public boolean equals(Object o) { return false; } SubType subType = (SubType) o; - return value == subType.value && Objects.equals( b, subType.b ); + return value == subType.value; } @Override public int hashCode() { - return Objects.hash( value, b ); + return Objects.hash( value ); } } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java deleted file mode 100644 index 4bb8cef311..0000000000 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/OptionalTestMapperImpl.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Optional; -import javax.annotation.processing.Generated; - -@Generated( - value = "org.mapstruct.ap.MappingProcessor", - date = "2023-03-02T00:33:34-0500", - comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" -) -public class OptionalTestMapperImpl implements OptionalTestMapper { - - @Override - public Target map(Source source) { - if ( source == null ) { - return null; - } - - Target target = new Target(); - - target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); - target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); - target.setOptionalToOptional( source.getOptionalToOptional() ); - target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); - target.setNonOptionalSubTypeToOptional( subTypeToSubTypeOptional( source.getNonOptionalSubTypeToOptional() ) ); - target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); - - return target; - } - - @Override - public Source map(Target target) { - if ( target == null ) { - return null; - } - - Source source = new Source(); - - source.setOptionalToNonOptional( stringToStringOptional( target.getOptionalToNonOptional() ) ); - source.setNonOptionalToOptional( stringOptionalToString( target.getNonOptionalToOptional() ) ); - source.setOptionalToOptional( target.getOptionalToOptional() ); - source.setOptionalSubTypeToNonOptional( subTypeToSubTypeOptional1( target.getOptionalSubTypeToNonOptional() ) ); - source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); - source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); - - return source; - } - - @Override - public Target.SubType map(Source.SubType source) { - if ( source == null ) { - return null; - } - - String b = null; - int value = 0; - - b = source.getA(); - value = source.getValue(); - - Target.SubType subType = new Target.SubType( value, b ); - - return subType; - } - - @Override - public Source.SubType map(Target.SubType source) { - if ( source == null ) { - return null; - } - - String a = null; - int value = 0; - - a = source.getB(); - value = source.getValue(); - - Source.SubType subType = new Source.SubType( value, a ); - - return subType; - } - - protected String stringOptionalToString(Optional optional) { - if ( optional == null ) { - return null; - } - - return optional.map( string -> string ).orElse( null ); - } - - protected Optional stringToStringOptional(String string) { - if ( string == null ) { - return Optional.empty(); - } - - String string1 = string; - return Optional.ofNullable( string1 ); - } - - protected Target.SubType subTypeOptionalToSubType(Optional optional) { - if ( optional == null ) { - return null; - } - - return optional.map( subType -> map( subType ) ).orElse( null ); - } - - protected Optional subTypeToSubTypeOptional(Source.SubType subType) { - if ( subType == null ) { - return Optional.empty(); - } - - Source.SubType subType1 = subType; - return Optional.ofNullable( map( subType1 ) ); - } - - protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { - if ( optional == null ) { - return Optional.empty(); - } - - return optional.map( subType -> map( subType ) ); - } - - protected Optional subTypeToSubTypeOptional1(Target.SubType subType) { - if ( subType == null ) { - return Optional.empty(); - } - - Target.SubType subType1 = subType; - return Optional.ofNullable( map( subType1 ) ); - } - - protected Source.SubType subTypeOptionalToSubType1(Optional optional) { - if ( optional == null ) { - return null; - } - - return optional.map( subType -> map( subType ) ).orElse( null ); - } - - protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { - if ( optional == null ) { - return Optional.empty(); - } - - return optional.map( subType -> map( subType ) ); - } -} From 966c4ad3a4ce20e28aa765f0567584df211fea37 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 2 Mar 2023 03:24:17 -0500 Subject: [PATCH 04/17] generated tests --- .../optionalmapping/OptionalMappingTest.java | 16 +- ...alueCheckAlwaysOptionalTestMapperImpl.java | 267 ++++++++++++++++++ .../SimpleOptionalTestMapperImpl.java | 171 +++++++++++ 3 files changed, 446 insertions(+), 8 deletions(-) create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java index 0c9eb0965a..41655f3fff 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java @@ -6,12 +6,9 @@ package org.mapstruct.ap.test.optionalmapping; import org.junit.jupiter.api.Nested; -import org.mapstruct.ap.testutil.ProcessorTest; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.WithClasses; - -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; +import org.mapstruct.ap.testutil.runner.GeneratedSource; /** * Test for mapping logic from {@link org.mapstruct.ap.internal.model.OptionalMappingMethod}. @@ -20,13 +17,13 @@ */ public class OptionalMappingTest { -// @RegisterExtension -// final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalTestMapper.class ); - @Nested @WithClasses({ SimpleOptionalTestMapper.class, BaseOptionalTestMapper.class, Source.class, Target.class }) class SimpleTests extends BaseOptionalMappingTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( SimpleOptionalTestMapper.class ); + protected SimpleTests() { super( SimpleOptionalTestMapper.class ); } @@ -36,6 +33,9 @@ protected SimpleTests() { @WithClasses({ NullValueCheckAlwaysOptionalTestMapper.class, BaseOptionalTestMapper.class, Source.class, Target.class }) class NullValueCheckAlwaysTests extends BaseOptionalMappingTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( NullValueCheckAlwaysOptionalTestMapper.class ); + protected NullValueCheckAlwaysTests() { super( NullValueCheckAlwaysOptionalTestMapper.class ); } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java new file mode 100644 index 0000000000..b81b15755a --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java @@ -0,0 +1,267 @@ +package org.mapstruct.ap.test.optionalmapping; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-03-02T03:14:36-0500", + comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" +) +public class NullValueCheckAlwaysOptionalTestMapperImpl implements NullValueCheckAlwaysOptionalTestMapper { + + @Override + public Target toTarget(Source source) { + if ( source == null ) { + return null; + } + + String constructorOptionalToNonOptional = null; + Optional constructorNonOptionalToOptional = null; + Optional constructorOptionalToOptional = null; + Target.SubType constructorOptionalSubTypeToNonOptional = null; + Optional constructorNonOptionalSubTypeToOptional = null; + Optional constructorOptionalSubTypeToOptional = null; + + if ( source.getConstructorOptionalToNonOptional() != null ) { + constructorOptionalToNonOptional = stringOptionalToString( source.getConstructorOptionalToNonOptional() ); + } + if ( source.getConstructorNonOptionalToOptional() != null ) { + constructorNonOptionalToOptional = stringToStringOptional( source.getConstructorNonOptionalToOptional() ); + } + else { + constructorNonOptionalToOptional = Optional.empty(); + } + if ( source.getConstructorOptionalToOptional() != null ) { + constructorOptionalToOptional = source.getConstructorOptionalToOptional(); + } + else { + constructorOptionalToOptional = Optional.empty(); + } + if ( source.getConstructorOptionalSubTypeToNonOptional() != null ) { + constructorOptionalSubTypeToNonOptional = subTypeOptionalToSubType( source.getConstructorOptionalSubTypeToNonOptional() ); + } + if ( source.getConstructorNonOptionalSubTypeToOptional() != null ) { + constructorNonOptionalSubTypeToOptional = subTypeToSubTypeOptional( source.getConstructorNonOptionalSubTypeToOptional() ); + } + else { + constructorNonOptionalSubTypeToOptional = Optional.empty(); + } + if ( source.getConstructorOptionalSubTypeToOptional() != null ) { + constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.getConstructorOptionalSubTypeToOptional() ); + } + else { + constructorOptionalSubTypeToOptional = Optional.empty(); + } + + Target target = new Target( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); + + if ( source.getOptionalToNonOptional() != null ) { + target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); + } + if ( source.getNonOptionalToOptional() != null ) { + target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); + } + else { + target.setNonOptionalToOptional( Optional.empty() ); + } + if ( source.getOptionalToOptional() != null ) { + target.setOptionalToOptional( source.getOptionalToOptional() ); + } + else { + target.setOptionalToOptional( Optional.empty() ); + } + if ( source.getOptionalSubTypeToNonOptional() != null ) { + target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); + } + if ( source.getNonOptionalSubTypeToOptional() != null ) { + target.setNonOptionalSubTypeToOptional( subTypeToSubTypeOptional( source.getNonOptionalSubTypeToOptional() ) ); + } + else { + target.setNonOptionalSubTypeToOptional( Optional.empty() ); + } + if ( source.getOptionalSubTypeToOptional() != null ) { + target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); + } + else { + target.setOptionalSubTypeToOptional( Optional.empty() ); + } + + return target; + } + + @Override + public Source fromTarget(Target target) { + if ( target == null ) { + return null; + } + + Optional constructorOptionalToNonOptional = null; + String constructorNonOptionalToOptional = null; + Optional constructorOptionalToOptional = null; + Optional constructorOptionalSubTypeToNonOptional = null; + Source.SubType constructorNonOptionalSubTypeToOptional = null; + Optional constructorOptionalSubTypeToOptional = null; + + if ( target.getConstructorOptionalToNonOptional() != null ) { + constructorOptionalToNonOptional = stringToStringOptional( target.getConstructorOptionalToNonOptional() ); + } + else { + constructorOptionalToNonOptional = Optional.empty(); + } + if ( target.getConstructorNonOptionalToOptional() != null ) { + constructorNonOptionalToOptional = stringOptionalToString( target.getConstructorNonOptionalToOptional() ); + } + if ( target.getConstructorOptionalToOptional() != null ) { + constructorOptionalToOptional = target.getConstructorOptionalToOptional(); + } + else { + constructorOptionalToOptional = Optional.empty(); + } + if ( target.getConstructorOptionalSubTypeToNonOptional() != null ) { + constructorOptionalSubTypeToNonOptional = subTypeToSubTypeOptional1( target.getConstructorOptionalSubTypeToNonOptional() ); + } + else { + constructorOptionalSubTypeToNonOptional = Optional.empty(); + } + if ( target.getConstructorNonOptionalSubTypeToOptional() != null ) { + constructorNonOptionalSubTypeToOptional = subTypeOptionalToSubType1( target.getConstructorNonOptionalSubTypeToOptional() ); + } + if ( target.getConstructorOptionalSubTypeToOptional() != null ) { + constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.getConstructorOptionalSubTypeToOptional() ); + } + else { + constructorOptionalSubTypeToOptional = Optional.empty(); + } + + Source source = new Source( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); + + if ( target.getOptionalToNonOptional() != null ) { + source.setOptionalToNonOptional( stringToStringOptional( target.getOptionalToNonOptional() ) ); + } + else { + source.setOptionalToNonOptional( Optional.empty() ); + } + if ( target.getNonOptionalToOptional() != null ) { + source.setNonOptionalToOptional( stringOptionalToString( target.getNonOptionalToOptional() ) ); + } + if ( target.getOptionalToOptional() != null ) { + source.setOptionalToOptional( target.getOptionalToOptional() ); + } + else { + source.setOptionalToOptional( Optional.empty() ); + } + if ( target.getOptionalSubTypeToNonOptional() != null ) { + source.setOptionalSubTypeToNonOptional( subTypeToSubTypeOptional1( target.getOptionalSubTypeToNonOptional() ) ); + } + else { + source.setOptionalSubTypeToNonOptional( Optional.empty() ); + } + if ( target.getNonOptionalSubTypeToOptional() != null ) { + source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); + } + if ( target.getOptionalSubTypeToOptional() != null ) { + source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); + } + else { + source.setOptionalSubTypeToOptional( Optional.empty() ); + } + + return source; + } + + protected String stringOptionalToString(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( string -> string ).orElse( null ); + } + + protected Optional stringToStringOptional(String string) { + if ( string == null ) { + return Optional.empty(); + } + + String string1 = string; + return Optional.ofNullable( string1 ); + } + + protected Target.SubType subTypeToSubType(Source.SubType subType) { + if ( subType == null ) { + return null; + } + + int value = 0; + + value = subType.getValue(); + + Target.SubType subType1 = new Target.SubType( value ); + + return subType1; + } + + protected Target.SubType subTypeOptionalToSubType(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + } + + protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Source.SubType subType1 = subType; + return Optional.ofNullable( subTypeToSubType( subType1 ) ); + } + + protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + if ( optional == null ) { + return Optional.empty(); + } + + return optional.map( subType -> subTypeToSubType( subType ) ); + } + + protected Source.SubType subTypeToSubType1(Target.SubType subType) { + if ( subType == null ) { + return null; + } + + int value = 0; + + value = subType.getValue(); + + Source.SubType subType1 = new Source.SubType( value ); + + return subType1; + } + + protected Optional subTypeToSubTypeOptional1(Target.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Target.SubType subType1 = subType; + return Optional.ofNullable( subTypeToSubType1( subType1 ) ); + } + + protected Source.SubType subTypeOptionalToSubType1(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); + } + + protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { + if ( optional == null ) { + return Optional.empty(); + } + + return optional.map( subType -> subTypeToSubType1( subType ) ); + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java new file mode 100644 index 0000000000..c64b747a78 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java @@ -0,0 +1,171 @@ +package org.mapstruct.ap.test.optionalmapping; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-03-02T03:14:40-0500", + comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" +) +public class SimpleOptionalTestMapperImpl implements SimpleOptionalTestMapper { + + @Override + public Target toTarget(Source source) { + if ( source == null ) { + return null; + } + + String constructorOptionalToNonOptional = null; + Optional constructorNonOptionalToOptional = null; + Optional constructorOptionalToOptional = null; + Target.SubType constructorOptionalSubTypeToNonOptional = null; + Optional constructorNonOptionalSubTypeToOptional = null; + Optional constructorOptionalSubTypeToOptional = null; + + constructorOptionalToNonOptional = stringOptionalToString( source.getConstructorOptionalToNonOptional() ); + constructorNonOptionalToOptional = stringToStringOptional( source.getConstructorNonOptionalToOptional() ); + constructorOptionalToOptional = source.getConstructorOptionalToOptional(); + constructorOptionalSubTypeToNonOptional = subTypeOptionalToSubType( source.getConstructorOptionalSubTypeToNonOptional() ); + constructorNonOptionalSubTypeToOptional = subTypeToSubTypeOptional( source.getConstructorNonOptionalSubTypeToOptional() ); + constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.getConstructorOptionalSubTypeToOptional() ); + + Target target = new Target( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); + + target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); + target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); + target.setOptionalToOptional( source.getOptionalToOptional() ); + target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); + target.setNonOptionalSubTypeToOptional( subTypeToSubTypeOptional( source.getNonOptionalSubTypeToOptional() ) ); + target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); + + return target; + } + + @Override + public Source fromTarget(Target target) { + if ( target == null ) { + return null; + } + + Optional constructorOptionalToNonOptional = null; + String constructorNonOptionalToOptional = null; + Optional constructorOptionalToOptional = null; + Optional constructorOptionalSubTypeToNonOptional = null; + Source.SubType constructorNonOptionalSubTypeToOptional = null; + Optional constructorOptionalSubTypeToOptional = null; + + constructorOptionalToNonOptional = stringToStringOptional( target.getConstructorOptionalToNonOptional() ); + constructorNonOptionalToOptional = stringOptionalToString( target.getConstructorNonOptionalToOptional() ); + constructorOptionalToOptional = target.getConstructorOptionalToOptional(); + constructorOptionalSubTypeToNonOptional = subTypeToSubTypeOptional1( target.getConstructorOptionalSubTypeToNonOptional() ); + constructorNonOptionalSubTypeToOptional = subTypeOptionalToSubType1( target.getConstructorNonOptionalSubTypeToOptional() ); + constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.getConstructorOptionalSubTypeToOptional() ); + + Source source = new Source( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); + + source.setOptionalToNonOptional( stringToStringOptional( target.getOptionalToNonOptional() ) ); + source.setNonOptionalToOptional( stringOptionalToString( target.getNonOptionalToOptional() ) ); + source.setOptionalToOptional( target.getOptionalToOptional() ); + source.setOptionalSubTypeToNonOptional( subTypeToSubTypeOptional1( target.getOptionalSubTypeToNonOptional() ) ); + source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); + source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); + + return source; + } + + protected String stringOptionalToString(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( string -> string ).orElse( null ); + } + + protected Optional stringToStringOptional(String string) { + if ( string == null ) { + return Optional.empty(); + } + + String string1 = string; + return Optional.ofNullable( string1 ); + } + + protected Target.SubType subTypeToSubType(Source.SubType subType) { + if ( subType == null ) { + return null; + } + + int value = 0; + + value = subType.getValue(); + + Target.SubType subType1 = new Target.SubType( value ); + + return subType1; + } + + protected Target.SubType subTypeOptionalToSubType(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + } + + protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Source.SubType subType1 = subType; + return Optional.ofNullable( subTypeToSubType( subType1 ) ); + } + + protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + if ( optional == null ) { + return Optional.empty(); + } + + return optional.map( subType -> subTypeToSubType( subType ) ); + } + + protected Source.SubType subTypeToSubType1(Target.SubType subType) { + if ( subType == null ) { + return null; + } + + int value = 0; + + value = subType.getValue(); + + Source.SubType subType1 = new Source.SubType( value ); + + return subType1; + } + + protected Optional subTypeToSubTypeOptional1(Target.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Target.SubType subType1 = subType; + return Optional.ofNullable( subTypeToSubType1( subType1 ) ); + } + + protected Source.SubType subTypeOptionalToSubType1(Optional optional) { + if ( optional == null ) { + return null; + } + + return optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); + } + + protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { + if ( optional == null ) { + return Optional.empty(); + } + + return optional.map( subType -> subTypeToSubType1( subType ) ); + } +} From 9309c388dd80bd8d99fe930e0106fb380ea9fe67 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 2 Mar 2023 23:44:38 -0500 Subject: [PATCH 05/17] optional check alongside null check --- .../org/mapstruct/NullValueCheckStrategy.java | 4 +- .../ap/internal/model/macro/CommonMacros.ftl | 2 +- .../BaseOptionalMappingTest.java | 17 +++-- .../BaseOptionalTestMapper.java | 5 ++ .../optionalmapping/OptionalMappingTest.java | 64 +++++++++++++++++-- .../ap/test/optionalmapping/Source.java | 20 ++++++ .../ap/test/optionalmapping/Target.java | 32 ++++++++++ ...alueCheckAlwaysOptionalTestMapperImpl.java | 57 ++++++++++++----- .../SimpleOptionalTestMapperImpl.java | 11 +++- 9 files changed, 181 insertions(+), 31 deletions(-) diff --git a/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java b/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java index 22dba7c58b..653c2eb4ff 100644 --- a/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java +++ b/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java @@ -21,7 +21,7 @@ public enum NullValueCheckStrategy { /** - * This option includes a null check. When: + * This option includes a null check as well as an empty check for Optional type. When: *
*
*
    @@ -36,7 +36,7 @@ public enum NullValueCheckStrategy { ON_IMPLICIT_CONVERSION, /** - * This option always includes a null check. + * This option always includes a null check as well as an empty check for Optional type. */ ALWAYS; diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl index 55db5176ed..6fc1e72df7 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl @@ -22,7 +22,7 @@ } <@elseDefaultAssignment/> <#elseif includeSourceNullCheck || ext.defaultValueAssignment??> - if ( <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference} != null ) { + if ( <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference} != null<#if sourceType.optionalType> && <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference}.isPresent() ) { <#nested> } <@elseDefaultAssignment/> diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java index 4f96432227..b66b46f057 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping; import java.util.Optional; @@ -8,17 +13,17 @@ import static org.assertj.core.api.Assertions.assertThat; public abstract class BaseOptionalMappingTest { - + private final Class mapperClass; private BaseOptionalTestMapper mapper; protected BaseOptionalMappingTest(Class mapperClass) { this.mapperClass = mapperClass; } - - private BaseOptionalTestMapper getMapper() { + + protected BaseOptionalTestMapper getMapper() { if (this.mapper == null) { - this.mapper = Mappers.getMapper(mapperClass); + this.mapper = Mappers.getMapper( mapperClass ); } return this.mapper; } @@ -238,7 +243,7 @@ public void testReverseMappingSubTypeOptionalFromEmptyOptional() { Source source = getMapper().fromTarget( target ); assertThat( source.getOptionalSubTypeToOptional() ).isEmpty(); } - + @ProcessorTest public void testConstructorMappingSimpleOptionalToNonOptional() { Source source = new Source( Optional.of( "some value" ), null, null, null, null, null ); @@ -430,5 +435,5 @@ public void testReverseConstructorMappingSubTypeOptionalFromEmptyOptional() { Source source = getMapper().fromTarget( target ); assertThat( source.getConstructorOptionalSubTypeToOptional() ).isEmpty(); } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java index 693240a24d..2cd4d943d7 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping; public interface BaseOptionalTestMapper { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java index 41655f3fff..a34aba58bc 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java @@ -5,11 +5,16 @@ */ package org.mapstruct.ap.test.optionalmapping; +import java.util.Optional; + import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.extension.RegisterExtension; +import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.runner.GeneratedSource; +import static org.assertj.core.api.Assertions.assertThat; + /** * Test for mapping logic from {@link org.mapstruct.ap.internal.model.OptionalMappingMethod}. * @@ -18,27 +23,78 @@ public class OptionalMappingTest { @Nested - @WithClasses({ SimpleOptionalTestMapper.class, BaseOptionalTestMapper.class, Source.class, Target.class }) + @WithClasses({ + SimpleOptionalTestMapper.class, + BaseOptionalTestMapper.class, + Source.class, + Target.class }) class SimpleTests extends BaseOptionalMappingTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( SimpleOptionalTestMapper.class ); + final GeneratedSource generatedSource = + new GeneratedSource().addComparisonToFixtureFor( SimpleOptionalTestMapper.class ); protected SimpleTests() { super( SimpleOptionalTestMapper.class ); } + + @ProcessorTest + public void testEmptyMonitoredOptionalStillCallsSetter() { + Source source = new Source( null, null, null, null, null, null ); + source.setMonitoredOptionalToString( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getMonitoredOptionalToString() ).isNull(); + assertThat( target.isMonitoredOptionalToStringWasCalled() ).isTrue(); + } + + @ProcessorTest + public void testEmptyMonitoredSubTypeOptionalStillCallsSetter() { + Source source = new Source( null, null, null, null, null, null ); + source.setMonitoredOptionalSubTypeToSubType( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getMonitoredOptionalSubTypeToSubType() ).isNull(); + assertThat( target.isMonitoredOptionalSubTypeToSubTypeWasCalled() ).isTrue(); + } + } @Nested - @WithClasses({ NullValueCheckAlwaysOptionalTestMapper.class, BaseOptionalTestMapper.class, Source.class, Target.class }) + @WithClasses({ + NullValueCheckAlwaysOptionalTestMapper.class, + BaseOptionalTestMapper.class, + Source.class, + Target.class }) class NullValueCheckAlwaysTests extends BaseOptionalMappingTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( NullValueCheckAlwaysOptionalTestMapper.class ); + final GeneratedSource generatedSource = + new GeneratedSource().addComparisonToFixtureFor( NullValueCheckAlwaysOptionalTestMapper.class ); protected NullValueCheckAlwaysTests() { super( NullValueCheckAlwaysOptionalTestMapper.class ); } + + @ProcessorTest + public void testEmptyMonitoredOptionalDoesNotCallSetter() { + Source source = new Source( null, null, null, null, null, null ); + source.setMonitoredOptionalToString( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getMonitoredOptionalToString() ).isNull(); + assertThat( target.isMonitoredOptionalToStringWasCalled() ).isFalse(); + } + + @ProcessorTest + public void testEmptyMonitoredSubTypeOptionalDoesNotCallSetter() { + Source source = new Source( null, null, null, null, null, null ); + source.setMonitoredOptionalSubTypeToSubType( Optional.empty() ); + + Target target = getMapper().toTarget( source ); + assertThat( target.getMonitoredOptionalSubTypeToSubType() ).isNull(); + assertThat( target.isMonitoredOptionalSubTypeToSubTypeWasCalled() ).isFalse(); + } } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java index 061d19d13b..b8123ff848 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java @@ -26,6 +26,9 @@ public class Source { private SubType nonOptionalSubTypeToOptional; private Optional optionalSubTypeToOptional; + private Optional monitoredOptionalToString; + private Optional monitoredOptionalSubTypeToSubType; + public Source(Optional constructorOptionalToNonOptional, String constructorNonOptionalToOptional, Optional constructorOptionalToOptional, @@ -112,6 +115,23 @@ public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOpti this.optionalSubTypeToOptional = optionalSubTypeToOptional; } + public Optional getMonitoredOptionalToString() { + return monitoredOptionalToString; + } + + public void setMonitoredOptionalToString(Optional monitoredOptionalToString) { + this.monitoredOptionalToString = monitoredOptionalToString; + } + + public Optional getMonitoredOptionalSubTypeToSubType() { + return monitoredOptionalSubTypeToSubType; + } + + public void setMonitoredOptionalSubTypeToSubType( + Optional monitoredOptionalSubTypeToSubType) { + this.monitoredOptionalSubTypeToSubType = monitoredOptionalSubTypeToSubType; + } + public static class SubType { private final int value; diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java index 5b5522ad2e..46f1e4c20b 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java @@ -26,6 +26,11 @@ public class Target { private Optional nonOptionalSubTypeToOptional; private Optional optionalSubTypeToOptional; + private String monitoredOptionalToString; + private boolean monitoredOptionalToStringWasCalled; + private SubType monitoredOptionalSubTypeToSubType; + private boolean monitoredOptionalSubTypeToSubTypeWasCalled; + public Target(String constructorOptionalToNonOptional, Optional constructorNonOptionalToOptional, Optional constructorOptionalToOptional, @@ -112,6 +117,33 @@ public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOpti this.optionalSubTypeToOptional = optionalSubTypeToOptional; } + public String getMonitoredOptionalToString() { + return monitoredOptionalToString; + } + + public void setMonitoredOptionalToString(String monitoredOptionalToString) { + this.monitoredOptionalToStringWasCalled = true; + this.monitoredOptionalToString = monitoredOptionalToString; + } + + public SubType getMonitoredOptionalSubTypeToSubType() { + return monitoredOptionalSubTypeToSubType; + } + + public void setMonitoredOptionalSubTypeToSubType( + SubType monitoredOptionalSubTypeToSubType) { + this.monitoredOptionalSubTypeToSubTypeWasCalled = true; + this.monitoredOptionalSubTypeToSubType = monitoredOptionalSubTypeToSubType; + } + + public boolean isMonitoredOptionalToStringWasCalled() { + return monitoredOptionalToStringWasCalled; + } + + public boolean isMonitoredOptionalSubTypeToSubTypeWasCalled() { + return monitoredOptionalSubTypeToSubTypeWasCalled; + } + public static class SubType { private final int value; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java index b81b15755a..270419028a 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping; import java.util.Optional; @@ -5,7 +10,7 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-03-02T03:14:36-0500", + date = "2023-03-02T23:19:14-0500", comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" ) public class NullValueCheckAlwaysOptionalTestMapperImpl implements NullValueCheckAlwaysOptionalTestMapper { @@ -23,7 +28,7 @@ public Target toTarget(Source source) { Optional constructorNonOptionalSubTypeToOptional = null; Optional constructorOptionalSubTypeToOptional = null; - if ( source.getConstructorOptionalToNonOptional() != null ) { + if ( source.getConstructorOptionalToNonOptional() != null && source.getConstructorOptionalToNonOptional().isPresent() ) { constructorOptionalToNonOptional = stringOptionalToString( source.getConstructorOptionalToNonOptional() ); } if ( source.getConstructorNonOptionalToOptional() != null ) { @@ -32,13 +37,13 @@ public Target toTarget(Source source) { else { constructorNonOptionalToOptional = Optional.empty(); } - if ( source.getConstructorOptionalToOptional() != null ) { + if ( source.getConstructorOptionalToOptional() != null && source.getConstructorOptionalToOptional().isPresent() ) { constructorOptionalToOptional = source.getConstructorOptionalToOptional(); } else { constructorOptionalToOptional = Optional.empty(); } - if ( source.getConstructorOptionalSubTypeToNonOptional() != null ) { + if ( source.getConstructorOptionalSubTypeToNonOptional() != null && source.getConstructorOptionalSubTypeToNonOptional().isPresent() ) { constructorOptionalSubTypeToNonOptional = subTypeOptionalToSubType( source.getConstructorOptionalSubTypeToNonOptional() ); } if ( source.getConstructorNonOptionalSubTypeToOptional() != null ) { @@ -47,7 +52,7 @@ public Target toTarget(Source source) { else { constructorNonOptionalSubTypeToOptional = Optional.empty(); } - if ( source.getConstructorOptionalSubTypeToOptional() != null ) { + if ( source.getConstructorOptionalSubTypeToOptional() != null && source.getConstructorOptionalSubTypeToOptional().isPresent() ) { constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.getConstructorOptionalSubTypeToOptional() ); } else { @@ -56,7 +61,7 @@ public Target toTarget(Source source) { Target target = new Target( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); - if ( source.getOptionalToNonOptional() != null ) { + if ( source.getOptionalToNonOptional() != null && source.getOptionalToNonOptional().isPresent() ) { target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); } if ( source.getNonOptionalToOptional() != null ) { @@ -65,13 +70,13 @@ public Target toTarget(Source source) { else { target.setNonOptionalToOptional( Optional.empty() ); } - if ( source.getOptionalToOptional() != null ) { + if ( source.getOptionalToOptional() != null && source.getOptionalToOptional().isPresent() ) { target.setOptionalToOptional( source.getOptionalToOptional() ); } else { target.setOptionalToOptional( Optional.empty() ); } - if ( source.getOptionalSubTypeToNonOptional() != null ) { + if ( source.getOptionalSubTypeToNonOptional() != null && source.getOptionalSubTypeToNonOptional().isPresent() ) { target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); } if ( source.getNonOptionalSubTypeToOptional() != null ) { @@ -80,12 +85,18 @@ public Target toTarget(Source source) { else { target.setNonOptionalSubTypeToOptional( Optional.empty() ); } - if ( source.getOptionalSubTypeToOptional() != null ) { + if ( source.getOptionalSubTypeToOptional() != null && source.getOptionalSubTypeToOptional().isPresent() ) { target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); } else { target.setOptionalSubTypeToOptional( Optional.empty() ); } + if ( source.getMonitoredOptionalToString() != null && source.getMonitoredOptionalToString().isPresent() ) { + target.setMonitoredOptionalToString( stringOptionalToString( source.getMonitoredOptionalToString() ) ); + } + if ( source.getMonitoredOptionalSubTypeToSubType() != null && source.getMonitoredOptionalSubTypeToSubType().isPresent() ) { + target.setMonitoredOptionalSubTypeToSubType( subTypeOptionalToSubType( source.getMonitoredOptionalSubTypeToSubType() ) ); + } return target; } @@ -109,10 +120,10 @@ public Source fromTarget(Target target) { else { constructorOptionalToNonOptional = Optional.empty(); } - if ( target.getConstructorNonOptionalToOptional() != null ) { + if ( target.getConstructorNonOptionalToOptional() != null && target.getConstructorNonOptionalToOptional().isPresent() ) { constructorNonOptionalToOptional = stringOptionalToString( target.getConstructorNonOptionalToOptional() ); } - if ( target.getConstructorOptionalToOptional() != null ) { + if ( target.getConstructorOptionalToOptional() != null && target.getConstructorOptionalToOptional().isPresent() ) { constructorOptionalToOptional = target.getConstructorOptionalToOptional(); } else { @@ -124,10 +135,10 @@ public Source fromTarget(Target target) { else { constructorOptionalSubTypeToNonOptional = Optional.empty(); } - if ( target.getConstructorNonOptionalSubTypeToOptional() != null ) { + if ( target.getConstructorNonOptionalSubTypeToOptional() != null && target.getConstructorNonOptionalSubTypeToOptional().isPresent() ) { constructorNonOptionalSubTypeToOptional = subTypeOptionalToSubType1( target.getConstructorNonOptionalSubTypeToOptional() ); } - if ( target.getConstructorOptionalSubTypeToOptional() != null ) { + if ( target.getConstructorOptionalSubTypeToOptional() != null && target.getConstructorOptionalSubTypeToOptional().isPresent() ) { constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.getConstructorOptionalSubTypeToOptional() ); } else { @@ -142,10 +153,10 @@ public Source fromTarget(Target target) { else { source.setOptionalToNonOptional( Optional.empty() ); } - if ( target.getNonOptionalToOptional() != null ) { + if ( target.getNonOptionalToOptional() != null && target.getNonOptionalToOptional().isPresent() ) { source.setNonOptionalToOptional( stringOptionalToString( target.getNonOptionalToOptional() ) ); } - if ( target.getOptionalToOptional() != null ) { + if ( target.getOptionalToOptional() != null && target.getOptionalToOptional().isPresent() ) { source.setOptionalToOptional( target.getOptionalToOptional() ); } else { @@ -157,15 +168,27 @@ public Source fromTarget(Target target) { else { source.setOptionalSubTypeToNonOptional( Optional.empty() ); } - if ( target.getNonOptionalSubTypeToOptional() != null ) { + if ( target.getNonOptionalSubTypeToOptional() != null && target.getNonOptionalSubTypeToOptional().isPresent() ) { source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); } - if ( target.getOptionalSubTypeToOptional() != null ) { + if ( target.getOptionalSubTypeToOptional() != null && target.getOptionalSubTypeToOptional().isPresent() ) { source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); } else { source.setOptionalSubTypeToOptional( Optional.empty() ); } + if ( target.getMonitoredOptionalToString() != null ) { + source.setMonitoredOptionalToString( stringToStringOptional( target.getMonitoredOptionalToString() ) ); + } + else { + source.setMonitoredOptionalToString( Optional.empty() ); + } + if ( target.getMonitoredOptionalSubTypeToSubType() != null ) { + source.setMonitoredOptionalSubTypeToSubType( subTypeToSubTypeOptional1( target.getMonitoredOptionalSubTypeToSubType() ) ); + } + else { + source.setMonitoredOptionalSubTypeToSubType( Optional.empty() ); + } return source; } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java index c64b747a78..919cb196ba 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping; import java.util.Optional; @@ -5,7 +10,7 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-03-02T03:14:40-0500", + date = "2023-03-02T23:19:18-0500", comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" ) public class SimpleOptionalTestMapperImpl implements SimpleOptionalTestMapper { @@ -38,6 +43,8 @@ public Target toTarget(Source source) { target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); target.setNonOptionalSubTypeToOptional( subTypeToSubTypeOptional( source.getNonOptionalSubTypeToOptional() ) ); target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); + target.setMonitoredOptionalToString( stringOptionalToString( source.getMonitoredOptionalToString() ) ); + target.setMonitoredOptionalSubTypeToSubType( subTypeOptionalToSubType( source.getMonitoredOptionalSubTypeToSubType() ) ); return target; } @@ -70,6 +77,8 @@ public Source fromTarget(Target target) { source.setOptionalSubTypeToNonOptional( subTypeToSubTypeOptional1( target.getOptionalSubTypeToNonOptional() ) ); source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); + source.setMonitoredOptionalToString( stringToStringOptional( target.getMonitoredOptionalToString() ) ); + source.setMonitoredOptionalSubTypeToSubType( subTypeToSubTypeOptional1( target.getMonitoredOptionalSubTypeToSubType() ) ); return source; } From 35fd4aacc9d2a2dcd0821a9209e0e1d74bdd350c Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Fri, 3 Mar 2023 00:03:24 -0500 Subject: [PATCH 06/17] public field tests --- .../BaseOptionalMappingTest.java | 27 +++++++++++++++++++ .../optionalmapping/OptionalMappingTest.java | 18 +++++++++++++ .../ap/test/optionalmapping/Source.java | 3 +++ .../ap/test/optionalmapping/Target.java | 3 +++ ...alueCheckAlwaysOptionalTestMapperImpl.java | 23 +++++++++++++++- .../SimpleOptionalTestMapperImpl.java | 6 ++++- 6 files changed, 78 insertions(+), 2 deletions(-) diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java index b66b46f057..8c14498366 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java @@ -436,4 +436,31 @@ public void testReverseConstructorMappingSubTypeOptionalFromEmptyOptional() { assertThat( source.getConstructorOptionalSubTypeToOptional() ).isEmpty(); } + @ProcessorTest + public void testMappingPublicSubTypeOptionalToOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.publicOptionalSubTypeToOptional = Optional.of( new Source.SubType( 9 ) ); + + Target target = getMapper().toTarget( source ); + assertThat( target.publicOptionalSubTypeToOptional ).contains( new Target.SubType( 9 ) ); + } + + @ProcessorTest + public void testMappingPublicEmptySubTypeOptionalToOptional() { + Source source = new Source( null, null, null, null, null, null ); + source.publicOptionalSubTypeToOptional = Optional.empty(); + + Target target = getMapper().toTarget( source ); + assertThat( target.publicOptionalSubTypeToOptional ).isEmpty(); + } + + @ProcessorTest + public void testMappingPublicOptionalToNonOptionalWithDefaultSetsToNewValue() { + Source source = new Source( null, null, null, null, null, null ); + source.publicOptionalToNonOptionalWithDefault = Optional.of( "new" ); + + Target target = getMapper().toTarget( source ); + assertThat( target.publicOptionalToNonOptionalWithDefault ).isEqualTo( "new" ); + } + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java index a34aba58bc..1725cd3b68 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java @@ -58,6 +58,15 @@ public void testEmptyMonitoredSubTypeOptionalStillCallsSetter() { assertThat( target.isMonitoredOptionalSubTypeToSubTypeWasCalled() ).isTrue(); } + @ProcessorTest + public void testMappingEmptyPublicOptionalToNonOptionalWithDefaultSetsToNull() { + Source source = new Source( null, null, null, null, null, null ); + source.publicOptionalToNonOptionalWithDefault = Optional.empty(); + + Target target = getMapper().toTarget( source ); + assertThat( target.publicOptionalToNonOptionalWithDefault ).isEqualTo( null ); + } + } @Nested @@ -95,6 +104,15 @@ public void testEmptyMonitoredSubTypeOptionalDoesNotCallSetter() { assertThat( target.getMonitoredOptionalSubTypeToSubType() ).isNull(); assertThat( target.isMonitoredOptionalSubTypeToSubTypeWasCalled() ).isFalse(); } + + @ProcessorTest + public void testMappingEmptyPublicOptionalToNonOptionalWithDefaultDoesNotOverwrite() { + Source source = new Source( null, null, null, null, null, null ); + source.publicOptionalToNonOptionalWithDefault = Optional.empty(); + + Target target = getMapper().toTarget( source ); + assertThat( target.publicOptionalToNonOptionalWithDefault ).isEqualTo( "DEFAULT" ); + } } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java index b8123ff848..6495b03ed6 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java @@ -29,6 +29,9 @@ public class Source { private Optional monitoredOptionalToString; private Optional monitoredOptionalSubTypeToSubType; + public Optional publicOptionalSubTypeToOptional; + public Optional publicOptionalToNonOptionalWithDefault; + public Source(Optional constructorOptionalToNonOptional, String constructorNonOptionalToOptional, Optional constructorOptionalToOptional, diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java index 46f1e4c20b..14a6262283 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java @@ -31,6 +31,9 @@ public class Target { private SubType monitoredOptionalSubTypeToSubType; private boolean monitoredOptionalSubTypeToSubTypeWasCalled; + public Optional publicOptionalSubTypeToOptional; + public String publicOptionalToNonOptionalWithDefault = "DEFAULT"; + public Target(String constructorOptionalToNonOptional, Optional constructorNonOptionalToOptional, Optional constructorOptionalToOptional, diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java index 270419028a..6561d6d8f4 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java @@ -10,7 +10,7 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-03-02T23:19:14-0500", + date = "2023-03-03T00:01:17-0500", comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" ) public class NullValueCheckAlwaysOptionalTestMapperImpl implements NullValueCheckAlwaysOptionalTestMapper { @@ -97,6 +97,15 @@ public Target toTarget(Source source) { if ( source.getMonitoredOptionalSubTypeToSubType() != null && source.getMonitoredOptionalSubTypeToSubType().isPresent() ) { target.setMonitoredOptionalSubTypeToSubType( subTypeOptionalToSubType( source.getMonitoredOptionalSubTypeToSubType() ) ); } + if ( source.publicOptionalSubTypeToOptional != null && source.publicOptionalSubTypeToOptional.isPresent() ) { + target.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.publicOptionalSubTypeToOptional ); + } + else { + target.publicOptionalSubTypeToOptional = Optional.empty(); + } + if ( source.publicOptionalToNonOptionalWithDefault != null && source.publicOptionalToNonOptionalWithDefault.isPresent() ) { + target.publicOptionalToNonOptionalWithDefault = stringOptionalToString( source.publicOptionalToNonOptionalWithDefault ); + } return target; } @@ -189,6 +198,18 @@ public Source fromTarget(Target target) { else { source.setMonitoredOptionalSubTypeToSubType( Optional.empty() ); } + if ( target.publicOptionalSubTypeToOptional != null && target.publicOptionalSubTypeToOptional.isPresent() ) { + source.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.publicOptionalSubTypeToOptional ); + } + else { + source.publicOptionalSubTypeToOptional = Optional.empty(); + } + if ( target.publicOptionalToNonOptionalWithDefault != null ) { + source.publicOptionalToNonOptionalWithDefault = stringToStringOptional( target.publicOptionalToNonOptionalWithDefault ); + } + else { + source.publicOptionalToNonOptionalWithDefault = Optional.empty(); + } return source; } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java index 919cb196ba..54997f08e2 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java @@ -10,7 +10,7 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-03-02T23:19:18-0500", + date = "2023-03-03T00:01:21-0500", comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" ) public class SimpleOptionalTestMapperImpl implements SimpleOptionalTestMapper { @@ -45,6 +45,8 @@ public Target toTarget(Source source) { target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); target.setMonitoredOptionalToString( stringOptionalToString( source.getMonitoredOptionalToString() ) ); target.setMonitoredOptionalSubTypeToSubType( subTypeOptionalToSubType( source.getMonitoredOptionalSubTypeToSubType() ) ); + target.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.publicOptionalSubTypeToOptional ); + target.publicOptionalToNonOptionalWithDefault = stringOptionalToString( source.publicOptionalToNonOptionalWithDefault ); return target; } @@ -79,6 +81,8 @@ public Source fromTarget(Target target) { source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); source.setMonitoredOptionalToString( stringToStringOptional( target.getMonitoredOptionalToString() ) ); source.setMonitoredOptionalSubTypeToSubType( subTypeToSubTypeOptional1( target.getMonitoredOptionalSubTypeToSubType() ) ); + source.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.publicOptionalSubTypeToOptional ); + source.publicOptionalToNonOptionalWithDefault = stringToStringOptional( target.publicOptionalToNonOptionalWithDefault ); return source; } From 2f1cb007ad48e91addf4f047b70285b4e8d45f9d Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Fri, 30 Jun 2023 01:20:48 -0400 Subject: [PATCH 07/17] Before/After mapping --- .../internal/model/OptionalMappingMethod.ftl | 19 ++++++- .../BaseOptionalTestMapper.java | 48 ++++++++++++++++ .../ap/test/optionalmapping/Source.java | 4 +- .../ap/test/optionalmapping/Target.java | 4 +- ...alueCheckAlwaysOptionalTestMapperImpl.java | 57 +++++++++++++++---- .../SimpleOptionalTestMapperImpl.java | 57 +++++++++++++++---- 6 files changed, 163 insertions(+), 26 deletions(-) diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl index 8dcdf333ce..8b41592ebb 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl @@ -8,6 +8,12 @@ <#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.OptionalMappingMethod" --> <#if overridden>@Override <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, )<@throws/> { + <#list beforeMappingReferencesWithoutMappingTarget as callback> + <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + <#if !callback_has_next> + + + if ( ${sourceParameter.name} == null ) { <#if resultType.optionalType> <#-- regardless of mapNullToDefault value, never return null for Optional resultType --> @@ -23,11 +29,20 @@ } <#if sourceParameter.type.optionalType> - return ${sourceParameter.name}.map( ${loopVariableName} -> <@includeModel object=elementAssignment/> )<#if !returnType.optionalType>.orElse( null ); + <@includeModel object=returnType/> ${resultName} = ${sourceParameter.name}.map( ${loopVariableName} -> <@includeModel object=elementAssignment/> )<#if !returnType.optionalType>.orElse( null ); <#else> <@includeModel object=sourceElementType/> ${loopVariableName} = ${sourceParameter.name}; - return Optional.ofNullable( <@includeModel object=elementAssignment/> ); + <@includeModel object=returnType/> ${resultName} = Optional.ofNullable( <@includeModel object=elementAssignment/> ); + + <#list afterMappingReferences as callback> + <#if callback_index = 0> + + + <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + + + return ${resultName}; } <#macro throws> <#if (thrownTypes?size > 0)><#lt> throws <@compress single_line=true> diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java index 2cd4d943d7..4fa4c26838 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java @@ -5,10 +5,58 @@ */ package org.mapstruct.ap.test.optionalmapping; +import java.util.Optional; + +import org.mapstruct.AfterMapping; +import org.mapstruct.BeforeMapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.TargetType; + public interface BaseOptionalTestMapper { Target toTarget(Source source); Source fromTarget(Target target); + @BeforeMapping + default void beforeOptionalSourceWithNoTargetType(Optional source) { + } + + @BeforeMapping + default void beforeOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, + Optional source) { + } + + @BeforeMapping + default void beforeNonOptionalSourceWithNoTargetType(Source.SubType source) { + } + + @BeforeMapping + default void beforeNonOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, + Source.SubType source) { + } + + @AfterMapping + default void afterOptionalSource(Optional source) { + } + + @AfterMapping + default void afterNonOptionalSource(Source.SubType source) { + } + + @AfterMapping + default void afterOptionalSourceWithNonOptionalTarget(@MappingTarget Target.SubType target, + Optional source) { + } + + @AfterMapping + default void afterOptionalSourceWithOptionalTarget(@MappingTarget Optional target, + Optional source) { + } + + @AfterMapping + default void afterNonOptionalSourceOptionalTarget(@MappingTarget Optional target, + Source.SubType source) { + } + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java index 6495b03ed6..3ec878f0ea 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java @@ -29,8 +29,8 @@ public class Source { private Optional monitoredOptionalToString; private Optional monitoredOptionalSubTypeToSubType; - public Optional publicOptionalSubTypeToOptional; - public Optional publicOptionalToNonOptionalWithDefault; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalSubTypeToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToNonOptionalWithDefault; public Source(Optional constructorOptionalToNonOptional, String constructorNonOptionalToOptional, diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java index 14a6262283..e24160f2d5 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java @@ -31,8 +31,8 @@ public class Target { private SubType monitoredOptionalSubTypeToSubType; private boolean monitoredOptionalSubTypeToSubTypeWasCalled; - public Optional publicOptionalSubTypeToOptional; - public String publicOptionalToNonOptionalWithDefault = "DEFAULT"; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalSubTypeToOptional; + @SuppressWarnings( "VisibilityModifier" ) public String publicOptionalToNonOptionalWithDefault = "DEFAULT"; public Target(String constructorOptionalToNonOptional, Optional constructorNonOptionalToOptional, diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java index 6561d6d8f4..a5b9635c8d 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java @@ -10,8 +10,8 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-03-03T00:01:17-0500", - comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" + date = "2023-06-30T00:29:43-0400", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" ) public class NullValueCheckAlwaysOptionalTestMapperImpl implements NullValueCheckAlwaysOptionalTestMapper { @@ -219,7 +219,9 @@ protected String stringOptionalToString(Optional optional) { return null; } - return optional.map( string -> string ).orElse( null ); + String string1 = optional.map( string -> string ).orElse( null ); + + return string1; } protected Optional stringToStringOptional(String string) { @@ -228,10 +230,15 @@ protected Optional stringToStringOptional(String string) { } String string1 = string; - return Optional.ofNullable( string1 ); + Optional optional = Optional.ofNullable( string1 ); + + return optional; } protected Target.SubType subTypeToSubType(Source.SubType subType) { + beforeNonOptionalSourceWithNoTargetType( subType ); + beforeNonOptionalSourceWithNonOptionalTargetType( Target.SubType.class, subType ); + if ( subType == null ) { return null; } @@ -242,32 +249,56 @@ protected Target.SubType subTypeToSubType(Source.SubType subType) { Target.SubType subType1 = new Target.SubType( value ); + afterNonOptionalSource( subType ); + return subType1; } protected Target.SubType subTypeOptionalToSubType(Optional optional) { + beforeOptionalSourceWithNoTargetType( optional ); + beforeOptionalSourceWithNonOptionalTargetType( Target.SubType.class, optional ); + if ( optional == null ) { return null; } - return optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + + afterOptionalSource( optional ); + afterOptionalSourceWithNonOptionalTarget( subType1, optional ); + + return subType1; } protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + beforeNonOptionalSourceWithNoTargetType( subType ); + if ( subType == null ) { return Optional.empty(); } Source.SubType subType1 = subType; - return Optional.ofNullable( subTypeToSubType( subType1 ) ); + Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); + + afterNonOptionalSource( subType ); + afterNonOptionalSourceOptionalTarget( optional, subType ); + + return optional; } protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + beforeOptionalSourceWithNoTargetType( optional ); + if ( optional == null ) { return Optional.empty(); } - return optional.map( subType -> subTypeToSubType( subType ) ); + Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); + + afterOptionalSource( optional ); + afterOptionalSourceWithOptionalTarget( optional1, optional ); + + return optional1; } protected Source.SubType subTypeToSubType1(Target.SubType subType) { @@ -290,7 +321,9 @@ protected Optional subTypeToSubTypeOptional1(Target.SubType subT } Target.SubType subType1 = subType; - return Optional.ofNullable( subTypeToSubType1( subType1 ) ); + Optional optional = Optional.ofNullable( subTypeToSubType1( subType1 ) ); + + return optional; } protected Source.SubType subTypeOptionalToSubType1(Optional optional) { @@ -298,7 +331,9 @@ protected Source.SubType subTypeOptionalToSubType1(Optional opti return null; } - return optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); + Source.SubType subType1 = optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); + + return subType1; } protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { @@ -306,6 +341,8 @@ protected Optional subTypeOptionalToSubTypeOptional1(Optional subTypeToSubType1( subType ) ); + Optional optional1 = optional.map( subType -> subTypeToSubType1( subType ) ); + + return optional1; } } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java index 54997f08e2..915cd5e474 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java @@ -10,8 +10,8 @@ @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-03-03T00:01:21-0500", - comments = "version: , compiler: javac, environment: Java 11.0.18 (Homebrew)" + date = "2023-06-30T00:32:23-0400", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" ) public class SimpleOptionalTestMapperImpl implements SimpleOptionalTestMapper { @@ -92,7 +92,9 @@ protected String stringOptionalToString(Optional optional) { return null; } - return optional.map( string -> string ).orElse( null ); + String string1 = optional.map( string -> string ).orElse( null ); + + return string1; } protected Optional stringToStringOptional(String string) { @@ -101,10 +103,15 @@ protected Optional stringToStringOptional(String string) { } String string1 = string; - return Optional.ofNullable( string1 ); + Optional optional = Optional.ofNullable( string1 ); + + return optional; } protected Target.SubType subTypeToSubType(Source.SubType subType) { + beforeNonOptionalSourceWithNoTargetType( subType ); + beforeNonOptionalSourceWithNonOptionalTargetType( Target.SubType.class, subType ); + if ( subType == null ) { return null; } @@ -115,32 +122,56 @@ protected Target.SubType subTypeToSubType(Source.SubType subType) { Target.SubType subType1 = new Target.SubType( value ); + afterNonOptionalSource( subType ); + return subType1; } protected Target.SubType subTypeOptionalToSubType(Optional optional) { + beforeOptionalSourceWithNoTargetType( optional ); + beforeOptionalSourceWithNonOptionalTargetType( Target.SubType.class, optional ); + if ( optional == null ) { return null; } - return optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + + afterOptionalSource( optional ); + afterOptionalSourceWithNonOptionalTarget( subType1, optional ); + + return subType1; } protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + beforeNonOptionalSourceWithNoTargetType( subType ); + if ( subType == null ) { return Optional.empty(); } Source.SubType subType1 = subType; - return Optional.ofNullable( subTypeToSubType( subType1 ) ); + Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); + + afterNonOptionalSource( subType ); + afterNonOptionalSourceOptionalTarget( optional, subType ); + + return optional; } protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + beforeOptionalSourceWithNoTargetType( optional ); + if ( optional == null ) { return Optional.empty(); } - return optional.map( subType -> subTypeToSubType( subType ) ); + Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); + + afterOptionalSource( optional ); + afterOptionalSourceWithOptionalTarget( optional1, optional ); + + return optional1; } protected Source.SubType subTypeToSubType1(Target.SubType subType) { @@ -163,7 +194,9 @@ protected Optional subTypeToSubTypeOptional1(Target.SubType subT } Target.SubType subType1 = subType; - return Optional.ofNullable( subTypeToSubType1( subType1 ) ); + Optional optional = Optional.ofNullable( subTypeToSubType1( subType1 ) ); + + return optional; } protected Source.SubType subTypeOptionalToSubType1(Optional optional) { @@ -171,7 +204,9 @@ protected Source.SubType subTypeOptionalToSubType1(Optional opti return null; } - return optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); + Source.SubType subType1 = optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); + + return subType1; } protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { @@ -179,6 +214,8 @@ protected Optional subTypeOptionalToSubTypeOptional1(Optional subTypeToSubType1( subType ) ); + Optional optional1 = optional.map( subType -> subTypeToSubType1( subType ) ); + + return optional1; } } From 49cd50c9754b53d1bf64b15198b60d7a8fe82a63 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 17 Oct 2023 22:37:35 -0400 Subject: [PATCH 08/17] Tests to clarify behaviour --- .../model/presence/OptionalPresenceCheck.java | 55 +++ .../model/presence/OptionalPresenceCheck.ftl | 9 + .../BaseOptionalMappingTest.java | 466 ------------------ .../BaseOptionalTestMapper.java | 62 --- ...ullValueCheckAlwaysOptionalTestMapper.java | 14 - .../optionalmapping/OptionalMappingTest.java | 118 ----- .../SimpleOptionalTestMapper.java | 13 - .../ap/test/optionalmapping/Source.java | 169 ------- .../ap/test/optionalmapping/Target.java | 181 ------- .../OptionalBeforeAfterMapper.java | 73 +++ .../beforeafter/OptionalBeforeAfterTest.java | 16 + .../optionalmapping/beforeafter/Source.java | 87 ++++ .../optionalmapping/beforeafter/Target.java | 86 ++++ .../OptionalDifferentTypesMapper.java | 20 + .../OptionalDifferentTypesTest.java | 235 +++++++++ .../differenttypes/Source.java | 99 ++++ .../differenttypes/Target.java | 98 ++++ .../nested/OptionalNestedMapper.java | 18 + .../nested/OptionalNestedTest.java | 178 +++++++ .../test/optionalmapping/nested/Source.java | 80 +++ .../test/optionalmapping/nested/Target.java | 48 ++ .../OptionalNullCheckAlwaysMapper.java | 14 + .../OptionalNullCheckAlwaysTest.java | 64 +++ .../nullcheckalways/Source.java | 40 ++ .../nullcheckalways/Target.java | 40 ++ .../sametype/OptionalSameTypeMapper.java | 20 + .../sametype/OptionalSameTypeTest.java | 247 ++++++++++ .../test/optionalmapping/sametype/Source.java | 67 +++ .../test/optionalmapping/sametype/Target.java | 67 +++ ...alueCheckAlwaysOptionalTestMapperImpl.java | 8 +- .../SimpleOptionalTestMapperImpl.java | 8 +- 31 files changed, 1669 insertions(+), 1031 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.java create mode 100644 processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Target.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Target.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Target.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.java b/processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.java new file mode 100644 index 0000000000..63f15e8557 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.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.internal.model.presence; + +import java.util.Collections; +import java.util.Objects; +import java.util.Set; + +import org.mapstruct.ap.internal.model.common.ModelElement; +import org.mapstruct.ap.internal.model.common.PresenceCheck; +import org.mapstruct.ap.internal.model.common.Type; + +/** + * Presence checker for {@link java.util.Optional} types. + * + * @author Ken Wang + */ +public class OptionalPresenceCheck extends ModelElement implements PresenceCheck { + + private final String sourceReference; + + public OptionalPresenceCheck(String sourceReference) { + this.sourceReference = sourceReference; + } + + public String getSourceReference() { + return sourceReference; + } + + @Override + public Set getImportTypes() { + return Collections.emptySet(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + OptionalPresenceCheck that = (OptionalPresenceCheck) o; + return Objects.equals( sourceReference, that.sourceReference ); + } + + @Override + public int hashCode() { + return Objects.hash( sourceReference ); + } + +} diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl new file mode 100644 index 0000000000..775f5a8448 --- /dev/null +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl @@ -0,0 +1,9 @@ +<#-- + + Copyright MapStruct Authors. + + Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + +--> +<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.presence.OptionalPresenceCheck" --> +${sourceReference}.isPresent() \ No newline at end of file diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java deleted file mode 100644 index 8c14498366..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalMappingTest.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Optional; - -import org.mapstruct.ap.testutil.ProcessorTest; -import org.mapstruct.factory.Mappers; - -import static org.assertj.core.api.Assertions.assertThat; - -public abstract class BaseOptionalMappingTest { - - private final Class mapperClass; - private BaseOptionalTestMapper mapper; - - protected BaseOptionalMappingTest(Class mapperClass) { - this.mapperClass = mapperClass; - } - - protected BaseOptionalTestMapper getMapper() { - if (this.mapper == null) { - this.mapper = Mappers.getMapper( mapperClass ); - } - return this.mapper; - } - - @ProcessorTest - public void testMappingSimpleOptionalToNonOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalToNonOptional( Optional.of( "some value" ) ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalToNonOptional() ).isEqualTo( "some value" ); - } - - @ProcessorTest - public void testMappingEmptySimpleOptionalToNonOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalToNonOptional( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalToNonOptional() ).isNull(); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromNonOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalToNonOptional( "some value" ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalToNonOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromNullNonOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalToNonOptional( null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalToNonOptional() ).isEmpty(); - } - - @ProcessorTest - public void testMappingNonOptionalToSimpleOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setNonOptionalToOptional( "some value" ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getNonOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testMappingNullNonOptionalToSimpleOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setNonOptionalToOptional( null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getNonOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromSimpleOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setNonOptionalToOptional( Optional.of( "some value" ) ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getNonOptionalToOptional() ).isEqualTo( "some value" ); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromEmptySimpleOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setNonOptionalToOptional( Optional.empty() ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getNonOptionalToOptional() ).isNull(); - } - - @ProcessorTest - public void testMappingSimpleOptionalToOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalToOptional( Optional.of( "some value" ) ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testMappingEmptySimpleOptionalToOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalToOptional( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalToOptional( Optional.of( "some value" ) ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testReverseMappingSimpleOptionalFromEmptyOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalToOptional( Optional.empty() ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testMappingSubTypeOptionalToNonOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalSubTypeToNonOptional( Optional.of( new Source.SubType( 94 ) ) ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalSubTypeToNonOptional() ).isEqualTo( new Target.SubType( 94 ) ); - } - - @ProcessorTest - public void testMappingEmptySubTypeOptionalToNonOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalSubTypeToNonOptional( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalSubTypeToNonOptional() ).isNull(); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromNonOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalSubTypeToNonOptional( new Target.SubType( 94 ) ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalSubTypeToNonOptional() ).contains( new Source.SubType( 94 ) ); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromNullNonOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalSubTypeToNonOptional( null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalSubTypeToNonOptional() ).isEmpty(); - } - - @ProcessorTest - public void testMappingNonOptionalToSubTypeOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setNonOptionalSubTypeToOptional( new Source.SubType( 94 ) ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getNonOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); - } - - @ProcessorTest - public void testMappingNullNonOptionalToSubTypeOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setNonOptionalSubTypeToOptional( null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getNonOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromSubTypeOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setNonOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94 ) ) ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getNonOptionalSubTypeToOptional() ).isEqualTo( new Source.SubType( 94 ) ); - } - - @ProcessorTest - public void testReverseMappingNonOptionalFromEmptySubTypeOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setNonOptionalSubTypeToOptional( Optional.empty() ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getNonOptionalSubTypeToOptional() ).isNull(); - } - - @ProcessorTest - public void testMappingSubTypeOptionalToOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalSubTypeToOptional( Optional.of( new Source.SubType( 94 ) ) ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); - } - - @ProcessorTest - public void testMappingEmptySubTypeOptionalToOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.setOptionalSubTypeToOptional( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalSubTypeToOptional( Optional.of( new Target.SubType( 94 ) ) ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalSubTypeToOptional() ).contains( new Source.SubType( 94 ) ); - } - - @ProcessorTest - public void testReverseMappingSubTypeOptionalFromEmptyOptional() { - Target target = new Target( null, null, null, null, null, null ); - target.setOptionalSubTypeToOptional( Optional.empty() ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testConstructorMappingSimpleOptionalToNonOptional() { - Source source = new Source( Optional.of( "some value" ), null, null, null, null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalToNonOptional() ).isEqualTo( "some value" ); - } - - @ProcessorTest - public void testConstructorMappingEmptySimpleOptionalToNonOptional() { - Source source = new Source( Optional.empty(), null, null, null, null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); - } - - @ProcessorTest - public void testReverseConstructorMappingSimpleOptionalFromNonOptional() { - Target target = new Target( "some value", null, null, null, null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalToNonOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testReverseConstructorMappingSimpleOptionalFromNullNonOptional() { - Target target = new Target( null, null, null, null, null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalToNonOptional() ).isEmpty(); - } - - @ProcessorTest - public void testConstructorMappingNonOptionalToSimpleOptional() { - Source source = new Source( null, "some value", null, null, null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorNonOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testConstructorMappingNullNonOptionalToSimpleOptional() { - Source source = new Source( null, null, null, null, null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorNonOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseConstructorMappingNonOptionalFromSimpleOptional() { - Target target = new Target( null, Optional.of( "some value" ), null, null, null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorNonOptionalToOptional() ).isEqualTo( "some value" ); - } - - @ProcessorTest - public void testReverseConstructorMappingNonOptionalFromEmptySimpleOptional() { - Target target = new Target( null, Optional.empty(), null, null, null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorNonOptionalToOptional() ).isNull(); - } - - @ProcessorTest - public void testConstructorMappingSimpleOptionalToOptional() { - Source source = new Source( null, null, Optional.of( "some value" ), null, null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testConstructorMappingEmptySimpleOptionalToOptional() { - Source source = new Source( null, null, Optional.empty(), null, null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseConstructorMappingSimpleOptionalFromOptional() { - Target target = new Target( null, null, Optional.of( "some value" ), null, null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalToOptional() ).contains( "some value" ); - } - - @ProcessorTest - public void testReverseConstructorMappingSimpleOptionalFromEmptyOptional() { - Target target = new Target( null, null, Optional.empty(), null, null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testConstructorMappingSubTypeOptionalToNonOptional() { - Source source = new Source( null, null, null, Optional.of( new Source.SubType( 94 ) ), null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalSubTypeToNonOptional() ).isEqualTo( new Target.SubType( 94 ) ); - } - - @ProcessorTest - public void testConstructorMappingEmptySubTypeOptionalToNonOptional() { - Source source = new Source( null, null, null, Optional.empty(), null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalSubTypeToNonOptional() ).isNull(); - } - - @ProcessorTest - public void testReverseConstructorMappingSubTypeOptionalFromNonOptional() { - Target target = new Target( null, null, null, new Target.SubType( 94 ), null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalSubTypeToNonOptional() ).contains( new Source.SubType( 94 ) ); - } - - @ProcessorTest - public void testReverseConstructorMappingSubTypeOptionalFromNullNonOptional() { - Target target = new Target( null, null, null, null, null, null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalSubTypeToNonOptional() ).isEmpty(); - } - - @ProcessorTest - public void testConstructorMappingNonOptionalToSubTypeOptional() { - Source source = new Source( null, null, null, null, new Source.SubType( 94 ), null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorNonOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); - } - - @ProcessorTest - public void testConstructorMappingNullNonOptionalToSubTypeOptional() { - Source source = new Source( null, null, null, null, null, null ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorNonOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseConstructorMappingNonOptionalFromSubTypeOptional() { - Target target = new Target( null, null, null, null, Optional.of( new Target.SubType( 94 ) ), null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorNonOptionalSubTypeToOptional() ).isEqualTo( new Source.SubType( 94 ) ); - } - - @ProcessorTest - public void testReverseConstructorMappingNonOptionalFromEmptySubTypeOptional() { - Target target = new Target( null, null, null, null, Optional.empty(), null ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorNonOptionalSubTypeToOptional() ).isNull(); - } - - @ProcessorTest - public void testConstructorMappingSubTypeOptionalToOptional() { - Source source = new Source( null, null, null, null, null, Optional.of( new Source.SubType( 94 ) ) ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalSubTypeToOptional() ).contains( new Target.SubType( 94 ) ); - } - - @ProcessorTest - public void testConstructorMappingEmptySubTypeOptionalToOptional() { - Source source = new Source( null, null, null, null, null, Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getConstructorOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testReverseConstructorMappingSubTypeOptionalFromOptional() { - Target target = new Target( null, null, null, null, null, Optional.of( new Target.SubType( 94 ) ) ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalSubTypeToOptional() ).contains( new Source.SubType( 94 ) ); - } - - @ProcessorTest - public void testReverseConstructorMappingSubTypeOptionalFromEmptyOptional() { - Target target = new Target( null, null, null, null, null, Optional.empty() ); - - Source source = getMapper().fromTarget( target ); - assertThat( source.getConstructorOptionalSubTypeToOptional() ).isEmpty(); - } - - @ProcessorTest - public void testMappingPublicSubTypeOptionalToOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.publicOptionalSubTypeToOptional = Optional.of( new Source.SubType( 9 ) ); - - Target target = getMapper().toTarget( source ); - assertThat( target.publicOptionalSubTypeToOptional ).contains( new Target.SubType( 9 ) ); - } - - @ProcessorTest - public void testMappingPublicEmptySubTypeOptionalToOptional() { - Source source = new Source( null, null, null, null, null, null ); - source.publicOptionalSubTypeToOptional = Optional.empty(); - - Target target = getMapper().toTarget( source ); - assertThat( target.publicOptionalSubTypeToOptional ).isEmpty(); - } - - @ProcessorTest - public void testMappingPublicOptionalToNonOptionalWithDefaultSetsToNewValue() { - Source source = new Source( null, null, null, null, null, null ); - source.publicOptionalToNonOptionalWithDefault = Optional.of( "new" ); - - Target target = getMapper().toTarget( source ); - assertThat( target.publicOptionalToNonOptionalWithDefault ).isEqualTo( "new" ); - } - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java deleted file mode 100644 index 4fa4c26838..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/BaseOptionalTestMapper.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Optional; - -import org.mapstruct.AfterMapping; -import org.mapstruct.BeforeMapping; -import org.mapstruct.MappingTarget; -import org.mapstruct.TargetType; - -public interface BaseOptionalTestMapper { - - Target toTarget(Source source); - - Source fromTarget(Target target); - - @BeforeMapping - default void beforeOptionalSourceWithNoTargetType(Optional source) { - } - - @BeforeMapping - default void beforeOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, - Optional source) { - } - - @BeforeMapping - default void beforeNonOptionalSourceWithNoTargetType(Source.SubType source) { - } - - @BeforeMapping - default void beforeNonOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, - Source.SubType source) { - } - - @AfterMapping - default void afterOptionalSource(Optional source) { - } - - @AfterMapping - default void afterNonOptionalSource(Source.SubType source) { - } - - @AfterMapping - default void afterOptionalSourceWithNonOptionalTarget(@MappingTarget Target.SubType target, - Optional source) { - } - - @AfterMapping - default void afterOptionalSourceWithOptionalTarget(@MappingTarget Optional target, - Optional source) { - } - - @AfterMapping - default void afterNonOptionalSourceOptionalTarget(@MappingTarget Optional target, - Source.SubType source) { - } - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java deleted file mode 100644 index a2bb736167..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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.optionalmapping; - -import org.mapstruct.Mapper; -import org.mapstruct.NullValueCheckStrategy; - -@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) -public interface NullValueCheckAlwaysOptionalTestMapper extends BaseOptionalTestMapper { - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java deleted file mode 100644 index 1725cd3b68..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/OptionalMappingTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Optional; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.mapstruct.ap.testutil.ProcessorTest; -import org.mapstruct.ap.testutil.WithClasses; -import org.mapstruct.ap.testutil.runner.GeneratedSource; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Test for mapping logic from {@link org.mapstruct.ap.internal.model.OptionalMappingMethod}. - * - * @author Ken Wang - */ -public class OptionalMappingTest { - - @Nested - @WithClasses({ - SimpleOptionalTestMapper.class, - BaseOptionalTestMapper.class, - Source.class, - Target.class }) - class SimpleTests extends BaseOptionalMappingTest { - - @RegisterExtension - final GeneratedSource generatedSource = - new GeneratedSource().addComparisonToFixtureFor( SimpleOptionalTestMapper.class ); - - protected SimpleTests() { - super( SimpleOptionalTestMapper.class ); - } - - @ProcessorTest - public void testEmptyMonitoredOptionalStillCallsSetter() { - Source source = new Source( null, null, null, null, null, null ); - source.setMonitoredOptionalToString( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getMonitoredOptionalToString() ).isNull(); - assertThat( target.isMonitoredOptionalToStringWasCalled() ).isTrue(); - } - - @ProcessorTest - public void testEmptyMonitoredSubTypeOptionalStillCallsSetter() { - Source source = new Source( null, null, null, null, null, null ); - source.setMonitoredOptionalSubTypeToSubType( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getMonitoredOptionalSubTypeToSubType() ).isNull(); - assertThat( target.isMonitoredOptionalSubTypeToSubTypeWasCalled() ).isTrue(); - } - - @ProcessorTest - public void testMappingEmptyPublicOptionalToNonOptionalWithDefaultSetsToNull() { - Source source = new Source( null, null, null, null, null, null ); - source.publicOptionalToNonOptionalWithDefault = Optional.empty(); - - Target target = getMapper().toTarget( source ); - assertThat( target.publicOptionalToNonOptionalWithDefault ).isEqualTo( null ); - } - - } - - @Nested - @WithClasses({ - NullValueCheckAlwaysOptionalTestMapper.class, - BaseOptionalTestMapper.class, - Source.class, - Target.class }) - class NullValueCheckAlwaysTests extends BaseOptionalMappingTest { - - @RegisterExtension - final GeneratedSource generatedSource = - new GeneratedSource().addComparisonToFixtureFor( NullValueCheckAlwaysOptionalTestMapper.class ); - - protected NullValueCheckAlwaysTests() { - super( NullValueCheckAlwaysOptionalTestMapper.class ); - } - - @ProcessorTest - public void testEmptyMonitoredOptionalDoesNotCallSetter() { - Source source = new Source( null, null, null, null, null, null ); - source.setMonitoredOptionalToString( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getMonitoredOptionalToString() ).isNull(); - assertThat( target.isMonitoredOptionalToStringWasCalled() ).isFalse(); - } - - @ProcessorTest - public void testEmptyMonitoredSubTypeOptionalDoesNotCallSetter() { - Source source = new Source( null, null, null, null, null, null ); - source.setMonitoredOptionalSubTypeToSubType( Optional.empty() ); - - Target target = getMapper().toTarget( source ); - assertThat( target.getMonitoredOptionalSubTypeToSubType() ).isNull(); - assertThat( target.isMonitoredOptionalSubTypeToSubTypeWasCalled() ).isFalse(); - } - - @ProcessorTest - public void testMappingEmptyPublicOptionalToNonOptionalWithDefaultDoesNotOverwrite() { - Source source = new Source( null, null, null, null, null, null ); - source.publicOptionalToNonOptionalWithDefault = Optional.empty(); - - Target target = getMapper().toTarget( source ); - assertThat( target.publicOptionalToNonOptionalWithDefault ).isEqualTo( "DEFAULT" ); - } - } - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java deleted file mode 100644 index 1ed77e0f70..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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.optionalmapping; - -import org.mapstruct.Mapper; - -@Mapper -public interface SimpleOptionalTestMapper extends BaseOptionalTestMapper { - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java deleted file mode 100644 index 3ec878f0ea..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Source.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Objects; -import java.util.Optional; - -public class Source { - - private final Optional constructorOptionalToNonOptional; - private final String constructorNonOptionalToOptional; - private final Optional constructorOptionalToOptional; - - private final Optional constructorOptionalSubTypeToNonOptional; - private final SubType constructorNonOptionalSubTypeToOptional; - private final Optional constructorOptionalSubTypeToOptional; - - private Optional optionalToNonOptional; - private String nonOptionalToOptional; - private Optional optionalToOptional; - - private Optional optionalSubTypeToNonOptional; - private SubType nonOptionalSubTypeToOptional; - private Optional optionalSubTypeToOptional; - - private Optional monitoredOptionalToString; - private Optional monitoredOptionalSubTypeToSubType; - - @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalSubTypeToOptional; - @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToNonOptionalWithDefault; - - public Source(Optional constructorOptionalToNonOptional, - String constructorNonOptionalToOptional, - Optional constructorOptionalToOptional, - Optional constructorOptionalSubTypeToNonOptional, - SubType constructorNonOptionalSubTypeToOptional, - Optional constructorOptionalSubTypeToOptional) { - this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; - this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; - this.constructorOptionalToOptional = constructorOptionalToOptional; - this.constructorOptionalSubTypeToNonOptional = constructorOptionalSubTypeToNonOptional; - this.constructorNonOptionalSubTypeToOptional = constructorNonOptionalSubTypeToOptional; - this.constructorOptionalSubTypeToOptional = constructorOptionalSubTypeToOptional; - } - - public Optional getConstructorOptionalToNonOptional() { - return constructorOptionalToNonOptional; - } - - public String getConstructorNonOptionalToOptional() { - return constructorNonOptionalToOptional; - } - - public Optional getConstructorOptionalToOptional() { - return constructorOptionalToOptional; - } - - public Optional getConstructorOptionalSubTypeToNonOptional() { - return constructorOptionalSubTypeToNonOptional; - } - - public SubType getConstructorNonOptionalSubTypeToOptional() { - return constructorNonOptionalSubTypeToOptional; - } - - public Optional getConstructorOptionalSubTypeToOptional() { - return constructorOptionalSubTypeToOptional; - } - - public Optional getOptionalToNonOptional() { - return optionalToNonOptional; - } - - public void setOptionalToNonOptional(Optional optionalToNonOptional) { - this.optionalToNonOptional = optionalToNonOptional; - } - - public String getNonOptionalToOptional() { - return nonOptionalToOptional; - } - - public void setNonOptionalToOptional(String nonOptionalToOptional) { - this.nonOptionalToOptional = nonOptionalToOptional; - } - - public Optional getOptionalToOptional() { - return optionalToOptional; - } - - public void setOptionalToOptional(Optional optionalToOptional) { - this.optionalToOptional = optionalToOptional; - } - - public Optional getOptionalSubTypeToNonOptional() { - return optionalSubTypeToNonOptional; - } - - public void setOptionalSubTypeToNonOptional(Optional optionalSubTypeToNonOptional) { - this.optionalSubTypeToNonOptional = optionalSubTypeToNonOptional; - } - - public SubType getNonOptionalSubTypeToOptional() { - return nonOptionalSubTypeToOptional; - } - - public void setNonOptionalSubTypeToOptional(SubType nonOptionalSubTypeToOptional) { - this.nonOptionalSubTypeToOptional = nonOptionalSubTypeToOptional; - } - - public Optional getOptionalSubTypeToOptional() { - return optionalSubTypeToOptional; - } - - public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOptional) { - this.optionalSubTypeToOptional = optionalSubTypeToOptional; - } - - public Optional getMonitoredOptionalToString() { - return monitoredOptionalToString; - } - - public void setMonitoredOptionalToString(Optional monitoredOptionalToString) { - this.monitoredOptionalToString = monitoredOptionalToString; - } - - public Optional getMonitoredOptionalSubTypeToSubType() { - return monitoredOptionalSubTypeToSubType; - } - - public void setMonitoredOptionalSubTypeToSubType( - Optional monitoredOptionalSubTypeToSubType) { - this.monitoredOptionalSubTypeToSubType = monitoredOptionalSubTypeToSubType; - } - - public static class SubType { - - private final int value; - - public SubType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - SubType subType = (SubType) o; - return value == subType.value; - } - - @Override - public int hashCode() { - return Objects.hash( value ); - } - - } - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java deleted file mode 100644 index e24160f2d5..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/Target.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Objects; -import java.util.Optional; - -public class Target { - - private final String constructorOptionalToNonOptional; - private final Optional constructorNonOptionalToOptional; - private final Optional constructorOptionalToOptional; - - private final SubType constructorOptionalSubTypeToNonOptional; - private final Optional constructorNonOptionalSubTypeToOptional; - private final Optional constructorOptionalSubTypeToOptional; - - private String optionalToNonOptional; - private Optional nonOptionalToOptional; - private Optional optionalToOptional; - - private SubType optionalSubTypeToNonOptional; - private Optional nonOptionalSubTypeToOptional; - private Optional optionalSubTypeToOptional; - - private String monitoredOptionalToString; - private boolean monitoredOptionalToStringWasCalled; - private SubType monitoredOptionalSubTypeToSubType; - private boolean monitoredOptionalSubTypeToSubTypeWasCalled; - - @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalSubTypeToOptional; - @SuppressWarnings( "VisibilityModifier" ) public String publicOptionalToNonOptionalWithDefault = "DEFAULT"; - - public Target(String constructorOptionalToNonOptional, - Optional constructorNonOptionalToOptional, - Optional constructorOptionalToOptional, - SubType constructorOptionalSubTypeToNonOptional, - Optional constructorNonOptionalSubTypeToOptional, - Optional constructorOptionalSubTypeToOptional) { - this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; - this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; - this.constructorOptionalToOptional = constructorOptionalToOptional; - this.constructorOptionalSubTypeToNonOptional = constructorOptionalSubTypeToNonOptional; - this.constructorNonOptionalSubTypeToOptional = constructorNonOptionalSubTypeToOptional; - this.constructorOptionalSubTypeToOptional = constructorOptionalSubTypeToOptional; - } - - public String getConstructorOptionalToNonOptional() { - return constructorOptionalToNonOptional; - } - - public Optional getConstructorNonOptionalToOptional() { - return constructorNonOptionalToOptional; - } - - public Optional getConstructorOptionalToOptional() { - return constructorOptionalToOptional; - } - - public SubType getConstructorOptionalSubTypeToNonOptional() { - return constructorOptionalSubTypeToNonOptional; - } - - public Optional getConstructorNonOptionalSubTypeToOptional() { - return constructorNonOptionalSubTypeToOptional; - } - - public Optional getConstructorOptionalSubTypeToOptional() { - return constructorOptionalSubTypeToOptional; - } - - public String getOptionalToNonOptional() { - return optionalToNonOptional; - } - - public void setOptionalToNonOptional(String optionalToNonOptional) { - this.optionalToNonOptional = optionalToNonOptional; - } - - public Optional getNonOptionalToOptional() { - return nonOptionalToOptional; - } - - public void setNonOptionalToOptional(Optional nonOptionalToOptional) { - this.nonOptionalToOptional = nonOptionalToOptional; - } - - public Optional getOptionalToOptional() { - return optionalToOptional; - } - - public void setOptionalToOptional(Optional optionalToOptional) { - this.optionalToOptional = optionalToOptional; - } - - public SubType getOptionalSubTypeToNonOptional() { - return optionalSubTypeToNonOptional; - } - - public void setOptionalSubTypeToNonOptional(SubType optionalSubTypeToNonOptional) { - this.optionalSubTypeToNonOptional = optionalSubTypeToNonOptional; - } - - public Optional getNonOptionalSubTypeToOptional() { - return nonOptionalSubTypeToOptional; - } - - public void setNonOptionalSubTypeToOptional(Optional nonOptionalSubTypeToOptional) { - this.nonOptionalSubTypeToOptional = nonOptionalSubTypeToOptional; - } - - public Optional getOptionalSubTypeToOptional() { - return optionalSubTypeToOptional; - } - - public void setOptionalSubTypeToOptional(Optional optionalSubTypeToOptional) { - this.optionalSubTypeToOptional = optionalSubTypeToOptional; - } - - public String getMonitoredOptionalToString() { - return monitoredOptionalToString; - } - - public void setMonitoredOptionalToString(String monitoredOptionalToString) { - this.monitoredOptionalToStringWasCalled = true; - this.monitoredOptionalToString = monitoredOptionalToString; - } - - public SubType getMonitoredOptionalSubTypeToSubType() { - return monitoredOptionalSubTypeToSubType; - } - - public void setMonitoredOptionalSubTypeToSubType( - SubType monitoredOptionalSubTypeToSubType) { - this.monitoredOptionalSubTypeToSubTypeWasCalled = true; - this.monitoredOptionalSubTypeToSubType = monitoredOptionalSubTypeToSubType; - } - - public boolean isMonitoredOptionalToStringWasCalled() { - return monitoredOptionalToStringWasCalled; - } - - public boolean isMonitoredOptionalSubTypeToSubTypeWasCalled() { - return monitoredOptionalSubTypeToSubTypeWasCalled; - } - - public static class SubType { - - private final int value; - - public SubType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - SubType subType = (SubType) o; - return value == subType.value; - } - - @Override - public int hashCode() { - return Objects.hash( value ); - } - - } - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java new file mode 100644 index 0000000000..e993637b9a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java @@ -0,0 +1,73 @@ +package org.mapstruct.ap.test.optionalmapping.beforeafter; + +import java.util.Optional; + +import org.mapstruct.AfterMapping; +import org.mapstruct.BeforeMapping; +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.TargetType; +import org.mapstruct.factory.Mappers; + +@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +public interface OptionalBeforeAfterMapper { + + OptionalBeforeAfterMapper INSTANCE = Mappers.getMapper( OptionalBeforeAfterMapper.class); + + Target toTarget(Source source); + + @BeforeMapping + default void beforeDeepOptionalSourceWithNoTargetType(Optional source) { + } + + @BeforeMapping + default void beforeDeepOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, + Optional source) { + } + + @AfterMapping + default void afterDeepOptionalSourceWithNoTarget(Optional source) { + + } + + @AfterMapping + default void afterDeepOptionalSourceWithNonOptionalTarget(@MappingTarget Target.SubType target, + Optional source) { + } + + @AfterMapping + default void afterDeepOptionalSourceWithOptionalTarget(@MappingTarget Optional target, + Optional source) { + } + + @AfterMapping + default void afterDeepNonOptionalSourceOptionalTarget(@MappingTarget Optional target, + Source.SubType source) { + } + + @BeforeMapping + default void beforeShallowOptionalSourceWithNoTargetType(Optional source) { + } + + @BeforeMapping + default void beforeShallowOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, + Optional source) { + } + + @AfterMapping + default void afterShallowOptionalSourceWithNoTarget(Optional source) { + + } + + @AfterMapping + default void afterShallowOptionalSourceWithNonOptionalTarget(@MappingTarget String target, + Optional source) { + } + + @AfterMapping + default void afterShallowNonOptionalSourceOptionalTarget(@MappingTarget Optional target, + String source) { + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java new file mode 100644 index 0000000000..d263e4fef9 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java @@ -0,0 +1,16 @@ +package org.mapstruct.ap.test.optionalmapping.beforeafter; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +@WithClasses({ + OptionalBeforeAfterMapper.class, + Source.class, + Target.class }) +public class OptionalBeforeAfterTest { + + @ProcessorTest + public void dummyTest() { + + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java new file mode 100644 index 0000000000..5b32f6fda3 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java @@ -0,0 +1,87 @@ +/* + * 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.optionalmapping.beforeafter; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Source { + + private final Optional deepOptionalToOptional; + private final Optional deepOptionalToNonOptional; + private final SubType deepNonOptionalToOptional; + + private final Optional shallowOptionalToOptional; + private final Optional shallowOptionalToNonOptional; + private final String shallowNonOptionalToOptional; + + public Source(Optional deepOptionalToOptional, Optional deepOptionalToNonOptional, + SubType deepNonOptionalToOptional, Optional shallowOptionalToOptional, + Optional shallowOptionalToNonOptional, String shallowNonOptionalToOptional) { + this.deepOptionalToOptional = deepOptionalToOptional; + this.deepOptionalToNonOptional = deepOptionalToNonOptional; + this.deepNonOptionalToOptional = deepNonOptionalToOptional; + this.shallowOptionalToOptional = shallowOptionalToOptional; + this.shallowOptionalToNonOptional = shallowOptionalToNonOptional; + this.shallowNonOptionalToOptional = shallowNonOptionalToOptional; + } + + public Optional getDeepOptionalToOptional() { + return deepOptionalToOptional; + } + + public Optional getDeepOptionalToNonOptional() { + return deepOptionalToNonOptional; + } + + public SubType getDeepNonOptionalToOptional() { + return deepNonOptionalToOptional; + } + + public Optional getShallowOptionalToOptional() { + return shallowOptionalToOptional; + } + + public Optional getShallowOptionalToNonOptional() { + return shallowOptionalToNonOptional; + } + + public String getShallowNonOptionalToOptional() { + return shallowNonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Target.java new file mode 100644 index 0000000000..a93b4b31e7 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Target.java @@ -0,0 +1,86 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.beforeafter; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Target { + + private final Optional deepOptionalToOptional; + private final SubType deepOptionalToNonOptional; + private final Optional deepNonOptionalToOptional; + + private final Optional shallowOptionalToOptional; + private final String shallowOptionalToNonOptional; + private final Optional shallowNonOptionalToOptional; + + public Target(Optional deepOptionalToOptional, SubType deepOptionalToNonOptional, + Optional deepNonOptionalToOptional, Optional shallowOptionalToOptional, + String shallowOptionalToNonOptional, Optional shallowNonOptionalToOptional) { + this.deepOptionalToOptional = deepOptionalToOptional; + this.deepOptionalToNonOptional = deepOptionalToNonOptional; + this.deepNonOptionalToOptional = deepNonOptionalToOptional; + this.shallowOptionalToOptional = shallowOptionalToOptional; + this.shallowOptionalToNonOptional = shallowOptionalToNonOptional; + this.shallowNonOptionalToOptional = shallowNonOptionalToOptional; + } + + public Optional getDeepOptionalToOptional() { + return deepOptionalToOptional; + } + + public SubType getDeepOptionalToNonOptional() { + return deepOptionalToNonOptional; + } + + public Optional getDeepNonOptionalToOptional() { + return deepNonOptionalToOptional; + } + + public Optional getShallowOptionalToOptional() { + return shallowOptionalToOptional; + } + + public String getShallowOptionalToNonOptional() { + return shallowOptionalToNonOptional; + } + + public Optional getShallowNonOptionalToOptional() { + return shallowNonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java new file mode 100644 index 0000000000..04775bce2d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java @@ -0,0 +1,20 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.differenttypes; + +import org.mapstruct.Mapper; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.factory.Mappers; + +@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION) +public interface OptionalDifferentTypesMapper { + + OptionalDifferentTypesMapper INSTANCE = Mappers.getMapper( + OptionalDifferentTypesMapper.class); + + Target toTarget(Source source); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java new file mode 100644 index 0000000000..1398c61746 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java @@ -0,0 +1,235 @@ +/* + * 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.optionalmapping.differenttypes; + +import java.util.Optional; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +@WithClasses({ + OptionalDifferentTypesMapper.class, + Source.class, + Target.class }) +public class OptionalDifferentTypesTest { + + @ProcessorTest + public void constructorOptionalToOptional_present() { + Source source = new Source( Optional.of( new Source.SubType( "some value" ) ), null, null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).contains( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void constructorOptionalToOptional_empty() { + Source source = new Source( Optional.empty(), null, null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + } + + // TODO Contentious + // Should null Optional map to null Optional, or explicitly to empty? + @ProcessorTest + public void constructorOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_present() { + Source source = new Source( null, Optional.of( new Source.SubType( "some value" ) ), null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isEqualTo( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_empty() { + Source source = new Source( null, Optional.empty(), null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void constructorNonOptionalToOptional_nonNull() { + Source source = new Source( null, null, new Source.SubType( "some value" ) ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).contains( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void constructorNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToOptional_present() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( Optional.of( new Source.SubType( "some value" ) ) ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).contains( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void optionalToOptional_empty() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( Optional.empty() ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + // TODO Contentious + // Should null Optional map to null Optional, or explicitly to empty? + @ProcessorTest + public void optionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToNonOptional_present() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( Optional.of( new Source.SubType( "some value" ) ) ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isEqualTo( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void optionalToNonOptional_empty() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( Optional.empty() ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void optionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nonOptionalToOptional_nonNull() { + Source source = new Source( null, null, null ); + source.setNonOptionalToOptional( new Source.SubType( "some value" ) ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).contains( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void nonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setNonOptionalToOptional( null ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToOptional_present() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = Optional.of( new Source.SubType( "some value" ) ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).contains( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void publicOptionalToOptional_empty() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = Optional.empty(); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).isEmpty(); + } + + // TODO Contentious + // Should null Optional map to null Optional, or explicitly to empty? + @ProcessorTest + public void publicOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = null; + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToNonOptional_present() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = Optional.of( new Source.SubType( "some value" ) ); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isEqualTo( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void publicOptionalToNonOptional_empty() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = Optional.empty(); + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isNull(); + } + + @ProcessorTest + public void publicOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = null; + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isNull(); + } + + @ProcessorTest + public void publicNonOptionalToOptional_nonNull() { + Source source = new Source( null, null, null ); + source.publicNonOptionalToOptional = new Source.SubType( "some value" ) ; + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicNonOptionalToOptional ).contains( new Target.SubType( "some value" ) ); + } + + @ProcessorTest + public void publicNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicNonOptionalToOptional = null ; + + Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); + assertThat( target.publicNonOptionalToOptional ).isEmpty(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java new file mode 100644 index 0000000000..ba765e0a26 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java @@ -0,0 +1,99 @@ +/* + * 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.optionalmapping.differenttypes; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Source { + + private final Optional constructorOptionalToOptional; + private final Optional constructorOptionalToNonOptional; + private final SubType constructorNonOptionalToOptional; + + private Optional optionalToOptional; + private Optional optionalToNonOptional; + private SubType nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public Optional publicOptionalToNonOptional; + public SubType publicNonOptionalToOptional; + + public Source(Optional constructorOptionalToOptional, Optional constructorOptionalToNonOptional, + SubType constructorNonOptionalToOptional) { + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public Optional getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public SubType getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public Optional getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(Optional optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public SubType getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(SubType nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java new file mode 100644 index 0000000000..9f06a6d289 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java @@ -0,0 +1,98 @@ +/* + * 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.optionalmapping.differenttypes; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Target { + + private final Optional constructorOptionalToOptional; + private final SubType constructorOptionalToNonOptional; + private final Optional constructorNonOptionalToOptional; + + private Optional optionalToOptional; + private SubType optionalToNonOptional; + private Optional nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public SubType publicOptionalToNonOptional; + public Optional publicNonOptionalToOptional; + + public Target(Optional constructorOptionalToOptional, SubType constructorOptionalToNonOptional, + Optional constructorNonOptionalToOptional) { + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public SubType getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public Optional getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public SubType getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(SubType optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public Optional getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + Target.SubType subType = (Target.SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java new file mode 100644 index 0000000000..dd6f34028d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java @@ -0,0 +1,18 @@ +package org.mapstruct.ap.test.optionalmapping.nested; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface OptionalNestedMapper { + + OptionalNestedMapper INSTANCE = Mappers.getMapper(OptionalNestedMapper.class); + + @Mapping( source = "optionalToNonOptional.value", target = "optionalToNonOptional") + @Mapping( source = "optionalToOptional.value", target = "optionalToOptional") + @Mapping( source = "nonOptionalToNonOptional.value", target = "nonOptionalToNonOptional") + @Mapping( source = "nonOptionalToOptional.value", target = "nonOptionalToOptional") + Target toTarget(Source source); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java new file mode 100644 index 0000000000..a64888efdb --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java @@ -0,0 +1,178 @@ +package org.mapstruct.ap.test.optionalmapping.nested; + +import java.util.Optional; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +@WithClasses({ + OptionalNestedMapper.class, + Source.class, + Target.class }) +public class OptionalNestedTest { + + @ProcessorTest + public void optionalToNonOptional_empty() { + Source source = new Source(); + source.setOptionalToNonOptional( Optional.empty() ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void optionalToNonOptional_null() { + Source source = new Source(); + source.setOptionalToNonOptional( null ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nestedOptionalToNonOptional_empty() { + Source source = new Source(); + source.setOptionalToNonOptional( Optional.of( new Source.NestedOptional( Optional.empty() ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nestedOptionalToNonOptional_null() { + Source source = new Source(); + source.setOptionalToNonOptional( Optional.of( new Source.NestedOptional( null ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nestedOptionalToNonOptional_nonNull() { + Source source = new Source(); + source.setOptionalToNonOptional( Optional.of( new Source.NestedOptional( Optional.of( "some value" ) ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isEqualTo("some value"); + } + + @ProcessorTest + public void optionalToOptional_empty() { + Source source = new Source(); + source.setOptionalToOptional( Optional.empty() ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToOptional_null() { + Source source = new Source(); + source.setOptionalToOptional( null ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void nestedOptionalToOptional_empty() { + Source source = new Source(); + source.setOptionalToOptional( Optional.of( new Source.NestedOptional( Optional.empty() ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void nestedOptionalToOptional_null() { + Source source = new Source(); + source.setOptionalToOptional( Optional.of( new Source.NestedOptional( null ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void nestedOptionalToOptional_nonNull() { + Source source = new Source(); + source.setOptionalToOptional( Optional.of( new Source.NestedOptional( Optional.of( "some value" ) ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).contains("some value"); + } + + @ProcessorTest + public void nonOptionalToNonOptional_empty() { + Source source = new Source(); + source.setNonOptionalToNonOptional( Optional.empty() ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nonOptionalToNonOptional_null() { + Source source = new Source(); + source.setNonOptionalToNonOptional( null ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nestedNonOptionalToNonOptional_null() { + Source source = new Source(); + source.setNonOptionalToNonOptional( Optional.of( new Source.NestedNonOptional( null ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nestedNonOptionalToNonOptional_nonNull() { + Source source = new Source(); + source.setNonOptionalToNonOptional( Optional.of( new Source.NestedNonOptional( "some value" ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToNonOptional() ).isEqualTo("some value"); + } + + @ProcessorTest + public void nonOptionalToOptional_empty() { + Source source = new Source(); + source.setNonOptionalToOptional( Optional.empty() ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void nonOptionalToOptional_null() { + Source source = new Source(); + source.setNonOptionalToOptional( null ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void nestedNonOptionalToOptional_null() { + Source source = new Source(); + source.setNonOptionalToOptional( Optional.of( new Source.NestedNonOptional( null ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void nestedNonOptionalToOptional_nonNull() { + Source source = new Source(); + source.setNonOptionalToOptional( Optional.of( new Source.NestedNonOptional( "some value" ) ) ); + + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).contains("some value"); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java new file mode 100644 index 0000000000..a9c2787305 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java @@ -0,0 +1,80 @@ +/* + * 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.optionalmapping.nested; + +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Source { + + private Optional optionalToNonOptional; + private Optional optionalToOptional; + private Optional nonOptionalToNonOptional; + private Optional nonOptionalToOptional; + + public Optional getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional( + Optional optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional( + Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public Optional getNonOptionalToNonOptional() { + return nonOptionalToNonOptional; + } + + public void setNonOptionalToNonOptional( + Optional nonOptionalToNonOptional) { + this.nonOptionalToNonOptional = nonOptionalToNonOptional; + } + + public Optional getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional( + Optional nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public static class NestedOptional { + + private final Optional value; + + public NestedOptional(Optional value) { + this.value = value; + } + + public Optional getValue() { + return value; + } + } + + public static class NestedNonOptional { + + private final String value; + + public NestedNonOptional(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Target.java new file mode 100644 index 0000000000..6f60833dc3 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Target.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.test.optionalmapping.nested; + +import java.util.Optional; + +public class Target { + + private String optionalToNonOptional; + private Optional optionalToOptional; + private String nonOptionalToNonOptional; + private Optional nonOptionalToOptional; + + public String getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(String optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public String getNonOptionalToNonOptional() { + return nonOptionalToNonOptional; + } + + public void setNonOptionalToNonOptional(String nonOptionalToNonOptional) { + this.nonOptionalToNonOptional = nonOptionalToNonOptional; + } + + public Optional getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java new file mode 100644 index 0000000000..8c3ac047fd --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java @@ -0,0 +1,14 @@ +package org.mapstruct.ap.test.optionalmapping.nullcheckalways; + +import org.mapstruct.Mapper; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.factory.Mappers; + +@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +public interface OptionalNullCheckAlwaysMapper { + + OptionalNullCheckAlwaysMapper INSTANCE = Mappers.getMapper( OptionalNullCheckAlwaysMapper.class); + + Target toTarget(Source source); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java new file mode 100644 index 0000000000..e4abae91df --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java @@ -0,0 +1,64 @@ +package org.mapstruct.ap.test.optionalmapping.nullcheckalways; + +import java.util.Optional; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +// TODO Question +// Should NullValueCheckStrategy.ALWAYS ALSO do an Optional.isPresent() check? +// Or should we add a new OptionalCheckStrategy.ON/OFF config? +@WithClasses({ + OptionalNullCheckAlwaysMapper.class, + Source.class, + Target.class }) +public class OptionalNullCheckAlwaysTest { + + @ProcessorTest + public void optionalToOptional_empty() { + Source source = new Source(); + source.setOptionalToOptional( Optional.empty() ); + + Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); + assertThat( target.isOptionalToOptionalCalled() ).isFalse(); + } + + @ProcessorTest + public void optionalToOptional_null() { + Source source = new Source(); + source.setOptionalToOptional( null ); + + Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); + assertThat( target.isOptionalToOptionalCalled() ).isFalse(); + } + + @ProcessorTest + public void optionalToNonOptional_empty() { + Source source = new Source(); + source.setOptionalToNonOptional( Optional.empty() ); + + Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); + assertThat( target.isOptionalToNonOptionalCalled() ).isFalse(); + } + + @ProcessorTest + public void optionalToNonOptional_null() { + Source source = new Source(); + source.setOptionalToNonOptional( null ); + + Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); + assertThat( target.isOptionalToNonOptionalCalled() ).isFalse(); + } + + @ProcessorTest + public void nonOptionalToOptional_null() { + Source source = new Source(); + source.setNonOptionalToOptional( null ); + + Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); + assertThat( target.isNonOptionalToOptionalCalled() ).isFalse(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Source.java new file mode 100644 index 0000000000..d6c06cce3a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Source.java @@ -0,0 +1,40 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.nullcheckalways; + +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Source { + + private Optional optionalToOptional; + private Optional optionalToNonOptional; + private String nonOptionalToOptional; + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public Optional getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(Optional optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public String getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(String nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Target.java new file mode 100644 index 0000000000..451e407dde --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/Target.java @@ -0,0 +1,40 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.nullcheckalways; + +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Target { + + private boolean optionalToOptionalCalled; + private boolean optionalToNonOptionalCalled; + private boolean nonOptionalToOptionalCalled; + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptionalCalled = true; + } + + public void setOptionalToNonOptional(String optionalToNonOptional) { + this.optionalToNonOptionalCalled = true; + } + + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { + this.nonOptionalToOptionalCalled = true; + } + + public boolean isOptionalToOptionalCalled() { + return optionalToOptionalCalled; + } + + public boolean isOptionalToNonOptionalCalled() { + return optionalToNonOptionalCalled; + } + + public boolean isNonOptionalToOptionalCalled() { + return nonOptionalToOptionalCalled; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java new file mode 100644 index 0000000000..c84cb588f1 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java @@ -0,0 +1,20 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.sametype; + +import org.mapstruct.Mapper; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.factory.Mappers; + +@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION) +public interface OptionalSameTypeMapper { + + OptionalSameTypeMapper INSTANCE = Mappers.getMapper( + OptionalSameTypeMapper.class); + + Target toTarget(Source source); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java new file mode 100644 index 0000000000..6010be755d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java @@ -0,0 +1,247 @@ +/* + * 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.optionalmapping.sametype; + +import java.util.Optional; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +@WithClasses({ + OptionalSameTypeMapper.class, + Source.class, + Target.class }) +public class OptionalSameTypeTest { + + @ProcessorTest + public void constructorOptionalToOptional_present() { + Source source = new Source( Optional.of( "some value" ), null, null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void constructorOptionalToOptional_empty() { + Source source = new Source( Optional.empty(), null, null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + } + + // TODO Contentious + // Should null Optional map to null Optional, or explicitly to empty? + // This one is a bit stranger than the "different types" case. + // Because here, both the source and target are the same type: + // Optional -> Optional, therefore no nested mapping is required. + // By default, the mapper just generates `target.prop = source.prop`. + @ProcessorTest + public void constructorOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isNull(); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_present() { + Source source = new Source( null, Optional.of( "some value" ), null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_empty() { + Source source = new Source( null, Optional.empty(), null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void constructorNonOptionalToOptional_nonNull() { + Source source = new Source( null, null, "some value" ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void constructorNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToOptional_present() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( Optional.of( "some value" ) ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void optionalToOptional_empty() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( Optional.empty() ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + // TODO Contentious + // Should null Optional map to null Optional, or explicitly to empty? + // This one is a bit stranger than the "different types" case. + // Because here, both the source and target are the same type: + // Optional -> Optional, therefore no nested mapping is required. + // By default, the mapper just generates `target.prop = source.prop`. + @ProcessorTest + public void optionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isNull(); + } + + @ProcessorTest + public void optionalToNonOptional_present() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( Optional.of( "some value" ) ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void optionalToNonOptional_empty() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( Optional.empty() ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void optionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nonOptionalToOptional_nonNull() { + Source source = new Source( null, null, null ); + source.setNonOptionalToOptional( "some value" ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).contains( "some value" ); + } + + @ProcessorTest + public void nonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setNonOptionalToOptional( null ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToOptional_present() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = Optional.of( "some value" ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).contains( "some value" ); + } + + @ProcessorTest + public void publicOptionalToOptional_empty() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = Optional.empty(); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).isEmpty(); + } + + // TODO Contentious + // Should null Optional map to null Optional, or explicitly to empty? + // This one is a bit stranger than the "different types" case. + // Because here, both the source and target are the same type: + // Optional -> Optional, therefore no nested mapping is required. + // By default, the mapper just generates `target.prop = source.prop`. + @ProcessorTest + public void publicOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = null; + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).isNull(); + } + + @ProcessorTest + public void publicOptionalToNonOptional_present() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = Optional.of( "some value" ); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isEqualTo( "some value" ); + } + + @ProcessorTest + public void publicOptionalToNonOptional_empty() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = Optional.empty(); + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isNull(); + } + + @ProcessorTest + public void publicOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = null; + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isNull(); + } + + @ProcessorTest + public void publicNonOptionalToOptional_nonNull() { + Source source = new Source( null, null, null ); + source.publicNonOptionalToOptional = "some value" ; + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicNonOptionalToOptional ).contains( "some value" ); + } + + @ProcessorTest + public void publicNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicNonOptionalToOptional = null ; + + Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); + assertThat( target.publicNonOptionalToOptional ).isEmpty(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java new file mode 100644 index 0000000000..04962af7e0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java @@ -0,0 +1,67 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.sametype; + +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Source { + + private final Optional constructorOptionalToOptional; + private final Optional constructorOptionalToNonOptional; + private final String constructorNonOptionalToOptional; + + private Optional optionalToOptional; + private Optional optionalToNonOptional; + private String nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public Optional publicOptionalToNonOptional; + public String publicNonOptionalToOptional; + + public Source(Optional constructorOptionalToOptional, Optional constructorOptionalToNonOptional, + String constructorNonOptionalToOptional) { + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public Optional getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public String getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public Optional getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(Optional optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public String getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(String nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java new file mode 100644 index 0000000000..1f3763d7a2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java @@ -0,0 +1,67 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.sametype; + +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Target { + + private final Optional constructorOptionalToOptional; + private final String constructorOptionalToNonOptional; + private final Optional constructorNonOptionalToOptional; + + private Optional optionalToOptional; + private String optionalToNonOptional; + private Optional nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public String publicOptionalToNonOptional; + public Optional publicNonOptionalToOptional; + + public Target(Optional constructorOptionalToOptional, String constructorOptionalToNonOptional, + Optional constructorNonOptionalToOptional) { + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public String getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public Optional getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public String getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(String optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public Optional getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java index a5b9635c8d..ff1d916a3f 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java @@ -249,7 +249,7 @@ protected Target.SubType subTypeToSubType(Source.SubType subType) { Target.SubType subType1 = new Target.SubType( value ); - afterNonOptionalSource( subType ); + afterNonOptionalSourceWithNoTarget( subType ); return subType1; } @@ -264,7 +264,7 @@ protected Target.SubType subTypeOptionalToSubType(Optional optio Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); - afterOptionalSource( optional ); + afterOptionalSourceWithNoTarget( optional ); afterOptionalSourceWithNonOptionalTarget( subType1, optional ); return subType1; @@ -280,7 +280,7 @@ protected Optional subTypeToSubTypeOptional(Source.SubType subTy Source.SubType subType1 = subType; Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); - afterNonOptionalSource( subType ); + afterNonOptionalSourceWithNoTarget( subType ); afterNonOptionalSourceOptionalTarget( optional, subType ); return optional; @@ -295,7 +295,7 @@ protected Optional subTypeOptionalToSubTypeOptional(Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); - afterOptionalSource( optional ); + afterOptionalSourceWithNoTarget( optional ); afterOptionalSourceWithOptionalTarget( optional1, optional ); return optional1; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java index 915cd5e474..0e051c238c 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java @@ -122,7 +122,7 @@ protected Target.SubType subTypeToSubType(Source.SubType subType) { Target.SubType subType1 = new Target.SubType( value ); - afterNonOptionalSource( subType ); + afterNonOptionalSourceWithNoTarget( subType ); return subType1; } @@ -137,7 +137,7 @@ protected Target.SubType subTypeOptionalToSubType(Optional optio Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); - afterOptionalSource( optional ); + afterOptionalSourceWithNoTarget( optional ); afterOptionalSourceWithNonOptionalTarget( subType1, optional ); return subType1; @@ -153,7 +153,7 @@ protected Optional subTypeToSubTypeOptional(Source.SubType subTy Source.SubType subType1 = subType; Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); - afterNonOptionalSource( subType ); + afterNonOptionalSourceWithNoTarget( subType ); afterNonOptionalSourceOptionalTarget( optional, subType ); return optional; @@ -168,7 +168,7 @@ protected Optional subTypeOptionalToSubTypeOptional(Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); - afterOptionalSource( optional ); + afterOptionalSourceWithNoTarget( optional ); afterOptionalSourceWithOptionalTarget( optional1, optional ); return optional1; From 129b07d6923b3a88bcbc5ca41abb1768422ebf8b Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 19 Oct 2023 20:52:14 -0400 Subject: [PATCH 09/17] negate support --- copyright.txt | 3 ++- .../model/presence/OptionalPresenceCheck.java | 16 ++++++++++++++++ .../model/presence/OptionalPresenceCheck.ftl | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/copyright.txt b/copyright.txt index d6dc8d1b8a..ed1c0a8dda 100644 --- a/copyright.txt +++ b/copyright.txt @@ -38,6 +38,7 @@ Joshua Spoerri - https://github.com/spoerri Jude Niroshan - https://github.com/JudeNiroshan Justyna Kubica-Ledzion - https://github.com/JKLedzion Kemal Özcan - https://github.com/yekeoe +Ken Wang - https://github.com/ro0sterjam Kevin Grüneberg - https://github.com/kevcodez Lukas Lazar - https://github.com/LukeLaz Nikolas Charalambidis - https://github.com/Nikolas-Charalambidis @@ -69,4 +70,4 @@ Tomek Gubala - https://github.com/vgtworld Valentin Kulesh - https://github.com/unshare Vincent Alexander Beelte - https://github.com/grandmasterpixel Winter Andreas - https://github.dev/wandi34 -Xiu Hong Kooi - https://github.com/kooixh +Xiu Hong Kooi - https://github.com/kooixh \ No newline at end of file diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.java b/processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.java index 63f15e8557..26430c2385 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.java @@ -21,9 +21,16 @@ public class OptionalPresenceCheck extends ModelElement implements PresenceCheck { private final String sourceReference; + private final boolean negate; public OptionalPresenceCheck(String sourceReference) { this.sourceReference = sourceReference; + this.negate = false; + } + + public OptionalPresenceCheck(String sourceReference, boolean negate) { + this.sourceReference = sourceReference; + this.negate = negate; } public String getSourceReference() { @@ -35,6 +42,15 @@ public Set getImportTypes() { return Collections.emptySet(); } + public boolean isNegate() { + return negate; + } + + @Override + public PresenceCheck negate() { + return new OptionalPresenceCheck( sourceReference, !negate ); + } + @Override public boolean equals(Object o) { if ( this == o ) { diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl index 775f5a8448..36a763ca5f 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/presence/OptionalPresenceCheck.ftl @@ -6,4 +6,4 @@ --> <#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.presence.OptionalPresenceCheck" --> -${sourceReference}.isPresent() \ No newline at end of file +${sourceReference}<#if isNegate()>.isEmpty()<#else>.isPresent() \ No newline at end of file From c9b551aebc0c5b1d9b84936100e4d36e87bb32bb Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Sun, 19 Nov 2023 23:13:16 -0500 Subject: [PATCH 10/17] map to default for all types --- .../mapstruct/NullValueMappingStrategy.java | 1 + .../model/NormalTypeMappingMethod.java | 5 + .../model/common/InitDefaultValue.java | 32 ++++ .../ap/internal/model/common/Type.java | 15 ++ .../ap/internal/model/BeanMappingMethod.ftl | 5 +- .../internal/model/OptionalMappingMethod.ftl | 16 +- .../model/common/InitDefaultValue.ftl | 31 ++++ .../ap/internal/model/macro/CommonMacros.ftl | 6 +- .../OptionalBeforeAfterMapper.java | 3 +- .../OptionalDifferentTypesMapper.java | 3 +- .../OptionalDifferentTypesTest.java | 6 +- .../MapNullToDefaultMapper.java | 20 +++ .../MapNullToDefaultTest.java | 151 ++++++++++++++++++ .../mapnulltodefault/Source.java | 99 ++++++++++++ .../mapnulltodefault/Target.java | 98 ++++++++++++ 15 files changed, 468 insertions(+), 23 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java create mode 100644 processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Target.java diff --git a/core/src/main/java/org/mapstruct/NullValueMappingStrategy.java b/core/src/main/java/org/mapstruct/NullValueMappingStrategy.java index 519a28bd81..d978750400 100644 --- a/core/src/main/java/org/mapstruct/NullValueMappingStrategy.java +++ b/core/src/main/java/org/mapstruct/NullValueMappingStrategy.java @@ -28,6 +28,7 @@ public enum NullValueMappingStrategy { * case. *
  1. For iterable mapping methods an empty collection will be returned.
  2. *
  3. For map mapping methods an empty map will be returned.
  4. + *
  5. For optional mapping methods an empty optional will be returned.
  6. * */ RETURN_DEFAULT; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java index 79cd0e0566..5ac2e299ab 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Set; +import org.mapstruct.ap.internal.model.common.InitDefaultValue; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.source.Method; @@ -67,6 +68,10 @@ public MethodReference getFactoryMethod() { return this.factoryMethod; } + public InitDefaultValue getInitDefaultValueForResultType() { + return new InitDefaultValue( this.getResultType(), this.getFactoryMethod() ); + } + public List getAnnotations() { return annotations; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java new file mode 100644 index 0000000000..bda35dae3e --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java @@ -0,0 +1,32 @@ +package org.mapstruct.ap.internal.model.common; + +import java.util.HashSet; +import java.util.Set; + +import org.mapstruct.ap.internal.model.MethodReference; + +public class InitDefaultValue extends ModelElement { + + private final Type targetType; + private final MethodReference factoryMethod; + + public InitDefaultValue(Type targetType, MethodReference factoryMethod) { + this.targetType = targetType; + this.factoryMethod = factoryMethod; + } + + @Override + public Set getImportTypes() { + Set types = new HashSet<>(); + types.add( targetType ); + return types; + } + + public Type getTargetType() { + return targetType; + } + + public MethodReference getFactoryMethod() { + return factoryMethod; + } +} 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 52139727a1..6dad0b12bf 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 @@ -137,6 +137,7 @@ public class Type extends ModelElement implements Comparable { private Type boxedEquivalent = null; private Boolean hasAccessibleConstructor; + private Boolean hasAccessibleDefaultConstructor; private final Filters filters; @@ -1357,6 +1358,20 @@ public boolean hasAccessibleConstructor() { return hasAccessibleConstructor; } + public boolean hasAccessibleDefaultConstructor() { + if ( hasAccessibleDefaultConstructor == null ) { + hasAccessibleDefaultConstructor = false; + List constructors = ElementFilter.constructorsIn( typeElement.getEnclosedElements() ); + for ( ExecutableElement constructor : constructors ) { + if ( constructor.isDefault() && !constructor.getModifiers().contains( Modifier.PRIVATE ) ) { + hasAccessibleDefaultConstructor = true; + break; + } + } + } + return hasAccessibleDefaultConstructor; + } + /** * Returns the direct supertypes of a type. The interface types, if any, * will appear last in the list. diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl index 8fb5bfdef0..1481052e77 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl @@ -117,11 +117,12 @@ <#else> - <#if mapNullToDefault>if ( <@includeModel object=getPresenceCheckByParameter(sourceParameters[0]) /> ) { + <#assign propertyMappings = propertyMappingsByParameter(sourceParameters[0])/> + <#if mapNullToDefault && (propertyMappings?size > 0)>if ( <@includeModel object=getPresenceCheckByParameter(sourceParameters[0]) /> ) { <#list propertyMappingsByParameter(sourceParameters[0]) as propertyMapping> <@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/> - <#if mapNullToDefault>} + <#if mapNullToDefault && (propertyMappings?size > 0)>} <#list constantMappings as constantMapping> <@includeModel object=constantMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/> diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl index 8b41592ebb..6bd2b7fc7b 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl @@ -14,22 +14,16 @@ - if ( ${sourceParameter.name} == null ) { - <#if resultType.optionalType> - <#-- regardless of mapNullToDefault value, never return null for Optional resultType --> - return Optional.empty(); + if ( <@includeModel object=sourceParameterPresenceCheck.negate() /> ) { + <#if (!sourceParameter.type.optionalType && resultType.optionalType) || mapNullToDefault> + return <@includeModel object=initDefaultValueForResultType/>; <#else> - <#if !mapNullToDefault> - return null; - <#else> - <#-- TODO: this should return the default value for whatever the returnType is --> - return null; - + return<#if returnType.name != "void"> null; } <#if sourceParameter.type.optionalType> - <@includeModel object=returnType/> ${resultName} = ${sourceParameter.name}.map( ${loopVariableName} -> <@includeModel object=elementAssignment/> )<#if !returnType.optionalType>.orElse( null ); + <@includeModel object=returnType/> ${resultName} = ${sourceParameter.name}.map( ${loopVariableName} -> <@includeModel object=elementAssignment/> )<#if !returnType.optionalType>.orElse( <#if mapNullToDefault><@includeModel object=initDefaultValueForResultType/><#else>null ); <#else> <@includeModel object=sourceElementType/> ${loopVariableName} = ${sourceParameter.name}; <@includeModel object=returnType/> ${resultName} = Optional.ofNullable( <@includeModel object=elementAssignment/> ); diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl new file mode 100644 index 0000000000..2dbbf7616a --- /dev/null +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl @@ -0,0 +1,31 @@ +<#-- + + Copyright MapStruct Authors. + + Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + +--> +<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.common.InitDefaultValue" --> +<#if factoryMethod??> + <@includeModel object=factoryMethod targetType=targetType/> +<#else> + <@constructTargetObject/> + +<#-- + macro: constructTargetObject + + purpose: Either call the constructor of the target object directly or of the implementing type. +--> +<#macro constructTargetObject><@compress single_line=true> + <#if targetType.implementationType?? && targetType.implementationType.hasAccessibleDefaultConstructor()> + new <@includeModel object=targetType.implementationType/>() + <#elseif targetType.arrayType> + new <@includeModel object=targetType.componentType/>[0] + <#elseif targetType.sensibleDefault??> + ${targetType.sensibleDefault} + <#elseif targetType.hasAccessibleDefaultConstructor()> + new <@includeModel object=targetType/>() + <#else> + null + + \ No newline at end of file diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl index 6fc1e72df7..bce28ebe19 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/macro/CommonMacros.ftl @@ -22,7 +22,7 @@ } <@elseDefaultAssignment/> <#elseif includeSourceNullCheck || ext.defaultValueAssignment??> - if ( <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference} != null<#if sourceType.optionalType> && <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference}.isPresent() ) { + if ( <#if sourceLocalVarName??>${sourceLocalVarName}<#else>${sourceReference} != null ) { <#nested> } <@elseDefaultAssignment/> @@ -40,9 +40,9 @@ else { <@handeDefaultAssigment/> } - <#elseif setExplicitlyToDefault || setExplicitlyToNull || ext.targetType.optionalType> + <#elseif setExplicitlyToDefault || setExplicitlyToNull> else { - <#if ext.targetBeanName?has_content>${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if setExplicitlyToDefault || ext.targetType.optionalType><@lib.initTargetObject/><#else>null; + <#if ext.targetBeanName?has_content>${ext.targetBeanName}.${ext.targetWriteAccessorName}<@lib.handleWrite><#if setExplicitlyToDefault><@lib.initTargetObject/><#else>null; } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java index e993637b9a..2523a0a59f 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java @@ -6,11 +6,10 @@ import org.mapstruct.BeforeMapping; import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; -import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.TargetType; import org.mapstruct.factory.Mappers; -@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +@Mapper public interface OptionalBeforeAfterMapper { OptionalBeforeAfterMapper INSTANCE = Mappers.getMapper( OptionalBeforeAfterMapper.class); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java index 04775bce2d..296191af4d 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java @@ -6,10 +6,9 @@ package org.mapstruct.ap.test.optionalmapping.differenttypes; import org.mapstruct.Mapper; -import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.factory.Mappers; -@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ON_IMPLICIT_CONVERSION) +@Mapper public interface OptionalDifferentTypesMapper { OptionalDifferentTypesMapper INSTANCE = Mappers.getMapper( diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java index 1398c61746..cc5ef8a162 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java @@ -41,7 +41,7 @@ public void constructorOptionalToOptional_null() { Source source = new Source( null, null, null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); - assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + assertThat( target.getConstructorOptionalToOptional() ).isNull(); } @ProcessorTest @@ -110,7 +110,7 @@ public void optionalToOptional_null() { source.setOptionalToOptional( null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToOptional() ).isEmpty(); + assertThat( target.getOptionalToOptional() ).isNull(); } @ProcessorTest @@ -184,7 +184,7 @@ public void publicOptionalToOptional_null() { source.publicOptionalToOptional = null; Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); - assertThat( target.publicOptionalToOptional ).isEmpty(); + assertThat( target.publicOptionalToOptional ).isNull(); } @ProcessorTest diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultMapper.java new file mode 100644 index 0000000000..022a3c0a76 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultMapper.java @@ -0,0 +1,20 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.optionalmapping.mapnulltodefault; + +import org.mapstruct.Mapper; +import org.mapstruct.NullValueMappingStrategy; +import org.mapstruct.factory.Mappers; + +@Mapper(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT) +public interface MapNullToDefaultMapper { + + MapNullToDefaultMapper INSTANCE = Mappers.getMapper( + MapNullToDefaultMapper.class); + + Target toTarget(Source source); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java new file mode 100644 index 0000000000..52cc1f206a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java @@ -0,0 +1,151 @@ +/* + * 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.optionalmapping.mapnulltodefault; + +import java.util.Optional; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +@WithClasses({ + MapNullToDefaultMapper.class, + Source.class, + Target.class }) +public class MapNullToDefaultTest { + + @ProcessorTest + public void constructorOptionalToOptional_empty() { + Source source = new Source( Optional.empty(), null, null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void constructorOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_empty() { + Source source = new Source( null, Optional.empty(), null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void constructorNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToOptional_empty() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( Optional.empty() ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToNonOptional_empty() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( Optional.empty() ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void optionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setNonOptionalToOptional( null ); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToOptional_empty() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = Optional.empty(); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = null; + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToNonOptional_empty() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = Optional.empty(); + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isNull(); + } + + @ProcessorTest + public void publicOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = null; + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isNull(); + } + + @ProcessorTest + public void publicNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicNonOptionalToOptional = null ; + + Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicNonOptionalToOptional ).isEmpty(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Source.java new file mode 100644 index 0000000000..f67fadbcf6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Source.java @@ -0,0 +1,99 @@ +/* + * 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.optionalmapping.mapnulltodefault; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Source { + + private final Optional constructorOptionalToOptional; + private final Optional constructorOptionalToNonOptional; + private final SubType constructorNonOptionalToOptional; + + private Optional optionalToOptional; + private Optional optionalToNonOptional; + private SubType nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public Optional publicOptionalToNonOptional; + public SubType publicNonOptionalToOptional; + + public Source(Optional constructorOptionalToOptional, Optional constructorOptionalToNonOptional, + SubType constructorNonOptionalToOptional) { + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public Optional getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public SubType getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public Optional getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(Optional optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public SubType getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(SubType nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Target.java new file mode 100644 index 0000000000..603be2ebab --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Target.java @@ -0,0 +1,98 @@ +/* + * 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.optionalmapping.mapnulltodefault; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Target { + + private final Optional constructorOptionalToOptional; + private final SubType constructorOptionalToNonOptional; + private final Optional constructorNonOptionalToOptional; + + private Optional optionalToOptional; + private SubType optionalToNonOptional; + private Optional nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public SubType publicOptionalToNonOptional; + public Optional publicNonOptionalToOptional; + + public Target(Optional constructorOptionalToOptional, SubType constructorOptionalToNonOptional, + Optional constructorNonOptionalToOptional) { + this.constructorOptionalToOptional = constructorOptionalToOptional; + this.constructorOptionalToNonOptional = constructorOptionalToNonOptional; + this.constructorNonOptionalToOptional = constructorNonOptionalToOptional; + } + + public Optional getConstructorOptionalToOptional() { + return constructorOptionalToOptional; + } + + public SubType getConstructorOptionalToNonOptional() { + return constructorOptionalToNonOptional; + } + + public Optional getConstructorNonOptionalToOptional() { + return constructorNonOptionalToOptional; + } + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public SubType getOptionalToNonOptional() { + return optionalToNonOptional; + } + + public void setOptionalToNonOptional(SubType optionalToNonOptional) { + this.optionalToNonOptional = optionalToNonOptional; + } + + public Optional getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } +} From 0e2832484032a1f94e9238ef3397586010b83e81 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Mon, 20 Nov 2023 00:03:01 -0500 Subject: [PATCH 11/17] more test --- .../NullValuePropertyMappingStrategy.java | 1 + .../model/common/InitDefaultValue.ftl | 1 + .../MapNullToDefaultTest.java | 151 ------------------ .../NullValuePropertyToDefaultMapper.java | 22 +++ .../NullValuePropertyToDefaultTest.java | 59 +++++++ .../nullvaluepropertytodefault/Source.java | 66 ++++++++ .../nullvaluepropertytodefault/Target.java | 65 ++++++++ .../NullValueToDefaultMapper.java} | 8 +- .../NullValueToDefaultTest.java | 99 ++++++++++++ .../Source.java | 2 +- .../Target.java | 2 +- 11 files changed, 319 insertions(+), 157 deletions(-) delete mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java rename processor/src/test/java/org/mapstruct/ap/test/optionalmapping/{mapnulltodefault/MapNullToDefaultMapper.java => nullvaluetodefault/NullValueToDefaultMapper.java} (64%) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java rename processor/src/test/java/org/mapstruct/ap/test/optionalmapping/{mapnulltodefault => nullvaluetodefault}/Source.java (97%) rename processor/src/test/java/org/mapstruct/ap/test/optionalmapping/{mapnulltodefault => nullvaluetodefault}/Target.java (97%) diff --git a/core/src/main/java/org/mapstruct/NullValuePropertyMappingStrategy.java b/core/src/main/java/org/mapstruct/NullValuePropertyMappingStrategy.java index 9e06e723b6..9c0a63cbf3 100644 --- a/core/src/main/java/org/mapstruct/NullValuePropertyMappingStrategy.java +++ b/core/src/main/java/org/mapstruct/NullValuePropertyMappingStrategy.java @@ -36,6 +36,7 @@ public enum NullValuePropertyMappingStrategy { *

    * This means: *

      + *
    1. For {@code Optional} MapStruct generates an {@code Optional.empty()}
    2. *
    3. For {@code List} MapStruct generates an {@code ArrayList}
    4. *
    5. For {@code Map} a {@code HashMap}
    6. *
    7. For arrays an empty array
    8. diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl index 2dbbf7616a..71c82c1b5e 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl @@ -15,6 +15,7 @@ macro: constructTargetObject purpose: Either call the constructor of the target object directly or of the implementing type. + If the target type is an Object but does not have a public default constructor, null is returned. --> <#macro constructTargetObject><@compress single_line=true> <#if targetType.implementationType?? && targetType.implementationType.hasAccessibleDefaultConstructor()> diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java deleted file mode 100644 index 52cc1f206a..0000000000 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.optionalmapping.mapnulltodefault; - -import java.util.Optional; - -import org.mapstruct.ap.testutil.ProcessorTest; -import org.mapstruct.ap.testutil.WithClasses; - -import static org.assertj.core.api.Assertions.assertThat; - -@WithClasses({ - MapNullToDefaultMapper.class, - Source.class, - Target.class }) -public class MapNullToDefaultTest { - - @ProcessorTest - public void constructorOptionalToOptional_empty() { - Source source = new Source( Optional.empty(), null, null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void constructorOptionalToOptional_null() { - Source source = new Source( null, null, null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void constructorOptionalToNonOptional_empty() { - Source source = new Source( null, Optional.empty(), null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); - } - - @ProcessorTest - public void constructorOptionalToNonOptional_null() { - Source source = new Source( null, null, null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); - } - - @ProcessorTest - public void constructorNonOptionalToOptional_null() { - Source source = new Source( null, null, null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getConstructorNonOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void optionalToOptional_empty() { - Source source = new Source( null, null, null ); - source.setOptionalToOptional( Optional.empty() ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void optionalToOptional_null() { - Source source = new Source( null, null, null ); - source.setOptionalToOptional( null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void optionalToNonOptional_empty() { - Source source = new Source( null, null, null ); - source.setOptionalToNonOptional( Optional.empty() ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToNonOptional() ).isNull(); - } - - @ProcessorTest - public void optionalToNonOptional_null() { - Source source = new Source( null, null, null ); - source.setOptionalToNonOptional( null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToNonOptional() ).isNull(); - } - - @ProcessorTest - public void nonOptionalToOptional_null() { - Source source = new Source( null, null, null ); - source.setNonOptionalToOptional( null ); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.getNonOptionalToOptional() ).isEmpty(); - } - - @ProcessorTest - public void publicOptionalToOptional_empty() { - Source source = new Source( null, null, null ); - source.publicOptionalToOptional = Optional.empty(); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.publicOptionalToOptional ).isEmpty(); - } - - @ProcessorTest - public void publicOptionalToOptional_null() { - Source source = new Source( null, null, null ); - source.publicOptionalToOptional = null; - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.publicOptionalToOptional ).isEmpty(); - } - - @ProcessorTest - public void publicOptionalToNonOptional_empty() { - Source source = new Source( null, null, null ); - source.publicOptionalToNonOptional = Optional.empty(); - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.publicOptionalToNonOptional ).isNull(); - } - - @ProcessorTest - public void publicOptionalToNonOptional_null() { - Source source = new Source( null, null, null ); - source.publicOptionalToNonOptional = null; - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.publicOptionalToNonOptional ).isNull(); - } - - @ProcessorTest - public void publicNonOptionalToOptional_null() { - Source source = new Source( null, null, null ); - source.publicNonOptionalToOptional = null ; - - Target target = MapNullToDefaultMapper.INSTANCE.toTarget( source ); - assertThat( target.publicNonOptionalToOptional ).isEmpty(); - } - -} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.java new file mode 100644 index 0000000000..7ab41d3037 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.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.optionalmapping.nullvaluepropertytodefault; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.NullValueMappingStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.mapstruct.factory.Mappers; + +@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT) +public interface NullValuePropertyToDefaultMapper { + + NullValuePropertyToDefaultMapper INSTANCE = Mappers.getMapper( + NullValuePropertyToDefaultMapper.class); + + void mapTarget(Source source, @MappingTarget Target target); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java new file mode 100644 index 0000000000..d6b7f69eed --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.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.optionalmapping.nullvaluepropertytodefault; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +@WithClasses({ + NullValuePropertyToDefaultMapper.class, + Source.class, + Target.class }) +public class NullValuePropertyToDefaultTest { + + @ProcessorTest + public void optionalToOptional_null() { + Source source = new Source(); + source.setOptionalToOptional( null ); + + Target target = new Target(); + NullValuePropertyToDefaultMapper.INSTANCE.mapTarget( source, target ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void nonOptionalToOptional_null() { + Source source = new Source(); + source.setNonOptionalToOptional( null ); + + Target target = new Target(); + NullValuePropertyToDefaultMapper.INSTANCE.mapTarget( source, target ); + assertThat( target.getNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToOptional_null() { + Source source = new Source(); + source.publicOptionalToOptional = null; + + Target target = new Target(); + NullValuePropertyToDefaultMapper.INSTANCE.mapTarget( source, target ); + assertThat( target.publicOptionalToOptional ).isEmpty(); + } + + @ProcessorTest + public void publicNonOptionalToOptional_null() { + Source source = new Source(); + source.publicNonOptionalToOptional = null; + + Target target = new Target(); + NullValuePropertyToDefaultMapper.INSTANCE.mapTarget( source, target ); + assertThat( target.publicNonOptionalToOptional ).isEmpty(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java new file mode 100644 index 0000000000..2ab8b8cefa --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java @@ -0,0 +1,66 @@ +/* + * 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.optionalmapping.nullvaluepropertytodefault; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Source { + + private Optional optionalToOptional; + private SubType nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public SubType publicNonOptionalToOptional; + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public SubType getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(SubType nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java new file mode 100644 index 0000000000..071256f5d2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java @@ -0,0 +1,65 @@ +/* + * 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.optionalmapping.nullvaluepropertytodefault; + +import java.util.Objects; +import java.util.Optional; + +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class Target { + + private Optional optionalToOptional; + private Optional nonOptionalToOptional; + + public Optional publicOptionalToOptional; + public Optional publicNonOptionalToOptional; + + public Optional getOptionalToOptional() { + return optionalToOptional; + } + + public void setOptionalToOptional(Optional optionalToOptional) { + this.optionalToOptional = optionalToOptional; + } + + public Optional getNonOptionalToOptional() { + return nonOptionalToOptional; + } + + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { + this.nonOptionalToOptional = nonOptionalToOptional; + } + + public static class SubType { + + private final String value; + + public SubType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + SubType subType = (SubType) o; + return Objects.equals( value, subType.value ); + } + + @Override + public int hashCode() { + return Objects.hash( value ); + } + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapper.java similarity index 64% rename from processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultMapper.java rename to processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapper.java index 022a3c0a76..fd9b790293 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/MapNullToDefaultMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapper.java @@ -3,17 +3,17 @@ * * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 */ -package org.mapstruct.ap.test.optionalmapping.mapnulltodefault; +package org.mapstruct.ap.test.optionalmapping.nullvaluetodefault; import org.mapstruct.Mapper; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.factory.Mappers; @Mapper(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT) -public interface MapNullToDefaultMapper { +public interface NullValueToDefaultMapper { - MapNullToDefaultMapper INSTANCE = Mappers.getMapper( - MapNullToDefaultMapper.class); + NullValueToDefaultMapper INSTANCE = Mappers.getMapper( + NullValueToDefaultMapper.class); Target toTarget(Source source); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java new file mode 100644 index 0000000000..a98ccbc3ef --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java @@ -0,0 +1,99 @@ +/* + * 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.optionalmapping.nullvaluetodefault; + +import java.util.Optional; + +import org.mapstruct.ap.testutil.ProcessorTest; +import org.mapstruct.ap.testutil.WithClasses; + +import static org.assertj.core.api.Assertions.assertThat; + +@WithClasses({ + NullValueToDefaultMapper.class, + Source.class, + Target.class }) +public class NullValueToDefaultTest { + + @ProcessorTest + public void constructorOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void constructorOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void constructorNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getConstructorNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToOptional( null ); + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void optionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.setOptionalToNonOptional( null ); + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getOptionalToNonOptional() ).isNull(); + } + + @ProcessorTest + public void nonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.setNonOptionalToOptional( null ); + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.getNonOptionalToOptional() ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToOptional = null; + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToOptional ).isEmpty(); + } + + @ProcessorTest + public void publicOptionalToNonOptional_null() { + Source source = new Source( null, null, null ); + source.publicOptionalToNonOptional = null; + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicOptionalToNonOptional ).isNull(); + } + + @ProcessorTest + public void publicNonOptionalToOptional_null() { + Source source = new Source( null, null, null ); + source.publicNonOptionalToOptional = null ; + + Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); + assertThat( target.publicNonOptionalToOptional ).isEmpty(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Source.java similarity index 97% rename from processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Source.java rename to processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Source.java index f67fadbcf6..90ea86debd 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Source.java @@ -3,7 +3,7 @@ * * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 */ -package org.mapstruct.ap.test.optionalmapping.mapnulltodefault; +package org.mapstruct.ap.test.optionalmapping.nullvaluetodefault; import java.util.Objects; import java.util.Optional; diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Target.java similarity index 97% rename from processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Target.java rename to processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Target.java index 603be2ebab..4e91a05453 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/mapnulltodefault/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Target.java @@ -3,7 +3,7 @@ * * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 */ -package org.mapstruct.ap.test.optionalmapping.mapnulltodefault; +package org.mapstruct.ap.test.optionalmapping.nullvaluetodefault; import java.util.Objects; import java.util.Optional; From 262b608c23fbe120ec4125038f4e4f8d3e0b9d1a Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Mon, 20 Nov 2023 21:01:17 -0500 Subject: [PATCH 12/17] nested optional support --- .../model/beanmapping/SourceReference.java | 3 +- .../ap/internal/model/common/Type.java | 9 +++ .../mapstruct/ap/internal/util/Strings.java | 1 + .../util/accessor/OptionalValueAccessor.java | 55 +++++++++++++++++++ .../model/NestedPropertyMappingMethod.ftl | 6 +- .../nested/OptionalNestedMapper.java | 9 +-- .../nested/OptionalNestedTest.java | 4 +- .../OptionalNullCheckAlwaysTest.java | 23 -------- 8 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.java 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 73ec84b6b7..9b63da938c 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 @@ -120,7 +120,8 @@ public SourceReference build() { ); } - String[] segments = sourceNameTrimmed.split( "\\." ); + // Split by "." but also include "?" as a separate segment for optionals + String[] segments = sourceNameTrimmed.split( "\\.|(?=\\?)" ); // start with an invalid source reference SourceReference result = new SourceReference( null, new ArrayList<>( ), false ); 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 6dad0b12bf..47e5fe7f49 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 @@ -52,6 +52,7 @@ import org.mapstruct.ap.internal.util.accessor.AccessorType; import org.mapstruct.ap.internal.util.accessor.FieldElementAccessor; import org.mapstruct.ap.internal.util.accessor.MapValueAccessor; +import org.mapstruct.ap.internal.util.accessor.OptionalValueAccessor; import org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor; import org.mapstruct.ap.internal.util.accessor.ReadAccessor; @@ -689,6 +690,14 @@ public ReadAccessor getReadAccessor(String propertyName, boolean allowedMapToBea .findAny() .orElse( null ); return new MapValueAccessor( getMethod, typeParameters.get( 1 ).getTypeMirror(), propertyName ); + } else if ( propertyName.equals( "?" ) && isOptionalType() ) { + ExecutableElement getMethod = getAllMethods() + .stream() + .filter( m -> m.getSimpleName().contentEquals( "orElse" ) ) + .filter( m -> m.getParameters().size() == 1 ) + .findAny() + .orElse( null ); + return new OptionalValueAccessor( getMethod, typeParameters.get( 0 ).getTypeMirror(), propertyName ); } Map readAccessors = getPropertyReadAccessors(); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Strings.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Strings.java index 88e0bdf6f6..54a034c357 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Strings.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Strings.java @@ -148,6 +148,7 @@ public static String getSafeVariableName(String name, String... existingVariable * any Java keyword; starting with a lower-case letter */ public static String getSafeVariableName(String name, Collection existingVariableNames) { + name = name.equals( "?" ) ? "optionalValue" : name; name = decapitalize( sanitizeIdentifierName( name ) ); name = joinAndCamelize( extractParts( name ) ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.java b/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.java new file mode 100644 index 0000000000..21c8b34b4b --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.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.internal.util.accessor; + +import java.util.Collections; +import java.util.Set; +import javax.lang.model.element.Element; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.TypeMirror; + +public class OptionalValueAccessor implements ReadAccessor { + + private final TypeMirror valueTypeMirror; + private final String simpleName; + private final Element element; + + public OptionalValueAccessor(Element element, TypeMirror valueTypeMirror, String simpleName) { + this.element = element; + this.valueTypeMirror = valueTypeMirror; + this.simpleName = simpleName; + } + + @Override + public TypeMirror getAccessedType() { + return valueTypeMirror; + } + + @Override + public String getSimpleName() { + return this.simpleName; + } + + @Override + public Set getModifiers() { + return Collections.emptySet(); + } + + @Override + public Element getElement() { + return this.element; + } + + @Override + public AccessorType getAccessorType() { + return AccessorType.GETTER; + } + + @Override + public String getReadValueSource() { + return "orElse( null )"; + } +} diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl index 8eabe23a16..7a54a6d029 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl @@ -21,7 +21,11 @@ <#if !entry.presenceChecker?? > <#if !entry.type.primitive> if ( ${entry.name} == null ) { - return ${returnType.null}; + <#if returnType.isOptionalType()> + return Optional.empty(); + <#else> + return ${returnType.null}; + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java index dd6f34028d..78eb204a35 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java @@ -2,6 +2,7 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.mapstruct.NullValuePropertyMappingStrategy; import org.mapstruct.factory.Mappers; @Mapper @@ -9,10 +10,10 @@ public interface OptionalNestedMapper { OptionalNestedMapper INSTANCE = Mappers.getMapper(OptionalNestedMapper.class); - @Mapping( source = "optionalToNonOptional.value", target = "optionalToNonOptional") - @Mapping( source = "optionalToOptional.value", target = "optionalToOptional") - @Mapping( source = "nonOptionalToNonOptional.value", target = "nonOptionalToNonOptional") - @Mapping( source = "nonOptionalToOptional.value", target = "nonOptionalToOptional") + @Mapping( source = "optionalToNonOptional?.value?", target = "optionalToNonOptional") + @Mapping( source = "optionalToOptional?.value", target = "optionalToOptional") + @Mapping( source = "nonOptionalToNonOptional?.value", target = "nonOptionalToNonOptional") + @Mapping( source = "nonOptionalToOptional?.value", target = "nonOptionalToOptional") Target toTarget(Source source); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java index a64888efdb..0ee5b6b8c0 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java @@ -91,7 +91,7 @@ public void nestedOptionalToOptional_null() { source.setOptionalToOptional( Optional.of( new Source.NestedOptional( null ) ) ); Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToOptional() ).isEmpty(); + assertThat( target.getOptionalToOptional() ).isNull(); } @ProcessorTest @@ -172,7 +172,7 @@ public void nestedNonOptionalToOptional_nonNull() { source.setNonOptionalToOptional( Optional.of( new Source.NestedNonOptional( "some value" ) ) ); Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToOptional() ).contains("some value"); + assertThat( target.getNonOptionalToOptional() ).contains("some value"); } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java index e4abae91df..b0360bfe60 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java @@ -1,30 +1,16 @@ package org.mapstruct.ap.test.optionalmapping.nullcheckalways; -import java.util.Optional; - import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; import static org.assertj.core.api.Assertions.assertThat; -// TODO Question -// Should NullValueCheckStrategy.ALWAYS ALSO do an Optional.isPresent() check? -// Or should we add a new OptionalCheckStrategy.ON/OFF config? @WithClasses({ OptionalNullCheckAlwaysMapper.class, Source.class, Target.class }) public class OptionalNullCheckAlwaysTest { - @ProcessorTest - public void optionalToOptional_empty() { - Source source = new Source(); - source.setOptionalToOptional( Optional.empty() ); - - Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); - assertThat( target.isOptionalToOptionalCalled() ).isFalse(); - } - @ProcessorTest public void optionalToOptional_null() { Source source = new Source(); @@ -34,15 +20,6 @@ public void optionalToOptional_null() { assertThat( target.isOptionalToOptionalCalled() ).isFalse(); } - @ProcessorTest - public void optionalToNonOptional_empty() { - Source source = new Source(); - source.setOptionalToNonOptional( Optional.empty() ); - - Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); - assertThat( target.isOptionalToNonOptionalCalled() ).isFalse(); - } - @ProcessorTest public void optionalToNonOptional_null() { Source source = new Source(); From 9e969e7308a49ef182ca82b86d72a896cf881e1a Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Mon, 20 Nov 2023 21:58:23 -0500 Subject: [PATCH 13/17] formatting --- .../ap/internal/model/InitDefaultValue.java | 53 +++++++++++ .../model/NormalTypeMappingMethod.java | 1 - .../model/common/InitDefaultValue.java | 32 ------- .../ap/internal/model/common/Type.java | 95 +++++++++---------- .../model/{common => }/InitDefaultValue.ftl | 2 +- .../OptionalBeforeAfterMapper.java | 28 +++--- .../beforeafter/OptionalBeforeAfterTest.java | 5 + .../optionalmapping/beforeafter/Source.java | 4 +- .../OptionalDifferentTypesMapper.java | 2 +- .../OptionalDifferentTypesTest.java | 59 ++++++------ .../differenttypes/Source.java | 7 +- .../differenttypes/Target.java | 3 + .../nested/OptionalNestedMapper.java | 16 ++-- .../nested/OptionalNestedTest.java | 58 +++++------ .../test/optionalmapping/nested/Source.java | 14 +-- .../OptionalNullCheckAlwaysMapper.java | 7 +- .../OptionalNullCheckAlwaysTest.java | 18 ++-- .../NullValuePropertyToDefaultMapper.java | 3 +- .../NullValuePropertyToDefaultTest.java | 13 +-- .../nullvaluepropertytodefault/Source.java | 6 +- .../nullvaluepropertytodefault/Target.java | 2 + .../NullValueToDefaultMapper.java | 2 +- .../NullValueToDefaultTest.java | 27 +++--- .../nullvaluetodefault/Source.java | 7 +- .../nullvaluetodefault/Target.java | 3 + .../sametype/OptionalSameTypeMapper.java | 2 +- .../sametype/OptionalSameTypeTest.java | 59 ++++++------ .../test/optionalmapping/sametype/Source.java | 3 + .../test/optionalmapping/sametype/Target.java | 3 + 29 files changed, 295 insertions(+), 239 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.java delete mode 100644 processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java rename processor/src/main/resources/org/mapstruct/ap/internal/model/{common => }/InitDefaultValue.ftl (97%) diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.java b/processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.java new file mode 100644 index 0000000000..7d2f009e3d --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.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.internal.model; + +import java.util.HashSet; +import java.util.Set; + +import org.mapstruct.ap.internal.model.common.ModelElement; +import org.mapstruct.ap.internal.model.common.Type; + +/** + * Model element to generate code that initializes a default value for a given type. + * + *

      Uses the provided factory method if available. + * Otherwise, constructs the target object using a sensible default including but not limited to: + * - an empty array for array types + * - an empty collection for collection types + * - an empty optional for optional types + * - using the public default constructor for other types if available + * + *

      If no default value can be constructed, a null is returned instead. + * TODO: Consider throwing an exception instead of returning null. + * + * @author kenwang + */ +public class InitDefaultValue extends ModelElement { + + private final Type targetType; + private final MethodReference factoryMethod; + + public InitDefaultValue(Type targetType, MethodReference factoryMethod) { + this.targetType = targetType; + this.factoryMethod = factoryMethod; + } + + @Override + public Set getImportTypes() { + Set types = new HashSet<>(); + types.add( targetType ); + return types; + } + + public Type getTargetType() { + return targetType; + } + + public MethodReference getFactoryMethod() { + return factoryMethod; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java index 5ac2e299ab..fc893d4439 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/NormalTypeMappingMethod.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Set; -import org.mapstruct.ap.internal.model.common.InitDefaultValue; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.source.Method; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java deleted file mode 100644 index bda35dae3e..0000000000 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/InitDefaultValue.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.mapstruct.ap.internal.model.common; - -import java.util.HashSet; -import java.util.Set; - -import org.mapstruct.ap.internal.model.MethodReference; - -public class InitDefaultValue extends ModelElement { - - private final Type targetType; - private final MethodReference factoryMethod; - - public InitDefaultValue(Type targetType, MethodReference factoryMethod) { - this.targetType = targetType; - this.factoryMethod = factoryMethod; - } - - @Override - public Set getImportTypes() { - Set types = new HashSet<>(); - types.add( targetType ); - return types; - } - - public Type getTargetType() { - return targetType; - } - - public MethodReference getFactoryMethod() { - return factoryMethod; - } -} 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 47e5fe7f49..4e3c2ef274 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 @@ -236,7 +236,7 @@ public String getName() { /** * Returns a String that could be used in generated code to reference to this {@link Type}.
      - *

      + *

      * The first time a name is referred-to it will be marked as to be imported. For instance * {@code LocalDateTime} can be one of {@code java.time.LocalDateTime} and {@code org.joda.LocalDateTime}) *

      @@ -264,7 +264,7 @@ public String createReferenceName() { return name; } - if ( isTopLevelTypeToBeImported() && nameWithTopLevelTypeName != null) { + if ( isTopLevelTypeToBeImported() && nameWithTopLevelTypeName != null ) { return nameWithTopLevelTypeName; } @@ -373,7 +373,7 @@ public boolean isArrayType() { } public boolean isTypeVar() { - return (typeMirror.getKind() == TypeKind.TYPEVAR); + return ( typeMirror.getKind() == TypeKind.TYPEVAR ); } public boolean isIntersection() { @@ -431,7 +431,7 @@ public boolean hasExtendsBound() { /** * A type variable type can have two types of bounds (mutual exclusive): lower and upper. - * + *

      * Note that its use is only permitted on a definition (not on the place where its used). For instance: * {@code T map( T in)} * @@ -448,7 +448,7 @@ public boolean hasLowerBound() { /** * A type variable type can have two types of bounds (mutual exclusive): lower and upper. - * + *

      * Note that its use is only permitted on a definition (not on the place where its used). For instance: * {@code> T map( T in)} * @@ -636,7 +636,6 @@ private Type replaceGeneric(Type oldGenericType, Type newType) { * as well. * * @param other The other type. - * * @return {@code true} if and only if this type is assignable to the given other type. */ public boolean isAssignableTo(Type other) { @@ -655,7 +654,6 @@ public boolean isAssignableTo(Type other) { * they need to be resolved first. * * @param other The other type. - * * @return {@code true} if and only if this type is assignable to the given other type. */ public boolean isRawAssignableTo(Type other) { @@ -670,6 +668,7 @@ public boolean isRawAssignableTo(Type other) { /** * removes any bounds from this type. + * * @return the raw type */ public Type asRawType() { @@ -690,7 +689,8 @@ public ReadAccessor getReadAccessor(String propertyName, boolean allowedMapToBea .findAny() .orElse( null ); return new MapValueAccessor( getMethod, typeParameters.get( 1 ).getTypeMirror(), propertyName ); - } else if ( propertyName.equals( "?" ) && isOptionalType() ) { + } + else if ( propertyName.equals( "?" ) && isOptionalType() ) { ExecutableElement getMethod = getAllMethods() .stream() .filter( m -> m.getSimpleName().contentEquals( "orElse" ) ) @@ -723,7 +723,7 @@ public Map getPropertyReadAccessors() { if ( readAccessors == null ) { Map recordAccessors = filters.recordAccessorsIn( getRecordComponents() ); - Map modifiableGetters = new LinkedHashMap<>(recordAccessors); + Map modifiableGetters = new LinkedHashMap<>( recordAccessors ); List getterList = filters.getterMethodsIn( getAllMethods() ); for ( ReadAccessor getter : getterList ) { @@ -801,7 +801,7 @@ public Map getPropertyPresenceCheckers() { * @param cmStrategy collection mapping strategy * @return an unmodifiable map of all write accessors indexed by property name */ - public Map getPropertyWriteAccessors( CollectionMappingStrategyGem cmStrategy ) { + public Map getPropertyWriteAccessors(CollectionMappingStrategyGem cmStrategy) { // collect all candidate target accessors List candidates = new ArrayList<>( getSetters() ); candidates.addAll( getAlternativeTargetAccessors() ); @@ -847,7 +847,7 @@ else if ( candidate.getAccessorType() == AccessorType.GETTER ) { continue; } } - else if ( candidate.getAccessorType() == AccessorType.FIELD && ( Executables.isFinal( candidate ) || + else if ( candidate.getAccessorType() == AccessorType.FIELD && ( Executables.isFinal( candidate ) || result.containsKey( targetPropertyName ) ) ) { // if the candidate is a field and a mapping already exists, then use that one, skip it. continue; @@ -884,7 +884,7 @@ private Type determineTargetType(Accessor candidate) { return parameter.getType(); } else if ( candidate.getAccessorType() == AccessorType.GETTER - || candidate.getAccessorType().isFieldAssignment() ) { + || candidate.getAccessorType().isFieldAssignment() ) { return typeFactory.getReturnType( (DeclaredType) typeMirror, candidate ); } return null; @@ -914,7 +914,7 @@ private List nullSafeTypeElementListConversion(Function * Matching occurs on: *

        *
      1. The generic type parameter type of the collection should match the adder method argument
      2. @@ -942,7 +942,6 @@ private String getPropertyName(ExecutableElement element) { * * @param collectionProperty property type (assumed collection) to find the adder method for * @param pluralPropertyName the property name (assumed plural) - * * @return corresponding adder method for getter when present */ private Accessor getAdderForType(Type collectionProperty, String pluralPropertyName) { @@ -981,9 +980,8 @@ else if ( collectionProperty.isStreamType() ) { * Returns all accessor candidates that start with "add" and have exactly one argument * whose type matches the collection or stream property's type argument. * - * @param property the collection or stream property + * @param property the collection or stream property * @param superclass the superclass to use for type argument lookup - * * @return accessor candidates */ private List getAccessorCandidates(Type property, Class superclass) { @@ -1042,7 +1040,7 @@ private List getAdders() { * Alternative accessors could be a getter for a collection. By means of the * {@link java.util.Collection#addAll(java.util.Collection) } this getter can still * be used as targetAccessor. JAXB XJC tool generates such constructs. - * + *

        * This method can be extended when new cases come along. * * @return an unmodifiable list of alternative target accessors. @@ -1128,7 +1126,6 @@ private boolean isSubType(TypeMirror candidate, Class clazz) { * the other type. Returns {@code 1}, if the other type is a direct super type of this type, and so on. * * @param assignableOther the other type - * * @return the length of the shortest path in the type hierarchy between this type and the specified other type */ public int distanceTo(Type assignableOther) { @@ -1157,7 +1154,7 @@ private int distanceTo(TypeMirror base, TypeMirror targetType) { } /** - * @param type the type declaring the method + * @param type the type declaring the method * @param method the method to check * @return Whether this type can access the given method declared on the given type. */ @@ -1178,7 +1175,7 @@ else if ( !method.getModifiers().contains( Modifier.PUBLIC ) ) { /** * @return A valid Java expression most suitable for representing null - useful for dealing with primitives from - * FTL. + * FTL. */ public String getNull() { if ( !isPrimitive() || isArrayType() ) { @@ -1192,7 +1189,7 @@ public String getNull() { } if ( "char".equals( getName() ) ) { //"'\u0000'" would have been better, but depends on platform encoding - return "0"; + return "0"; } if ( "double".equals( getName() ) ) { return "0.0d"; @@ -1238,8 +1235,8 @@ public int hashCode() { // are in another jar than the mapper. So the qualfiedName is a better candidate. final int prime = 31; int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((packageName == null) ? 0 : packageName.hashCode()); + result = prime * result + ( ( name == null ) ? 0 : name.hashCode() ); + result = prime * result + ( ( packageName == null ) ? 0 : packageName.hashCode() ); return result; } @@ -1257,7 +1254,7 @@ public boolean equals(Object obj) { Type other = (Type) obj; if ( this.isWildCardBoundByTypeVar() && other.isWildCardBoundByTypeVar() ) { - return ( this.hasExtendsBound() == this.hasExtendsBound() + return ( this.hasExtendsBound() == this.hasExtendsBound() || this.hasSuperBound() == this.hasSuperBound() ) && typeUtils.isSameType( getTypeBound().getTypeMirror(), other.getTypeBound().getTypeMirror() ); } @@ -1298,7 +1295,6 @@ public String describe() { } /** - * * @return an identification that can be used as part in a forged method name. */ public String getIdentification() { @@ -1318,6 +1314,7 @@ public String getIdentification() { *

      3. {@code }, returns Object
      4. *
      5. {@code , returns Number}
      6. *
      + * * @return the bound for this parameter */ public Type getTypeBound() { @@ -1419,6 +1416,7 @@ public List determineTypeArguments(Class superclass) { /** * All primitive types and their corresponding boxed types are considered native. + * * @return true when native. */ public boolean isNative() { @@ -1448,12 +1446,11 @@ public boolean isLiteral() { * } * * - * @param declared the type + * @param declared the type * @param parameterized the parameterized type - * * @return - the same type when this is not a type var in the broadest sense (T, T[], or ? extends T)
      - * - the matching parameter in the parameterized type when this is a type var when found
      - * - null in all other cases + * - the matching parameter in the parameterized type when this is a type var when found
      + * - null in all other cases */ public ResolvedPair resolveParameterToType(Type declared, Type parameterized) { if ( isTypeVar() || isArrayTypeVar() || isWildCardBoundByTypeVar() ) { @@ -1512,7 +1509,7 @@ public ResolvedPair resolveParameterToType(Type declared, Type parameterized) { * result: Map * } * - * + *

      * Mismatch result examples: *

            * {@code
      @@ -1528,12 +1525,11 @@ public ResolvedPair resolveParameterToType(Type declared, Type parameterized) {
            * }
            * 
      * - * @param declared the type + * @param declared the type * @param parameterized the parameterized type - * * @return - the result of {@link #resolveParameterToType(Type, Type)} when this type itself is a type var.
      - * - the type but then with the matching type parameters replaced.
      - * - the same type when this type does not contain matching type parameters. + * - the type but then with the matching type parameters replaced.
      + * - the same type when this type does not contain matching type parameters. */ public Type resolveGenericTypeParameters(Type declared, Type parameterized) { if ( isTypeVar() || isArrayTypeVar() || isWildCardBoundByTypeVar() ) { @@ -1558,7 +1554,7 @@ public boolean isWildCardBoundByTypeVar() { } public boolean isArrayTypeVar() { - return isArrayType() && getComponentType().isTypeVar(); + return isArrayType() && getComponentType().isTypeVar(); } private static class TypeVarMatcher extends SimpleTypeVisitor8 { @@ -1569,7 +1565,7 @@ private static class TypeVarMatcher extends SimpleTypeVisitor8 results = new ArrayList<>( ); + List results = new ArrayList<>(); if ( parameterized.getTypeArguments().isEmpty() ) { return super.DEFAULT_VALUE; } @@ -1659,7 +1655,7 @@ else if ( types.isSameType( types.erasure( parameterized ), types.erasure( decla continue; } ResolvedPair result = visitDeclared( parameterized, declaredSuperType ); - if ( result != super.DEFAULT_VALUE ) { + if ( result != super.DEFAULT_VALUE ) { results.add( result ); } } @@ -1669,7 +1665,7 @@ else if ( types.isSameType( types.erasure( parameterized ), types.erasure( decla continue; } ResolvedPair result = visitDeclared( (DeclaredType) parameterizedSuper, declared ); - if ( result != super.DEFAULT_VALUE ) { + if ( result != super.DEFAULT_VALUE ) { results.add( result ); } } @@ -1685,7 +1681,7 @@ else if ( types.isSameType( types.erasure( parameterized ), types.erasure( decla private boolean isJavaLangObject(TypeMirror type) { if ( type instanceof DeclaredType ) { return ( (TypeElement) ( (DeclaredType) type ).asElement() ).getQualifiedName() - .contentEquals( Object.class.getName() ); + .contentEquals( Object.class.getName() ); } return false; } @@ -1758,7 +1754,7 @@ else if ( isPrimitive() ) { /** * It strips all the {@code []} from the {@code className}. - * + *

      * E.g. *

            *     trimSimpleClassName("String[][][]") -> "String"
      @@ -1766,7 +1762,6 @@ else if ( isPrimitive() ) {
            * 
      * * @param className that needs to be trimmed - * * @return the trimmed {@code className}, or {@code null} if the {@code className} was {@code null} */ private String trimSimpleClassName(String className) { @@ -1829,9 +1824,9 @@ public boolean isSealed() { /** * return the list of permitted TypeMirrors for the java 17+ sealed class */ - @SuppressWarnings( "unchecked" ) + @SuppressWarnings("unchecked") public List getPermittedSubclasses() { - if (SEALED_PERMITTED_SUBCLASSES_METHOD == null) { + if ( SEALED_PERMITTED_SUBCLASSES_METHOD == null ) { return emptyList(); } try { diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/InitDefaultValue.ftl similarity index 97% rename from processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl rename to processor/src/main/resources/org/mapstruct/ap/internal/model/InitDefaultValue.ftl index 71c82c1b5e..1adc810517 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/common/InitDefaultValue.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/InitDefaultValue.ftl @@ -5,7 +5,7 @@ Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 --> -<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.common.InitDefaultValue" --> +<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.InitDefaultValue" --> <#if factoryMethod??> <@includeModel object=factoryMethod targetType=targetType/> <#else> diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java index 2523a0a59f..f8c9a15af1 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapper.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.beforeafter; import java.util.Optional; @@ -12,8 +17,8 @@ @Mapper public interface OptionalBeforeAfterMapper { - OptionalBeforeAfterMapper INSTANCE = Mappers.getMapper( OptionalBeforeAfterMapper.class); - + OptionalBeforeAfterMapper INSTANCE = Mappers.getMapper( OptionalBeforeAfterMapper.class ); + Target toTarget(Source source); @BeforeMapping @@ -22,7 +27,7 @@ default void beforeDeepOptionalSourceWithNoTargetType(Optional s @BeforeMapping default void beforeDeepOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, - Optional source) { + Optional source) { } @AfterMapping @@ -32,26 +37,26 @@ default void afterDeepOptionalSourceWithNoTarget(Optional source @AfterMapping default void afterDeepOptionalSourceWithNonOptionalTarget(@MappingTarget Target.SubType target, - Optional source) { + Optional source) { } @AfterMapping default void afterDeepOptionalSourceWithOptionalTarget(@MappingTarget Optional target, - Optional source) { + Optional source) { } @AfterMapping default void afterDeepNonOptionalSourceOptionalTarget(@MappingTarget Optional target, - Source.SubType source) { + Source.SubType source) { } - + @BeforeMapping default void beforeShallowOptionalSourceWithNoTargetType(Optional source) { } @BeforeMapping default void beforeShallowOptionalSourceWithNonOptionalTargetType(@TargetType Class targetType, - Optional source) { + Optional source) { } @AfterMapping @@ -61,12 +66,11 @@ default void afterShallowOptionalSourceWithNoTarget(Optional source) { @AfterMapping default void afterShallowOptionalSourceWithNonOptionalTarget(@MappingTarget String target, - Optional source) { + Optional source) { } @AfterMapping - default void afterShallowNonOptionalSourceOptionalTarget(@MappingTarget Optional target, - String source) { + default void afterShallowNonOptionalSourceOptionalTarget(@MappingTarget Optional target, String source) { } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java index d263e4fef9..c6c87c75cf 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.beforeafter; import org.mapstruct.ap.testutil.ProcessorTest; diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java index 5b32f6fda3..4d87be0e04 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/Source.java @@ -55,7 +55,7 @@ public String getShallowNonOptionalToOptional() { } public static class SubType { - + private final String value; public SubType(String value) { @@ -83,5 +83,5 @@ public int hashCode() { return Objects.hash( value ); } } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java index 296191af4d..88f4d2e966 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapper.java @@ -12,7 +12,7 @@ public interface OptionalDifferentTypesMapper { OptionalDifferentTypesMapper INSTANCE = Mappers.getMapper( - OptionalDifferentTypesMapper.class); + OptionalDifferentTypesMapper.class ); Target toTarget(Source source); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java index cc5ef8a162..2328cb0ee8 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java @@ -13,13 +13,12 @@ import static org.assertj.core.api.Assertions.assertThat; @WithClasses({ - OptionalDifferentTypesMapper.class, - Source.class, - Target.class }) + OptionalDifferentTypesMapper.class, Source.class, Target.class +}) public class OptionalDifferentTypesTest { @ProcessorTest - public void constructorOptionalToOptional_present() { + public void constructorOptionalToOptionalWhenPresent() { Source source = new Source( Optional.of( new Source.SubType( "some value" ) ), null, null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -27,7 +26,7 @@ public void constructorOptionalToOptional_present() { } @ProcessorTest - public void constructorOptionalToOptional_empty() { + public void constructorOptionalToOptionalWhenEmpty() { Source source = new Source( Optional.empty(), null, null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -37,7 +36,7 @@ public void constructorOptionalToOptional_empty() { // TODO Contentious // Should null Optional map to null Optional, or explicitly to empty? @ProcessorTest - public void constructorOptionalToOptional_null() { + public void constructorOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -45,7 +44,7 @@ public void constructorOptionalToOptional_null() { } @ProcessorTest - public void constructorOptionalToNonOptional_present() { + public void constructorOptionalToNonOptionalWhenPresent() { Source source = new Source( null, Optional.of( new Source.SubType( "some value" ) ), null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -53,7 +52,7 @@ public void constructorOptionalToNonOptional_present() { } @ProcessorTest - public void constructorOptionalToNonOptional_empty() { + public void constructorOptionalToNonOptionalWhenEmpty() { Source source = new Source( null, Optional.empty(), null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -61,7 +60,7 @@ public void constructorOptionalToNonOptional_empty() { } @ProcessorTest - public void constructorOptionalToNonOptional_null() { + public void constructorOptionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -69,7 +68,7 @@ public void constructorOptionalToNonOptional_null() { } @ProcessorTest - public void constructorNonOptionalToOptional_nonNull() { + public void constructorNonOptionalToOptionalWhenNotNull() { Source source = new Source( null, null, new Source.SubType( "some value" ) ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -77,7 +76,7 @@ public void constructorNonOptionalToOptional_nonNull() { } @ProcessorTest - public void constructorNonOptionalToOptional_null() { + public void constructorNonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); @@ -85,7 +84,7 @@ public void constructorNonOptionalToOptional_null() { } @ProcessorTest - public void optionalToOptional_present() { + public void optionalToOptionalWhenPresent() { Source source = new Source( null, null, null ); source.setOptionalToOptional( Optional.of( new Source.SubType( "some value" ) ) ); @@ -94,7 +93,7 @@ public void optionalToOptional_present() { } @ProcessorTest - public void optionalToOptional_empty() { + public void optionalToOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.setOptionalToOptional( Optional.empty() ); @@ -105,7 +104,7 @@ public void optionalToOptional_empty() { // TODO Contentious // Should null Optional map to null Optional, or explicitly to empty? @ProcessorTest - public void optionalToOptional_null() { + public void optionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.setOptionalToOptional( null ); @@ -114,7 +113,7 @@ public void optionalToOptional_null() { } @ProcessorTest - public void optionalToNonOptional_present() { + public void optionalToNonOptionalWhenPresent() { Source source = new Source( null, null, null ); source.setOptionalToNonOptional( Optional.of( new Source.SubType( "some value" ) ) ); @@ -123,7 +122,7 @@ public void optionalToNonOptional_present() { } @ProcessorTest - public void optionalToNonOptional_empty() { + public void optionalToNonOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.setOptionalToNonOptional( Optional.empty() ); @@ -132,7 +131,7 @@ public void optionalToNonOptional_empty() { } @ProcessorTest - public void optionalToNonOptional_null() { + public void optionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); source.setOptionalToNonOptional( null ); @@ -141,7 +140,7 @@ public void optionalToNonOptional_null() { } @ProcessorTest - public void nonOptionalToOptional_nonNull() { + public void nonOptionalToOptionalWhenNotNull() { Source source = new Source( null, null, null ); source.setNonOptionalToOptional( new Source.SubType( "some value" ) ); @@ -150,7 +149,7 @@ public void nonOptionalToOptional_nonNull() { } @ProcessorTest - public void nonOptionalToOptional_null() { + public void nonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.setNonOptionalToOptional( null ); @@ -159,7 +158,7 @@ public void nonOptionalToOptional_null() { } @ProcessorTest - public void publicOptionalToOptional_present() { + public void publicOptionalToOptionalWhenPresent() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = Optional.of( new Source.SubType( "some value" ) ); @@ -168,7 +167,7 @@ public void publicOptionalToOptional_present() { } @ProcessorTest - public void publicOptionalToOptional_empty() { + public void publicOptionalToOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = Optional.empty(); @@ -179,7 +178,7 @@ public void publicOptionalToOptional_empty() { // TODO Contentious // Should null Optional map to null Optional, or explicitly to empty? @ProcessorTest - public void publicOptionalToOptional_null() { + public void publicOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = null; @@ -188,7 +187,7 @@ public void publicOptionalToOptional_null() { } @ProcessorTest - public void publicOptionalToNonOptional_present() { + public void publicOptionalToNonOptionalWhenPresent() { Source source = new Source( null, null, null ); source.publicOptionalToNonOptional = Optional.of( new Source.SubType( "some value" ) ); @@ -197,7 +196,7 @@ public void publicOptionalToNonOptional_present() { } @ProcessorTest - public void publicOptionalToNonOptional_empty() { + public void publicOptionalToNonOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.publicOptionalToNonOptional = Optional.empty(); @@ -206,7 +205,7 @@ public void publicOptionalToNonOptional_empty() { } @ProcessorTest - public void publicOptionalToNonOptional_null() { + public void publicOptionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); source.publicOptionalToNonOptional = null; @@ -215,21 +214,21 @@ public void publicOptionalToNonOptional_null() { } @ProcessorTest - public void publicNonOptionalToOptional_nonNull() { + public void publicNonOptionalToOptionalWhenNotNull() { Source source = new Source( null, null, null ); - source.publicNonOptionalToOptional = new Source.SubType( "some value" ) ; + source.publicNonOptionalToOptional = new Source.SubType( "some value" ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); assertThat( target.publicNonOptionalToOptional ).contains( new Target.SubType( "some value" ) ); } @ProcessorTest - public void publicNonOptionalToOptional_null() { + public void publicNonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); - source.publicNonOptionalToOptional = null ; + source.publicNonOptionalToOptional = null; Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); assertThat( target.publicNonOptionalToOptional ).isEmpty(); } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java index ba765e0a26..0c9c92811d 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Source.java @@ -19,8 +19,11 @@ public class Source { private Optional optionalToNonOptional; private SubType nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToNonOptional; + @SuppressWarnings( "VisibilityModifier" ) public SubType publicNonOptionalToOptional; public Source(Optional constructorOptionalToOptional, Optional constructorOptionalToNonOptional, @@ -67,7 +70,7 @@ public void setNonOptionalToOptional(SubType nonOptionalToOptional) { } public static class SubType { - + private final String value; public SubType(String value) { @@ -95,5 +98,5 @@ public int hashCode() { return Objects.hash( value ); } } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java index 9f06a6d289..7784e8ee52 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/Target.java @@ -19,8 +19,11 @@ public class Target { private SubType optionalToNonOptional; private Optional nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public SubType publicOptionalToNonOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicNonOptionalToOptional; public Target(Optional constructorOptionalToOptional, SubType constructorOptionalToNonOptional, diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java index 78eb204a35..59ae1b1ee2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapper.java @@ -1,19 +1,23 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ package org.mapstruct.ap.test.optionalmapping.nested; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.NullValuePropertyMappingStrategy; import org.mapstruct.factory.Mappers; @Mapper public interface OptionalNestedMapper { - OptionalNestedMapper INSTANCE = Mappers.getMapper(OptionalNestedMapper.class); + OptionalNestedMapper INSTANCE = Mappers.getMapper( OptionalNestedMapper.class ); - @Mapping( source = "optionalToNonOptional?.value?", target = "optionalToNonOptional") - @Mapping( source = "optionalToOptional?.value", target = "optionalToOptional") - @Mapping( source = "nonOptionalToNonOptional?.value", target = "nonOptionalToNonOptional") - @Mapping( source = "nonOptionalToOptional?.value", target = "nonOptionalToOptional") + @Mapping(source = "optionalToNonOptional?.value?", target = "optionalToNonOptional") + @Mapping(source = "optionalToOptional?.value", target = "optionalToOptional") + @Mapping(source = "nonOptionalToNonOptional?.value", target = "nonOptionalToNonOptional") + @Mapping(source = "nonOptionalToOptional?.value", target = "nonOptionalToOptional") Target toTarget(Source source); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java index 0ee5b6b8c0..5271fdfe51 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.nested; import java.util.Optional; @@ -8,22 +13,21 @@ import static org.assertj.core.api.Assertions.assertThat; @WithClasses({ - OptionalNestedMapper.class, - Source.class, - Target.class }) + OptionalNestedMapper.class, Source.class, Target.class +}) public class OptionalNestedTest { @ProcessorTest - public void optionalToNonOptional_empty() { + public void optionalToNonOptionalWhenEmpty() { Source source = new Source(); source.setOptionalToNonOptional( Optional.empty() ); - + Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); assertThat( target.getOptionalToNonOptional() ).isNull(); } @ProcessorTest - public void optionalToNonOptional_null() { + public void optionalToNonOptionalWhenNull() { Source source = new Source(); source.setOptionalToNonOptional( null ); @@ -32,7 +36,7 @@ public void optionalToNonOptional_null() { } @ProcessorTest - public void nestedOptionalToNonOptional_empty() { + public void nestedOptionalToNonOptionalWhenEmpty() { Source source = new Source(); source.setOptionalToNonOptional( Optional.of( new Source.NestedOptional( Optional.empty() ) ) ); @@ -41,7 +45,7 @@ public void nestedOptionalToNonOptional_empty() { } @ProcessorTest - public void nestedOptionalToNonOptional_null() { + public void nestedOptionalToNonOptionalWhenNull() { Source source = new Source(); source.setOptionalToNonOptional( Optional.of( new Source.NestedOptional( null ) ) ); @@ -50,16 +54,16 @@ public void nestedOptionalToNonOptional_null() { } @ProcessorTest - public void nestedOptionalToNonOptional_nonNull() { + public void nestedOptionalToNonOptionalWhenNotNull() { Source source = new Source(); source.setOptionalToNonOptional( Optional.of( new Source.NestedOptional( Optional.of( "some value" ) ) ) ); Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToNonOptional() ).isEqualTo("some value"); + assertThat( target.getOptionalToNonOptional() ).isEqualTo( "some value" ); } @ProcessorTest - public void optionalToOptional_empty() { + public void optionalToOptionalWhenEmpty() { Source source = new Source(); source.setOptionalToOptional( Optional.empty() ); @@ -68,7 +72,7 @@ public void optionalToOptional_empty() { } @ProcessorTest - public void optionalToOptional_null() { + public void optionalToOptionalWhenNull() { Source source = new Source(); source.setOptionalToOptional( null ); @@ -77,7 +81,7 @@ public void optionalToOptional_null() { } @ProcessorTest - public void nestedOptionalToOptional_empty() { + public void nestedOptionalToOptionalWhenEmpty() { Source source = new Source(); source.setOptionalToOptional( Optional.of( new Source.NestedOptional( Optional.empty() ) ) ); @@ -86,7 +90,7 @@ public void nestedOptionalToOptional_empty() { } @ProcessorTest - public void nestedOptionalToOptional_null() { + public void nestedOptionalToOptionalWhenNull() { Source source = new Source(); source.setOptionalToOptional( Optional.of( new Source.NestedOptional( null ) ) ); @@ -95,16 +99,16 @@ public void nestedOptionalToOptional_null() { } @ProcessorTest - public void nestedOptionalToOptional_nonNull() { + public void nestedOptionalToOptionalWhenNotNull() { Source source = new Source(); source.setOptionalToOptional( Optional.of( new Source.NestedOptional( Optional.of( "some value" ) ) ) ); Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToOptional() ).contains("some value"); + assertThat( target.getOptionalToOptional() ).contains( "some value" ); } @ProcessorTest - public void nonOptionalToNonOptional_empty() { + public void nonOptionalToNonOptionalWhenEmpty() { Source source = new Source(); source.setNonOptionalToNonOptional( Optional.empty() ); @@ -113,7 +117,7 @@ public void nonOptionalToNonOptional_empty() { } @ProcessorTest - public void nonOptionalToNonOptional_null() { + public void nonOptionalToNonOptionalWhenNull() { Source source = new Source(); source.setNonOptionalToNonOptional( null ); @@ -122,7 +126,7 @@ public void nonOptionalToNonOptional_null() { } @ProcessorTest - public void nestedNonOptionalToNonOptional_null() { + public void nestedNonOptionalToNonOptionalWhenNull() { Source source = new Source(); source.setNonOptionalToNonOptional( Optional.of( new Source.NestedNonOptional( null ) ) ); @@ -131,16 +135,16 @@ public void nestedNonOptionalToNonOptional_null() { } @ProcessorTest - public void nestedNonOptionalToNonOptional_nonNull() { + public void nestedNonOptionalToNonOptionalWhenNotNull() { Source source = new Source(); source.setNonOptionalToNonOptional( Optional.of( new Source.NestedNonOptional( "some value" ) ) ); Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); - assertThat( target.getNonOptionalToNonOptional() ).isEqualTo("some value"); + assertThat( target.getNonOptionalToNonOptional() ).isEqualTo( "some value" ); } @ProcessorTest - public void nonOptionalToOptional_empty() { + public void nonOptionalToOptionalWhenEmpty() { Source source = new Source(); source.setNonOptionalToOptional( Optional.empty() ); @@ -149,7 +153,7 @@ public void nonOptionalToOptional_empty() { } @ProcessorTest - public void nonOptionalToOptional_null() { + public void nonOptionalToOptionalWhenNull() { Source source = new Source(); source.setNonOptionalToOptional( null ); @@ -158,7 +162,7 @@ public void nonOptionalToOptional_null() { } @ProcessorTest - public void nestedNonOptionalToOptional_null() { + public void nestedNonOptionalToOptionalWhenNull() { Source source = new Source(); source.setNonOptionalToOptional( Optional.of( new Source.NestedNonOptional( null ) ) ); @@ -167,12 +171,12 @@ public void nestedNonOptionalToOptional_null() { } @ProcessorTest - public void nestedNonOptionalToOptional_nonNull() { + public void nestedNonOptionalToOptionalWhenNotNull() { Source source = new Source(); source.setNonOptionalToOptional( Optional.of( new Source.NestedNonOptional( "some value" ) ) ); Target target = OptionalNestedMapper.INSTANCE.toTarget( source ); - assertThat( target.getNonOptionalToOptional() ).contains("some value"); + assertThat( target.getNonOptionalToOptional() ).contains( "some value" ); } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java index a9c2787305..efafb1fb6b 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/Source.java @@ -19,8 +19,7 @@ public Optional getOptionalToNonOptional() { return optionalToNonOptional; } - public void setOptionalToNonOptional( - Optional optionalToNonOptional) { + public void setOptionalToNonOptional(Optional optionalToNonOptional) { this.optionalToNonOptional = optionalToNonOptional; } @@ -28,8 +27,7 @@ public Optional getOptionalToOptional() { return optionalToOptional; } - public void setOptionalToOptional( - Optional optionalToOptional) { + public void setOptionalToOptional(Optional optionalToOptional) { this.optionalToOptional = optionalToOptional; } @@ -37,8 +35,7 @@ public Optional getNonOptionalToNonOptional() { return nonOptionalToNonOptional; } - public void setNonOptionalToNonOptional( - Optional nonOptionalToNonOptional) { + public void setNonOptionalToNonOptional(Optional nonOptionalToNonOptional) { this.nonOptionalToNonOptional = nonOptionalToNonOptional; } @@ -46,8 +43,7 @@ public Optional getNonOptionalToOptional() { return nonOptionalToOptional; } - public void setNonOptionalToOptional( - Optional nonOptionalToOptional) { + public void setNonOptionalToOptional(Optional nonOptionalToOptional) { this.nonOptionalToOptional = nonOptionalToOptional; } @@ -76,5 +72,5 @@ public String getValue() { return value; } } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java index 8c3ac047fd..9f170da90d 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapper.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.nullcheckalways; import org.mapstruct.Mapper; @@ -7,7 +12,7 @@ @Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) public interface OptionalNullCheckAlwaysMapper { - OptionalNullCheckAlwaysMapper INSTANCE = Mappers.getMapper( OptionalNullCheckAlwaysMapper.class); + OptionalNullCheckAlwaysMapper INSTANCE = Mappers.getMapper( OptionalNullCheckAlwaysMapper.class ); Target toTarget(Source source); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java index b0360bfe60..c727e67bf9 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.nullcheckalways; import org.mapstruct.ap.testutil.ProcessorTest; @@ -6,13 +11,12 @@ import static org.assertj.core.api.Assertions.assertThat; @WithClasses({ - OptionalNullCheckAlwaysMapper.class, - Source.class, - Target.class }) + OptionalNullCheckAlwaysMapper.class, Source.class, Target.class +}) public class OptionalNullCheckAlwaysTest { @ProcessorTest - public void optionalToOptional_null() { + public void optionalToOptionalWhenNull() { Source source = new Source(); source.setOptionalToOptional( null ); @@ -21,7 +25,7 @@ public void optionalToOptional_null() { } @ProcessorTest - public void optionalToNonOptional_null() { + public void optionalToNonOptionalWhenNull() { Source source = new Source(); source.setOptionalToNonOptional( null ); @@ -30,12 +34,12 @@ public void optionalToNonOptional_null() { } @ProcessorTest - public void nonOptionalToOptional_null() { + public void nonOptionalToOptionalWhenNull() { Source source = new Source(); source.setNonOptionalToOptional( null ); Target target = OptionalNullCheckAlwaysMapper.INSTANCE.toTarget( source ); assertThat( target.isNonOptionalToOptionalCalled() ).isFalse(); } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.java index 7ab41d3037..1784550c52 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapper.java @@ -7,7 +7,6 @@ import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; -import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.NullValuePropertyMappingStrategy; import org.mapstruct.factory.Mappers; @@ -15,7 +14,7 @@ public interface NullValuePropertyToDefaultMapper { NullValuePropertyToDefaultMapper INSTANCE = Mappers.getMapper( - NullValuePropertyToDefaultMapper.class); + NullValuePropertyToDefaultMapper.class ); void mapTarget(Source source, @MappingTarget Target target); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java index d6b7f69eed..d5d4d60126 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java @@ -13,11 +13,12 @@ @WithClasses({ NullValuePropertyToDefaultMapper.class, Source.class, - Target.class }) + Target.class +}) public class NullValuePropertyToDefaultTest { @ProcessorTest - public void optionalToOptional_null() { + public void optionalToOptionalWhenNull() { Source source = new Source(); source.setOptionalToOptional( null ); @@ -27,7 +28,7 @@ public void optionalToOptional_null() { } @ProcessorTest - public void nonOptionalToOptional_null() { + public void nonOptionalToOptionalWhenNull() { Source source = new Source(); source.setNonOptionalToOptional( null ); @@ -37,7 +38,7 @@ public void nonOptionalToOptional_null() { } @ProcessorTest - public void publicOptionalToOptional_null() { + public void publicOptionalToOptionalWhenNull() { Source source = new Source(); source.publicOptionalToOptional = null; @@ -47,7 +48,7 @@ public void publicOptionalToOptional_null() { } @ProcessorTest - public void publicNonOptionalToOptional_null() { + public void publicNonOptionalToOptionalWhenNull() { Source source = new Source(); source.publicNonOptionalToOptional = null; @@ -55,5 +56,5 @@ public void publicNonOptionalToOptional_null() { NullValuePropertyToDefaultMapper.INSTANCE.mapTarget( source, target ); assertThat( target.publicNonOptionalToOptional ).isEmpty(); } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java index 2ab8b8cefa..01a6efb1de 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Source.java @@ -14,7 +14,9 @@ public class Source { private Optional optionalToOptional; private SubType nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public SubType publicNonOptionalToOptional; public Optional getOptionalToOptional() { @@ -34,7 +36,7 @@ public void setNonOptionalToOptional(SubType nonOptionalToOptional) { } public static class SubType { - + private final String value; public SubType(String value) { @@ -62,5 +64,5 @@ public int hashCode() { return Objects.hash( value ); } } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java index 071256f5d2..e374e6940d 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/Target.java @@ -14,7 +14,9 @@ public class Target { private Optional optionalToOptional; private Optional nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicNonOptionalToOptional; public Optional getOptionalToOptional() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapper.java index fd9b790293..8cfd09dd6f 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapper.java @@ -13,7 +13,7 @@ public interface NullValueToDefaultMapper { NullValueToDefaultMapper INSTANCE = Mappers.getMapper( - NullValueToDefaultMapper.class); + NullValueToDefaultMapper.class ); Target toTarget(Source source); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java index a98ccbc3ef..289101e5dd 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java @@ -5,8 +5,6 @@ */ package org.mapstruct.ap.test.optionalmapping.nullvaluetodefault; -import java.util.Optional; - import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; @@ -15,11 +13,12 @@ @WithClasses({ NullValueToDefaultMapper.class, Source.class, - Target.class }) + Target.class +}) public class NullValueToDefaultTest { @ProcessorTest - public void constructorOptionalToOptional_null() { + public void constructorOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); @@ -27,7 +26,7 @@ public void constructorOptionalToOptional_null() { } @ProcessorTest - public void constructorOptionalToNonOptional_null() { + public void constructorOptionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); @@ -35,7 +34,7 @@ public void constructorOptionalToNonOptional_null() { } @ProcessorTest - public void constructorNonOptionalToOptional_null() { + public void constructorNonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); @@ -43,7 +42,7 @@ public void constructorNonOptionalToOptional_null() { } @ProcessorTest - public void optionalToOptional_null() { + public void optionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.setOptionalToOptional( null ); @@ -52,7 +51,7 @@ public void optionalToOptional_null() { } @ProcessorTest - public void optionalToNonOptional_null() { + public void optionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); source.setOptionalToNonOptional( null ); @@ -61,7 +60,7 @@ public void optionalToNonOptional_null() { } @ProcessorTest - public void nonOptionalToOptional_null() { + public void nonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.setNonOptionalToOptional( null ); @@ -70,7 +69,7 @@ public void nonOptionalToOptional_null() { } @ProcessorTest - public void publicOptionalToOptional_null() { + public void publicOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = null; @@ -79,7 +78,7 @@ public void publicOptionalToOptional_null() { } @ProcessorTest - public void publicOptionalToNonOptional_null() { + public void publicOptionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); source.publicOptionalToNonOptional = null; @@ -88,12 +87,12 @@ public void publicOptionalToNonOptional_null() { } @ProcessorTest - public void publicNonOptionalToOptional_null() { + public void publicNonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); - source.publicNonOptionalToOptional = null ; + source.publicNonOptionalToOptional = null; Target target = NullValueToDefaultMapper.INSTANCE.toTarget( source ); assertThat( target.publicNonOptionalToOptional ).isEmpty(); } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Source.java index 90ea86debd..48881cbdf2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Source.java @@ -19,8 +19,11 @@ public class Source { private Optional optionalToNonOptional; private SubType nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToNonOptional; + @SuppressWarnings( "VisibilityModifier" ) public SubType publicNonOptionalToOptional; public Source(Optional constructorOptionalToOptional, Optional constructorOptionalToNonOptional, @@ -67,7 +70,7 @@ public void setNonOptionalToOptional(SubType nonOptionalToOptional) { } public static class SubType { - + private final String value; public SubType(String value) { @@ -95,5 +98,5 @@ public int hashCode() { return Objects.hash( value ); } } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Target.java index 4e91a05453..bc7fd34540 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/Target.java @@ -19,8 +19,11 @@ public class Target { private SubType optionalToNonOptional; private Optional nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public SubType publicOptionalToNonOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicNonOptionalToOptional; public Target(Optional constructorOptionalToOptional, SubType constructorOptionalToNonOptional, diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java index c84cb588f1..6a34d231bd 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapper.java @@ -13,7 +13,7 @@ public interface OptionalSameTypeMapper { OptionalSameTypeMapper INSTANCE = Mappers.getMapper( - OptionalSameTypeMapper.class); + OptionalSameTypeMapper.class ); Target toTarget(Source source); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java index 6010be755d..d7678e00d9 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java @@ -13,13 +13,12 @@ import static org.assertj.core.api.Assertions.assertThat; @WithClasses({ - OptionalSameTypeMapper.class, - Source.class, - Target.class }) + OptionalSameTypeMapper.class, Source.class, Target.class +}) public class OptionalSameTypeTest { @ProcessorTest - public void constructorOptionalToOptional_present() { + public void constructorOptionalToOptionalWhenPresent() { Source source = new Source( Optional.of( "some value" ), null, null ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -27,7 +26,7 @@ public void constructorOptionalToOptional_present() { } @ProcessorTest - public void constructorOptionalToOptional_empty() { + public void constructorOptionalToOptionalWhenEmpty() { Source source = new Source( Optional.empty(), null, null ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -41,7 +40,7 @@ public void constructorOptionalToOptional_empty() { // Optional -> Optional, therefore no nested mapping is required. // By default, the mapper just generates `target.prop = source.prop`. @ProcessorTest - public void constructorOptionalToOptional_null() { + public void constructorOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -49,7 +48,7 @@ public void constructorOptionalToOptional_null() { } @ProcessorTest - public void constructorOptionalToNonOptional_present() { + public void constructorOptionalToNonOptionalWhenPresent() { Source source = new Source( null, Optional.of( "some value" ), null ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -57,7 +56,7 @@ public void constructorOptionalToNonOptional_present() { } @ProcessorTest - public void constructorOptionalToNonOptional_empty() { + public void constructorOptionalToNonOptionalWhenEmpty() { Source source = new Source( null, Optional.empty(), null ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -65,7 +64,7 @@ public void constructorOptionalToNonOptional_empty() { } @ProcessorTest - public void constructorOptionalToNonOptional_null() { + public void constructorOptionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -73,7 +72,7 @@ public void constructorOptionalToNonOptional_null() { } @ProcessorTest - public void constructorNonOptionalToOptional_nonNull() { + public void constructorNonOptionalToOptionalWhenNotNull() { Source source = new Source( null, null, "some value" ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -81,7 +80,7 @@ public void constructorNonOptionalToOptional_nonNull() { } @ProcessorTest - public void constructorNonOptionalToOptional_null() { + public void constructorNonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); @@ -89,7 +88,7 @@ public void constructorNonOptionalToOptional_null() { } @ProcessorTest - public void optionalToOptional_present() { + public void optionalToOptionalWhenPresent() { Source source = new Source( null, null, null ); source.setOptionalToOptional( Optional.of( "some value" ) ); @@ -98,7 +97,7 @@ public void optionalToOptional_present() { } @ProcessorTest - public void optionalToOptional_empty() { + public void optionalToOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.setOptionalToOptional( Optional.empty() ); @@ -113,7 +112,7 @@ public void optionalToOptional_empty() { // Optional -> Optional, therefore no nested mapping is required. // By default, the mapper just generates `target.prop = source.prop`. @ProcessorTest - public void optionalToOptional_null() { + public void optionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.setOptionalToOptional( null ); @@ -122,7 +121,7 @@ public void optionalToOptional_null() { } @ProcessorTest - public void optionalToNonOptional_present() { + public void optionalToNonOptionalWhenPresent() { Source source = new Source( null, null, null ); source.setOptionalToNonOptional( Optional.of( "some value" ) ); @@ -131,7 +130,7 @@ public void optionalToNonOptional_present() { } @ProcessorTest - public void optionalToNonOptional_empty() { + public void optionalToNonOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.setOptionalToNonOptional( Optional.empty() ); @@ -140,7 +139,7 @@ public void optionalToNonOptional_empty() { } @ProcessorTest - public void optionalToNonOptional_null() { + public void optionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); source.setOptionalToNonOptional( null ); @@ -149,7 +148,7 @@ public void optionalToNonOptional_null() { } @ProcessorTest - public void nonOptionalToOptional_nonNull() { + public void nonOptionalToOptionalWhenNotNull() { Source source = new Source( null, null, null ); source.setNonOptionalToOptional( "some value" ); @@ -158,7 +157,7 @@ public void nonOptionalToOptional_nonNull() { } @ProcessorTest - public void nonOptionalToOptional_null() { + public void nonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.setNonOptionalToOptional( null ); @@ -167,7 +166,7 @@ public void nonOptionalToOptional_null() { } @ProcessorTest - public void publicOptionalToOptional_present() { + public void publicOptionalToOptionalWhenPresent() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = Optional.of( "some value" ); @@ -176,7 +175,7 @@ public void publicOptionalToOptional_present() { } @ProcessorTest - public void publicOptionalToOptional_empty() { + public void publicOptionalToOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = Optional.empty(); @@ -191,7 +190,7 @@ public void publicOptionalToOptional_empty() { // Optional -> Optional, therefore no nested mapping is required. // By default, the mapper just generates `target.prop = source.prop`. @ProcessorTest - public void publicOptionalToOptional_null() { + public void publicOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = null; @@ -200,7 +199,7 @@ public void publicOptionalToOptional_null() { } @ProcessorTest - public void publicOptionalToNonOptional_present() { + public void publicOptionalToNonOptionalWhenPresent() { Source source = new Source( null, null, null ); source.publicOptionalToNonOptional = Optional.of( "some value" ); @@ -209,7 +208,7 @@ public void publicOptionalToNonOptional_present() { } @ProcessorTest - public void publicOptionalToNonOptional_empty() { + public void publicOptionalToNonOptionalWhenEmpty() { Source source = new Source( null, null, null ); source.publicOptionalToNonOptional = Optional.empty(); @@ -218,7 +217,7 @@ public void publicOptionalToNonOptional_empty() { } @ProcessorTest - public void publicOptionalToNonOptional_null() { + public void publicOptionalToNonOptionalWhenNull() { Source source = new Source( null, null, null ); source.publicOptionalToNonOptional = null; @@ -227,21 +226,21 @@ public void publicOptionalToNonOptional_null() { } @ProcessorTest - public void publicNonOptionalToOptional_nonNull() { + public void publicNonOptionalToOptionalWhenNotNull() { Source source = new Source( null, null, null ); - source.publicNonOptionalToOptional = "some value" ; + source.publicNonOptionalToOptional = "some value"; Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); assertThat( target.publicNonOptionalToOptional ).contains( "some value" ); } @ProcessorTest - public void publicNonOptionalToOptional_null() { + public void publicNonOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); - source.publicNonOptionalToOptional = null ; + source.publicNonOptionalToOptional = null; Target target = OptionalSameTypeMapper.INSTANCE.toTarget( source ); assertThat( target.publicNonOptionalToOptional ).isEmpty(); } - + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java index 04962af7e0..6d136056d3 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Source.java @@ -18,8 +18,11 @@ public class Source { private Optional optionalToNonOptional; private String nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToNonOptional; + @SuppressWarnings( "VisibilityModifier" ) public String publicNonOptionalToOptional; public Source(Optional constructorOptionalToOptional, Optional constructorOptionalToNonOptional, diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java index 1f3763d7a2..d1210aff05 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/Target.java @@ -18,8 +18,11 @@ public class Target { private String optionalToNonOptional; private Optional nonOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicOptionalToOptional; + @SuppressWarnings( "VisibilityModifier" ) public String publicOptionalToNonOptional; + @SuppressWarnings( "VisibilityModifier" ) public Optional publicNonOptionalToOptional; public Target(Optional constructorOptionalToOptional, String constructorOptionalToNonOptional, From c7e7ed9f00f564356189deb33f93dfff6199beab Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Mon, 20 Nov 2023 22:14:44 -0500 Subject: [PATCH 14/17] generated sources --- .../beforeafter/OptionalBeforeAfterTest.java | 10 +- .../OptionalDifferentTypesTest.java | 5 + .../nested/OptionalNestedTest.java | 5 + .../OptionalNullCheckAlwaysTest.java | 5 + .../NullValuePropertyToDefaultTest.java | 5 + .../NullValueToDefaultTest.java | 5 + .../sametype/OptionalSameTypeTest.java | 5 + ...alueCheckAlwaysOptionalTestMapperImpl.java | 348 ------------------ .../SimpleOptionalTestMapperImpl.java | 221 ----------- .../OptionalBeforeAfterMapperImpl.java | 124 +++++++ .../OptionalDifferentTypesMapperImpl.java | 83 +++++ .../nested/OptionalNestedMapperImpl.java | 91 +++++ .../OptionalNullCheckAlwaysMapperImpl.java | 54 +++ .../NullValuePropertyToDefaultMapperImpl.java | 79 ++++ .../NullValueToDefaultMapperImpl.java | 81 ++++ .../sametype/OptionalSameTypeMapperImpl.java | 59 +++ 16 files changed, 608 insertions(+), 572 deletions(-) delete mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java delete mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java create mode 100644 processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java index c6c87c75cf..ce3350a0f5 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java @@ -5,15 +5,19 @@ */ package org.mapstruct.ap.test.optionalmapping.beforeafter; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; @WithClasses({ - OptionalBeforeAfterMapper.class, - Source.class, - Target.class }) + OptionalBeforeAfterMapper.class, Source.class, Target.class +}) public class OptionalBeforeAfterTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalBeforeAfterMapper.class ); + @ProcessorTest public void dummyTest() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java index 2328cb0ee8..2473fc8fe2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java @@ -7,8 +7,10 @@ import java.util.Optional; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; import static org.assertj.core.api.Assertions.assertThat; @@ -17,6 +19,9 @@ }) public class OptionalDifferentTypesTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalDifferentTypesMapper.class ); + @ProcessorTest public void constructorOptionalToOptionalWhenPresent() { Source source = new Source( Optional.of( new Source.SubType( "some value" ) ), null, null ); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java index 5271fdfe51..4f1a351dfd 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java @@ -7,8 +7,10 @@ import java.util.Optional; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; import static org.assertj.core.api.Assertions.assertThat; @@ -17,6 +19,9 @@ }) public class OptionalNestedTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalNestedMapper.class ); + @ProcessorTest public void optionalToNonOptionalWhenEmpty() { Source source = new Source(); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java index c727e67bf9..35bcd502cd 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java @@ -5,8 +5,10 @@ */ package org.mapstruct.ap.test.optionalmapping.nullcheckalways; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; import static org.assertj.core.api.Assertions.assertThat; @@ -15,6 +17,9 @@ }) public class OptionalNullCheckAlwaysTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalNullCheckAlwaysMapper.class ); + @ProcessorTest public void optionalToOptionalWhenNull() { Source source = new Source(); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java index d5d4d60126..57a656ef9f 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java @@ -5,8 +5,10 @@ */ package org.mapstruct.ap.test.optionalmapping.nullvaluepropertytodefault; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; import static org.assertj.core.api.Assertions.assertThat; @@ -17,6 +19,9 @@ }) public class NullValuePropertyToDefaultTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( NullValuePropertyToDefaultMapper.class ); + @ProcessorTest public void optionalToOptionalWhenNull() { Source source = new Source(); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java index 289101e5dd..479bb74002 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java @@ -5,8 +5,10 @@ */ package org.mapstruct.ap.test.optionalmapping.nullvaluetodefault; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; import static org.assertj.core.api.Assertions.assertThat; @@ -17,6 +19,9 @@ }) public class NullValueToDefaultTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( NullValueToDefaultMapper.class ); + @ProcessorTest public void constructorOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java index d7678e00d9..bb7a8ec02f 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java @@ -7,8 +7,10 @@ import java.util.Optional; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mapstruct.ap.testutil.ProcessorTest; import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.GeneratedSource; import static org.assertj.core.api.Assertions.assertThat; @@ -17,6 +19,9 @@ }) public class OptionalSameTypeTest { + @RegisterExtension + final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalSameTypeMapper.class ); + @ProcessorTest public void constructorOptionalToOptionalWhenPresent() { Source source = new Source( Optional.of( "some value" ), null, null ); diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java deleted file mode 100644 index ff1d916a3f..0000000000 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/NullValueCheckAlwaysOptionalTestMapperImpl.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Optional; -import javax.annotation.processing.Generated; - -@Generated( - value = "org.mapstruct.ap.MappingProcessor", - date = "2023-06-30T00:29:43-0400", - comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" -) -public class NullValueCheckAlwaysOptionalTestMapperImpl implements NullValueCheckAlwaysOptionalTestMapper { - - @Override - public Target toTarget(Source source) { - if ( source == null ) { - return null; - } - - String constructorOptionalToNonOptional = null; - Optional constructorNonOptionalToOptional = null; - Optional constructorOptionalToOptional = null; - Target.SubType constructorOptionalSubTypeToNonOptional = null; - Optional constructorNonOptionalSubTypeToOptional = null; - Optional constructorOptionalSubTypeToOptional = null; - - if ( source.getConstructorOptionalToNonOptional() != null && source.getConstructorOptionalToNonOptional().isPresent() ) { - constructorOptionalToNonOptional = stringOptionalToString( source.getConstructorOptionalToNonOptional() ); - } - if ( source.getConstructorNonOptionalToOptional() != null ) { - constructorNonOptionalToOptional = stringToStringOptional( source.getConstructorNonOptionalToOptional() ); - } - else { - constructorNonOptionalToOptional = Optional.empty(); - } - if ( source.getConstructorOptionalToOptional() != null && source.getConstructorOptionalToOptional().isPresent() ) { - constructorOptionalToOptional = source.getConstructorOptionalToOptional(); - } - else { - constructorOptionalToOptional = Optional.empty(); - } - if ( source.getConstructorOptionalSubTypeToNonOptional() != null && source.getConstructorOptionalSubTypeToNonOptional().isPresent() ) { - constructorOptionalSubTypeToNonOptional = subTypeOptionalToSubType( source.getConstructorOptionalSubTypeToNonOptional() ); - } - if ( source.getConstructorNonOptionalSubTypeToOptional() != null ) { - constructorNonOptionalSubTypeToOptional = subTypeToSubTypeOptional( source.getConstructorNonOptionalSubTypeToOptional() ); - } - else { - constructorNonOptionalSubTypeToOptional = Optional.empty(); - } - if ( source.getConstructorOptionalSubTypeToOptional() != null && source.getConstructorOptionalSubTypeToOptional().isPresent() ) { - constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.getConstructorOptionalSubTypeToOptional() ); - } - else { - constructorOptionalSubTypeToOptional = Optional.empty(); - } - - Target target = new Target( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); - - if ( source.getOptionalToNonOptional() != null && source.getOptionalToNonOptional().isPresent() ) { - target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); - } - if ( source.getNonOptionalToOptional() != null ) { - target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); - } - else { - target.setNonOptionalToOptional( Optional.empty() ); - } - if ( source.getOptionalToOptional() != null && source.getOptionalToOptional().isPresent() ) { - target.setOptionalToOptional( source.getOptionalToOptional() ); - } - else { - target.setOptionalToOptional( Optional.empty() ); - } - if ( source.getOptionalSubTypeToNonOptional() != null && source.getOptionalSubTypeToNonOptional().isPresent() ) { - target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); - } - if ( source.getNonOptionalSubTypeToOptional() != null ) { - target.setNonOptionalSubTypeToOptional( subTypeToSubTypeOptional( source.getNonOptionalSubTypeToOptional() ) ); - } - else { - target.setNonOptionalSubTypeToOptional( Optional.empty() ); - } - if ( source.getOptionalSubTypeToOptional() != null && source.getOptionalSubTypeToOptional().isPresent() ) { - target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); - } - else { - target.setOptionalSubTypeToOptional( Optional.empty() ); - } - if ( source.getMonitoredOptionalToString() != null && source.getMonitoredOptionalToString().isPresent() ) { - target.setMonitoredOptionalToString( stringOptionalToString( source.getMonitoredOptionalToString() ) ); - } - if ( source.getMonitoredOptionalSubTypeToSubType() != null && source.getMonitoredOptionalSubTypeToSubType().isPresent() ) { - target.setMonitoredOptionalSubTypeToSubType( subTypeOptionalToSubType( source.getMonitoredOptionalSubTypeToSubType() ) ); - } - if ( source.publicOptionalSubTypeToOptional != null && source.publicOptionalSubTypeToOptional.isPresent() ) { - target.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.publicOptionalSubTypeToOptional ); - } - else { - target.publicOptionalSubTypeToOptional = Optional.empty(); - } - if ( source.publicOptionalToNonOptionalWithDefault != null && source.publicOptionalToNonOptionalWithDefault.isPresent() ) { - target.publicOptionalToNonOptionalWithDefault = stringOptionalToString( source.publicOptionalToNonOptionalWithDefault ); - } - - return target; - } - - @Override - public Source fromTarget(Target target) { - if ( target == null ) { - return null; - } - - Optional constructorOptionalToNonOptional = null; - String constructorNonOptionalToOptional = null; - Optional constructorOptionalToOptional = null; - Optional constructorOptionalSubTypeToNonOptional = null; - Source.SubType constructorNonOptionalSubTypeToOptional = null; - Optional constructorOptionalSubTypeToOptional = null; - - if ( target.getConstructorOptionalToNonOptional() != null ) { - constructorOptionalToNonOptional = stringToStringOptional( target.getConstructorOptionalToNonOptional() ); - } - else { - constructorOptionalToNonOptional = Optional.empty(); - } - if ( target.getConstructorNonOptionalToOptional() != null && target.getConstructorNonOptionalToOptional().isPresent() ) { - constructorNonOptionalToOptional = stringOptionalToString( target.getConstructorNonOptionalToOptional() ); - } - if ( target.getConstructorOptionalToOptional() != null && target.getConstructorOptionalToOptional().isPresent() ) { - constructorOptionalToOptional = target.getConstructorOptionalToOptional(); - } - else { - constructorOptionalToOptional = Optional.empty(); - } - if ( target.getConstructorOptionalSubTypeToNonOptional() != null ) { - constructorOptionalSubTypeToNonOptional = subTypeToSubTypeOptional1( target.getConstructorOptionalSubTypeToNonOptional() ); - } - else { - constructorOptionalSubTypeToNonOptional = Optional.empty(); - } - if ( target.getConstructorNonOptionalSubTypeToOptional() != null && target.getConstructorNonOptionalSubTypeToOptional().isPresent() ) { - constructorNonOptionalSubTypeToOptional = subTypeOptionalToSubType1( target.getConstructorNonOptionalSubTypeToOptional() ); - } - if ( target.getConstructorOptionalSubTypeToOptional() != null && target.getConstructorOptionalSubTypeToOptional().isPresent() ) { - constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.getConstructorOptionalSubTypeToOptional() ); - } - else { - constructorOptionalSubTypeToOptional = Optional.empty(); - } - - Source source = new Source( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); - - if ( target.getOptionalToNonOptional() != null ) { - source.setOptionalToNonOptional( stringToStringOptional( target.getOptionalToNonOptional() ) ); - } - else { - source.setOptionalToNonOptional( Optional.empty() ); - } - if ( target.getNonOptionalToOptional() != null && target.getNonOptionalToOptional().isPresent() ) { - source.setNonOptionalToOptional( stringOptionalToString( target.getNonOptionalToOptional() ) ); - } - if ( target.getOptionalToOptional() != null && target.getOptionalToOptional().isPresent() ) { - source.setOptionalToOptional( target.getOptionalToOptional() ); - } - else { - source.setOptionalToOptional( Optional.empty() ); - } - if ( target.getOptionalSubTypeToNonOptional() != null ) { - source.setOptionalSubTypeToNonOptional( subTypeToSubTypeOptional1( target.getOptionalSubTypeToNonOptional() ) ); - } - else { - source.setOptionalSubTypeToNonOptional( Optional.empty() ); - } - if ( target.getNonOptionalSubTypeToOptional() != null && target.getNonOptionalSubTypeToOptional().isPresent() ) { - source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); - } - if ( target.getOptionalSubTypeToOptional() != null && target.getOptionalSubTypeToOptional().isPresent() ) { - source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); - } - else { - source.setOptionalSubTypeToOptional( Optional.empty() ); - } - if ( target.getMonitoredOptionalToString() != null ) { - source.setMonitoredOptionalToString( stringToStringOptional( target.getMonitoredOptionalToString() ) ); - } - else { - source.setMonitoredOptionalToString( Optional.empty() ); - } - if ( target.getMonitoredOptionalSubTypeToSubType() != null ) { - source.setMonitoredOptionalSubTypeToSubType( subTypeToSubTypeOptional1( target.getMonitoredOptionalSubTypeToSubType() ) ); - } - else { - source.setMonitoredOptionalSubTypeToSubType( Optional.empty() ); - } - if ( target.publicOptionalSubTypeToOptional != null && target.publicOptionalSubTypeToOptional.isPresent() ) { - source.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.publicOptionalSubTypeToOptional ); - } - else { - source.publicOptionalSubTypeToOptional = Optional.empty(); - } - if ( target.publicOptionalToNonOptionalWithDefault != null ) { - source.publicOptionalToNonOptionalWithDefault = stringToStringOptional( target.publicOptionalToNonOptionalWithDefault ); - } - else { - source.publicOptionalToNonOptionalWithDefault = Optional.empty(); - } - - return source; - } - - protected String stringOptionalToString(Optional optional) { - if ( optional == null ) { - return null; - } - - String string1 = optional.map( string -> string ).orElse( null ); - - return string1; - } - - protected Optional stringToStringOptional(String string) { - if ( string == null ) { - return Optional.empty(); - } - - String string1 = string; - Optional optional = Optional.ofNullable( string1 ); - - return optional; - } - - protected Target.SubType subTypeToSubType(Source.SubType subType) { - beforeNonOptionalSourceWithNoTargetType( subType ); - beforeNonOptionalSourceWithNonOptionalTargetType( Target.SubType.class, subType ); - - if ( subType == null ) { - return null; - } - - int value = 0; - - value = subType.getValue(); - - Target.SubType subType1 = new Target.SubType( value ); - - afterNonOptionalSourceWithNoTarget( subType ); - - return subType1; - } - - protected Target.SubType subTypeOptionalToSubType(Optional optional) { - beforeOptionalSourceWithNoTargetType( optional ); - beforeOptionalSourceWithNonOptionalTargetType( Target.SubType.class, optional ); - - if ( optional == null ) { - return null; - } - - Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); - - afterOptionalSourceWithNoTarget( optional ); - afterOptionalSourceWithNonOptionalTarget( subType1, optional ); - - return subType1; - } - - protected Optional subTypeToSubTypeOptional(Source.SubType subType) { - beforeNonOptionalSourceWithNoTargetType( subType ); - - if ( subType == null ) { - return Optional.empty(); - } - - Source.SubType subType1 = subType; - Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); - - afterNonOptionalSourceWithNoTarget( subType ); - afterNonOptionalSourceOptionalTarget( optional, subType ); - - return optional; - } - - protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { - beforeOptionalSourceWithNoTargetType( optional ); - - if ( optional == null ) { - return Optional.empty(); - } - - Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); - - afterOptionalSourceWithNoTarget( optional ); - afterOptionalSourceWithOptionalTarget( optional1, optional ); - - return optional1; - } - - protected Source.SubType subTypeToSubType1(Target.SubType subType) { - if ( subType == null ) { - return null; - } - - int value = 0; - - value = subType.getValue(); - - Source.SubType subType1 = new Source.SubType( value ); - - return subType1; - } - - protected Optional subTypeToSubTypeOptional1(Target.SubType subType) { - if ( subType == null ) { - return Optional.empty(); - } - - Target.SubType subType1 = subType; - Optional optional = Optional.ofNullable( subTypeToSubType1( subType1 ) ); - - return optional; - } - - protected Source.SubType subTypeOptionalToSubType1(Optional optional) { - if ( optional == null ) { - return null; - } - - Source.SubType subType1 = optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); - - return subType1; - } - - protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { - if ( optional == null ) { - return Optional.empty(); - } - - Optional optional1 = optional.map( subType -> subTypeToSubType1( subType ) ); - - return optional1; - } -} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java deleted file mode 100644 index 0e051c238c..0000000000 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/SimpleOptionalTestMapperImpl.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * 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.optionalmapping; - -import java.util.Optional; -import javax.annotation.processing.Generated; - -@Generated( - value = "org.mapstruct.ap.MappingProcessor", - date = "2023-06-30T00:32:23-0400", - comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" -) -public class SimpleOptionalTestMapperImpl implements SimpleOptionalTestMapper { - - @Override - public Target toTarget(Source source) { - if ( source == null ) { - return null; - } - - String constructorOptionalToNonOptional = null; - Optional constructorNonOptionalToOptional = null; - Optional constructorOptionalToOptional = null; - Target.SubType constructorOptionalSubTypeToNonOptional = null; - Optional constructorNonOptionalSubTypeToOptional = null; - Optional constructorOptionalSubTypeToOptional = null; - - constructorOptionalToNonOptional = stringOptionalToString( source.getConstructorOptionalToNonOptional() ); - constructorNonOptionalToOptional = stringToStringOptional( source.getConstructorNonOptionalToOptional() ); - constructorOptionalToOptional = source.getConstructorOptionalToOptional(); - constructorOptionalSubTypeToNonOptional = subTypeOptionalToSubType( source.getConstructorOptionalSubTypeToNonOptional() ); - constructorNonOptionalSubTypeToOptional = subTypeToSubTypeOptional( source.getConstructorNonOptionalSubTypeToOptional() ); - constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.getConstructorOptionalSubTypeToOptional() ); - - Target target = new Target( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); - - target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); - target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); - target.setOptionalToOptional( source.getOptionalToOptional() ); - target.setOptionalSubTypeToNonOptional( subTypeOptionalToSubType( source.getOptionalSubTypeToNonOptional() ) ); - target.setNonOptionalSubTypeToOptional( subTypeToSubTypeOptional( source.getNonOptionalSubTypeToOptional() ) ); - target.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalSubTypeToOptional() ) ); - target.setMonitoredOptionalToString( stringOptionalToString( source.getMonitoredOptionalToString() ) ); - target.setMonitoredOptionalSubTypeToSubType( subTypeOptionalToSubType( source.getMonitoredOptionalSubTypeToSubType() ) ); - target.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional( source.publicOptionalSubTypeToOptional ); - target.publicOptionalToNonOptionalWithDefault = stringOptionalToString( source.publicOptionalToNonOptionalWithDefault ); - - return target; - } - - @Override - public Source fromTarget(Target target) { - if ( target == null ) { - return null; - } - - Optional constructorOptionalToNonOptional = null; - String constructorNonOptionalToOptional = null; - Optional constructorOptionalToOptional = null; - Optional constructorOptionalSubTypeToNonOptional = null; - Source.SubType constructorNonOptionalSubTypeToOptional = null; - Optional constructorOptionalSubTypeToOptional = null; - - constructorOptionalToNonOptional = stringToStringOptional( target.getConstructorOptionalToNonOptional() ); - constructorNonOptionalToOptional = stringOptionalToString( target.getConstructorNonOptionalToOptional() ); - constructorOptionalToOptional = target.getConstructorOptionalToOptional(); - constructorOptionalSubTypeToNonOptional = subTypeToSubTypeOptional1( target.getConstructorOptionalSubTypeToNonOptional() ); - constructorNonOptionalSubTypeToOptional = subTypeOptionalToSubType1( target.getConstructorNonOptionalSubTypeToOptional() ); - constructorOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.getConstructorOptionalSubTypeToOptional() ); - - Source source = new Source( constructorOptionalToNonOptional, constructorNonOptionalToOptional, constructorOptionalToOptional, constructorOptionalSubTypeToNonOptional, constructorNonOptionalSubTypeToOptional, constructorOptionalSubTypeToOptional ); - - source.setOptionalToNonOptional( stringToStringOptional( target.getOptionalToNonOptional() ) ); - source.setNonOptionalToOptional( stringOptionalToString( target.getNonOptionalToOptional() ) ); - source.setOptionalToOptional( target.getOptionalToOptional() ); - source.setOptionalSubTypeToNonOptional( subTypeToSubTypeOptional1( target.getOptionalSubTypeToNonOptional() ) ); - source.setNonOptionalSubTypeToOptional( subTypeOptionalToSubType1( target.getNonOptionalSubTypeToOptional() ) ); - source.setOptionalSubTypeToOptional( subTypeOptionalToSubTypeOptional1( target.getOptionalSubTypeToOptional() ) ); - source.setMonitoredOptionalToString( stringToStringOptional( target.getMonitoredOptionalToString() ) ); - source.setMonitoredOptionalSubTypeToSubType( subTypeToSubTypeOptional1( target.getMonitoredOptionalSubTypeToSubType() ) ); - source.publicOptionalSubTypeToOptional = subTypeOptionalToSubTypeOptional1( target.publicOptionalSubTypeToOptional ); - source.publicOptionalToNonOptionalWithDefault = stringToStringOptional( target.publicOptionalToNonOptionalWithDefault ); - - return source; - } - - protected String stringOptionalToString(Optional optional) { - if ( optional == null ) { - return null; - } - - String string1 = optional.map( string -> string ).orElse( null ); - - return string1; - } - - protected Optional stringToStringOptional(String string) { - if ( string == null ) { - return Optional.empty(); - } - - String string1 = string; - Optional optional = Optional.ofNullable( string1 ); - - return optional; - } - - protected Target.SubType subTypeToSubType(Source.SubType subType) { - beforeNonOptionalSourceWithNoTargetType( subType ); - beforeNonOptionalSourceWithNonOptionalTargetType( Target.SubType.class, subType ); - - if ( subType == null ) { - return null; - } - - int value = 0; - - value = subType.getValue(); - - Target.SubType subType1 = new Target.SubType( value ); - - afterNonOptionalSourceWithNoTarget( subType ); - - return subType1; - } - - protected Target.SubType subTypeOptionalToSubType(Optional optional) { - beforeOptionalSourceWithNoTargetType( optional ); - beforeOptionalSourceWithNonOptionalTargetType( Target.SubType.class, optional ); - - if ( optional == null ) { - return null; - } - - Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); - - afterOptionalSourceWithNoTarget( optional ); - afterOptionalSourceWithNonOptionalTarget( subType1, optional ); - - return subType1; - } - - protected Optional subTypeToSubTypeOptional(Source.SubType subType) { - beforeNonOptionalSourceWithNoTargetType( subType ); - - if ( subType == null ) { - return Optional.empty(); - } - - Source.SubType subType1 = subType; - Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); - - afterNonOptionalSourceWithNoTarget( subType ); - afterNonOptionalSourceOptionalTarget( optional, subType ); - - return optional; - } - - protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { - beforeOptionalSourceWithNoTargetType( optional ); - - if ( optional == null ) { - return Optional.empty(); - } - - Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); - - afterOptionalSourceWithNoTarget( optional ); - afterOptionalSourceWithOptionalTarget( optional1, optional ); - - return optional1; - } - - protected Source.SubType subTypeToSubType1(Target.SubType subType) { - if ( subType == null ) { - return null; - } - - int value = 0; - - value = subType.getValue(); - - Source.SubType subType1 = new Source.SubType( value ); - - return subType1; - } - - protected Optional subTypeToSubTypeOptional1(Target.SubType subType) { - if ( subType == null ) { - return Optional.empty(); - } - - Target.SubType subType1 = subType; - Optional optional = Optional.ofNullable( subTypeToSubType1( subType1 ) ); - - return optional; - } - - protected Source.SubType subTypeOptionalToSubType1(Optional optional) { - if ( optional == null ) { - return null; - } - - Source.SubType subType1 = optional.map( subType -> subTypeToSubType1( subType ) ).orElse( null ); - - return subType1; - } - - protected Optional subTypeOptionalToSubTypeOptional1(Optional optional) { - if ( optional == null ) { - return Optional.empty(); - } - - Optional optional1 = optional.map( subType -> subTypeToSubType1( subType ) ); - - return optional1; - } -} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java new file mode 100644 index 0000000000..b7d0d19b09 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java @@ -0,0 +1,124 @@ +package org.mapstruct.ap.test.optionalmapping.beforeafter; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-11-20T22:01:31-0500", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" +) +public class OptionalBeforeAfterMapperImpl implements OptionalBeforeAfterMapper { + + @Override + public Target toTarget(Source source) { + if ( source == null ) { + return null; + } + + Optional deepOptionalToOptional = null; + Target.SubType deepOptionalToNonOptional = null; + Optional deepNonOptionalToOptional = null; + Optional shallowOptionalToOptional = null; + String shallowOptionalToNonOptional = null; + Optional shallowNonOptionalToOptional = null; + + deepOptionalToOptional = subTypeOptionalToSubTypeOptional( source.getDeepOptionalToOptional() ); + deepOptionalToNonOptional = subTypeOptionalToSubType( source.getDeepOptionalToNonOptional() ); + deepNonOptionalToOptional = subTypeToSubTypeOptional( source.getDeepNonOptionalToOptional() ); + shallowOptionalToOptional = source.getShallowOptionalToOptional(); + shallowOptionalToNonOptional = stringOptionalToString( source.getShallowOptionalToNonOptional() ); + shallowNonOptionalToOptional = stringToStringOptional( source.getShallowNonOptionalToOptional() ); + + Target target = new Target( deepOptionalToOptional, deepOptionalToNonOptional, deepNonOptionalToOptional, shallowOptionalToOptional, shallowOptionalToNonOptional, shallowNonOptionalToOptional ); + + return target; + } + + protected Target.SubType subTypeToSubType(Source.SubType subType) { + if ( subType == null ) { + return null; + } + + String value = null; + + value = subType.getValue(); + + Target.SubType subType1 = new Target.SubType( value ); + + return subType1; + } + + protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + beforeDeepOptionalSourceWithNoTargetType( optional ); + + if ( optional == null ) { + return null; + } + + Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); + + afterDeepOptionalSourceWithNoTarget( optional ); + afterDeepOptionalSourceWithOptionalTarget( optional1, optional ); + + return optional1; + } + + protected Target.SubType subTypeOptionalToSubType(Optional optional) { + beforeDeepOptionalSourceWithNoTargetType( optional ); + beforeDeepOptionalSourceWithNonOptionalTargetType( Target.SubType.class, optional ); + + if ( optional == null ) { + return null; + } + + Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + + afterDeepOptionalSourceWithNoTarget( optional ); + afterDeepOptionalSourceWithNonOptionalTarget( subType1, optional ); + + return subType1; + } + + protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Source.SubType subType1 = subType; + Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); + + afterDeepNonOptionalSourceOptionalTarget( optional, subType ); + + return optional; + } + + protected String stringOptionalToString(Optional optional) { + beforeShallowOptionalSourceWithNoTargetType( optional ); + beforeShallowOptionalSourceWithNonOptionalTargetType( String.class, optional ); + + if ( optional == null ) { + return null; + } + + String string1 = optional.map( string -> string ).orElse( null ); + + afterShallowOptionalSourceWithNoTarget( optional ); + afterShallowOptionalSourceWithNonOptionalTarget( string1, optional ); + + return string1; + } + + protected Optional stringToStringOptional(String string) { + if ( string == null ) { + return Optional.empty(); + } + + String string1 = string; + Optional optional = Optional.ofNullable( string1 ); + + afterShallowNonOptionalSourceOptionalTarget( optional, string ); + + return optional; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java new file mode 100644 index 0000000000..0294c84f63 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java @@ -0,0 +1,83 @@ +package org.mapstruct.ap.test.optionalmapping.differenttypes; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-11-20T21:40:58-0500", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" +) +public class OptionalDifferentTypesMapperImpl implements OptionalDifferentTypesMapper { + + @Override + public Target toTarget(Source source) { + if ( source == null ) { + return null; + } + + Optional constructorOptionalToOptional = null; + Target.SubType constructorOptionalToNonOptional = null; + Optional constructorNonOptionalToOptional = null; + + constructorOptionalToOptional = subTypeOptionalToSubTypeOptional( source.getConstructorOptionalToOptional() ); + constructorOptionalToNonOptional = subTypeOptionalToSubType( source.getConstructorOptionalToNonOptional() ); + constructorNonOptionalToOptional = subTypeToSubTypeOptional( source.getConstructorNonOptionalToOptional() ); + + Target target = new Target( constructorOptionalToOptional, constructorOptionalToNonOptional, constructorNonOptionalToOptional ); + + target.setOptionalToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalToOptional() ) ); + target.setOptionalToNonOptional( subTypeOptionalToSubType( source.getOptionalToNonOptional() ) ); + target.setNonOptionalToOptional( subTypeToSubTypeOptional( source.getNonOptionalToOptional() ) ); + target.publicOptionalToOptional = subTypeOptionalToSubTypeOptional( source.publicOptionalToOptional ); + target.publicOptionalToNonOptional = subTypeOptionalToSubType( source.publicOptionalToNonOptional ); + target.publicNonOptionalToOptional = subTypeToSubTypeOptional( source.publicNonOptionalToOptional ); + + return target; + } + + protected Target.SubType subTypeToSubType(Source.SubType subType) { + if ( subType == null ) { + return null; + } + + String value = null; + + value = subType.getValue(); + + Target.SubType subType1 = new Target.SubType( value ); + + return subType1; + } + + protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + if ( optional == null ) { + return null; + } + + Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); + + return optional1; + } + + protected Target.SubType subTypeOptionalToSubType(Optional optional) { + if ( optional == null ) { + return null; + } + + Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + + return subType1; + } + + protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Source.SubType subType1 = subType; + Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); + + return optional; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java new file mode 100644 index 0000000000..8a76a3ace3 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java @@ -0,0 +1,91 @@ +package org.mapstruct.ap.test.optionalmapping.nested; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-11-20T21:40:54-0500", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" +) +public class OptionalNestedMapperImpl implements OptionalNestedMapper { + + @Override + public Target toTarget(Source source) { + if ( source == null ) { + return null; + } + + Target target = new Target(); + + target.setOptionalToNonOptional( sourceOptionalToNonOptional_Value_( source ) ); + target.setOptionalToOptional( sourceOptionalToOptional_Value( source ) ); + target.setNonOptionalToNonOptional( sourceNonOptionalToNonOptional_Value( source ) ); + target.setNonOptionalToOptional( stringToStringOptional( sourceNonOptionalToOptional_Value( source ) ) ); + + return target; + } + + private String sourceOptionalToNonOptional_Value_(Source source) { + Optional optionalToNonOptional = source.getOptionalToNonOptional(); + if ( optionalToNonOptional == null ) { + return null; + } + Source.NestedOptional optionalValue = optionalToNonOptional.orElse( null ); + if ( optionalValue == null ) { + return null; + } + Optional value = optionalValue.getValue(); + if ( value == null ) { + return null; + } + return value.orElse( null ); + } + + private Optional sourceOptionalToOptional_Value(Source source) { + Optional optionalToOptional = source.getOptionalToOptional(); + if ( optionalToOptional == null ) { + return Optional.empty(); + } + Source.NestedOptional optionalValue = optionalToOptional.orElse( null ); + if ( optionalValue == null ) { + return Optional.empty(); + } + return optionalValue.getValue(); + } + + private String sourceNonOptionalToNonOptional_Value(Source source) { + Optional nonOptionalToNonOptional = source.getNonOptionalToNonOptional(); + if ( nonOptionalToNonOptional == null ) { + return null; + } + Source.NestedNonOptional optionalValue = nonOptionalToNonOptional.orElse( null ); + if ( optionalValue == null ) { + return null; + } + return optionalValue.getValue(); + } + + private String sourceNonOptionalToOptional_Value(Source source) { + Optional nonOptionalToOptional = source.getNonOptionalToOptional(); + if ( nonOptionalToOptional == null ) { + return null; + } + Source.NestedNonOptional optionalValue = nonOptionalToOptional.orElse( null ); + if ( optionalValue == null ) { + return null; + } + return optionalValue.getValue(); + } + + protected Optional stringToStringOptional(String string) { + if ( string == null ) { + return Optional.empty(); + } + + String string1 = string; + Optional optional = Optional.ofNullable( string1 ); + + return optional; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java new file mode 100644 index 0000000000..6d8a7071e8 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java @@ -0,0 +1,54 @@ +package org.mapstruct.ap.test.optionalmapping.nullcheckalways; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-11-20T21:40:55-0500", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" +) +public class OptionalNullCheckAlwaysMapperImpl implements OptionalNullCheckAlwaysMapper { + + @Override + public Target toTarget(Source source) { + if ( source == null ) { + return null; + } + + Target target = new Target(); + + if ( source.getOptionalToOptional() != null ) { + target.setOptionalToOptional( source.getOptionalToOptional() ); + } + if ( source.getOptionalToNonOptional() != null ) { + target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); + } + if ( source.getNonOptionalToOptional() != null ) { + target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); + } + + return target; + } + + protected String stringOptionalToString(Optional optional) { + if ( optional == null ) { + return null; + } + + String string1 = optional.map( string -> string ).orElse( null ); + + return string1; + } + + protected Optional stringToStringOptional(String string) { + if ( string == null ) { + return Optional.empty(); + } + + String string1 = string; + Optional optional = Optional.ofNullable( string1 ); + + return optional; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java new file mode 100644 index 0000000000..89925db100 --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java @@ -0,0 +1,79 @@ +package org.mapstruct.ap.test.optionalmapping.nullvaluepropertytodefault; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-11-20T21:40:59-0500", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" +) +public class NullValuePropertyToDefaultMapperImpl implements NullValuePropertyToDefaultMapper { + + @Override + public void mapTarget(Source source, Target target) { + if ( source == null ) { + return; + } + + if ( source.getOptionalToOptional() != null ) { + target.setOptionalToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalToOptional() ) ); + } + else { + target.setOptionalToOptional( Optional.empty() ); + } + if ( source.getNonOptionalToOptional() != null ) { + target.setNonOptionalToOptional( subTypeToSubTypeOptional( source.getNonOptionalToOptional() ) ); + } + else { + target.setNonOptionalToOptional( Optional.empty() ); + } + if ( source.publicOptionalToOptional != null ) { + target.publicOptionalToOptional = subTypeOptionalToSubTypeOptional( source.publicOptionalToOptional ); + } + else { + target.publicOptionalToOptional = Optional.empty(); + } + if ( source.publicNonOptionalToOptional != null ) { + target.publicNonOptionalToOptional = subTypeToSubTypeOptional( source.publicNonOptionalToOptional ); + } + else { + target.publicNonOptionalToOptional = Optional.empty(); + } + } + + protected Target.SubType subTypeToSubType(Source.SubType subType) { + if ( subType == null ) { + return null; + } + + String value = null; + + value = subType.getValue(); + + Target.SubType subType1 = new Target.SubType( value ); + + return subType1; + } + + protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + if ( optional == null ) { + return null; + } + + Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); + + return optional1; + } + + protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Source.SubType subType1 = subType; + Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); + + return optional; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java new file mode 100644 index 0000000000..ab28bb682f --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java @@ -0,0 +1,81 @@ +package org.mapstruct.ap.test.optionalmapping.nullvaluetodefault; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-11-20T21:40:57-0500", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" +) +public class NullValueToDefaultMapperImpl implements NullValueToDefaultMapper { + + @Override + public Target toTarget(Source source) { + + Optional constructorOptionalToOptional = null; + Target.SubType constructorOptionalToNonOptional = null; + Optional constructorNonOptionalToOptional = null; + if ( source != null ) { + constructorOptionalToOptional = subTypeOptionalToSubTypeOptional( source.getConstructorOptionalToOptional() ); + constructorOptionalToNonOptional = subTypeOptionalToSubType( source.getConstructorOptionalToNonOptional() ); + constructorNonOptionalToOptional = subTypeToSubTypeOptional( source.getConstructorNonOptionalToOptional() ); + } + + Target target = new Target( constructorOptionalToOptional, constructorOptionalToNonOptional, constructorNonOptionalToOptional ); + + if ( source != null ) { + target.setOptionalToOptional( subTypeOptionalToSubTypeOptional( source.getOptionalToOptional() ) ); + target.setOptionalToNonOptional( subTypeOptionalToSubType( source.getOptionalToNonOptional() ) ); + target.setNonOptionalToOptional( subTypeToSubTypeOptional( source.getNonOptionalToOptional() ) ); + target.publicOptionalToOptional = subTypeOptionalToSubTypeOptional( source.publicOptionalToOptional ); + target.publicOptionalToNonOptional = subTypeOptionalToSubType( source.publicOptionalToNonOptional ); + target.publicNonOptionalToOptional = subTypeToSubTypeOptional( source.publicNonOptionalToOptional ); + } + + return target; + } + + protected Target.SubType subTypeToSubType(Source.SubType subType) { + + String value = null; + if ( subType != null ) { + value = subType.getValue(); + } + + Target.SubType subType1 = new Target.SubType( value ); + + return subType1; + } + + protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { + if ( optional == null ) { + return Optional.empty(); + } + + Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); + + return optional1; + } + + protected Target.SubType subTypeOptionalToSubType(Optional optional) { + if ( optional == null ) { + return null; + } + + Target.SubType subType1 = optional.map( subType -> subTypeToSubType( subType ) ).orElse( null ); + + return subType1; + } + + protected Optional subTypeToSubTypeOptional(Source.SubType subType) { + if ( subType == null ) { + return Optional.empty(); + } + + Source.SubType subType1 = subType; + Optional optional = Optional.ofNullable( subTypeToSubType( subType1 ) ); + + return optional; + } +} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java new file mode 100644 index 0000000000..1162d89c7e --- /dev/null +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java @@ -0,0 +1,59 @@ +package org.mapstruct.ap.test.optionalmapping.sametype; + +import java.util.Optional; +import javax.annotation.processing.Generated; + +@Generated( + value = "org.mapstruct.ap.MappingProcessor", + date = "2023-11-20T21:40:52-0500", + comments = "version: , compiler: javac, environment: Java 11.0.19 (Homebrew)" +) +public class OptionalSameTypeMapperImpl implements OptionalSameTypeMapper { + + @Override + public Target toTarget(Source source) { + if ( source == null ) { + return null; + } + + Optional constructorOptionalToOptional = null; + String constructorOptionalToNonOptional = null; + Optional constructorNonOptionalToOptional = null; + + constructorOptionalToOptional = source.getConstructorOptionalToOptional(); + constructorOptionalToNonOptional = stringOptionalToString( source.getConstructorOptionalToNonOptional() ); + constructorNonOptionalToOptional = stringToStringOptional( source.getConstructorNonOptionalToOptional() ); + + Target target = new Target( constructorOptionalToOptional, constructorOptionalToNonOptional, constructorNonOptionalToOptional ); + + target.setOptionalToOptional( source.getOptionalToOptional() ); + target.setOptionalToNonOptional( stringOptionalToString( source.getOptionalToNonOptional() ) ); + target.setNonOptionalToOptional( stringToStringOptional( source.getNonOptionalToOptional() ) ); + target.publicOptionalToOptional = source.publicOptionalToOptional; + target.publicOptionalToNonOptional = stringOptionalToString( source.publicOptionalToNonOptional ); + target.publicNonOptionalToOptional = stringToStringOptional( source.publicNonOptionalToOptional ); + + return target; + } + + protected String stringOptionalToString(Optional optional) { + if ( optional == null ) { + return null; + } + + String string1 = optional.map( string -> string ).orElse( null ); + + return string1; + } + + protected Optional stringToStringOptional(String string) { + if ( string == null ) { + return Optional.empty(); + } + + String string1 = string; + Optional optional = Optional.ofNullable( string1 ); + + return optional; + } +} From 56cf07464ce73d8ec2467ba3b76cb8abfb11d994 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Mon, 20 Nov 2023 22:27:28 -0500 Subject: [PATCH 15/17] formatting --- .../optionalmapping/beforeafter/OptionalBeforeAfterTest.java | 3 ++- .../differenttypes/OptionalDifferentTypesTest.java | 3 ++- .../ap/test/optionalmapping/nested/OptionalNestedTest.java | 3 ++- .../nullcheckalways/OptionalNullCheckAlwaysTest.java | 3 ++- .../NullValuePropertyToDefaultTest.java | 3 ++- .../nullvaluetodefault/NullValueToDefaultTest.java | 3 ++- .../test/optionalmapping/sametype/OptionalSameTypeTest.java | 3 ++- .../beforeafter/OptionalBeforeAfterMapperImpl.java | 5 +++++ .../differenttypes/OptionalDifferentTypesMapperImpl.java | 5 +++++ .../optionalmapping/nested/OptionalNestedMapperImpl.java | 5 +++++ .../nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java | 5 +++++ .../NullValuePropertyToDefaultMapperImpl.java | 5 +++++ .../nullvaluetodefault/NullValueToDefaultMapperImpl.java | 5 +++++ .../optionalmapping/sametype/OptionalSameTypeMapperImpl.java | 5 +++++ 14 files changed, 49 insertions(+), 7 deletions(-) diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java index ce3350a0f5..6a6b043313 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterTest.java @@ -16,7 +16,8 @@ public class OptionalBeforeAfterTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalBeforeAfterMapper.class ); + final GeneratedSource generatedSource = new GeneratedSource() + .addComparisonToFixtureFor( OptionalBeforeAfterMapper.class ); @ProcessorTest public void dummyTest() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java index 2473fc8fe2..7f21bfc12a 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java @@ -20,7 +20,8 @@ public class OptionalDifferentTypesTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalDifferentTypesMapper.class ); + final GeneratedSource generatedSource = new GeneratedSource() + .addComparisonToFixtureFor( OptionalDifferentTypesMapper.class ); @ProcessorTest public void constructorOptionalToOptionalWhenPresent() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java index 4f1a351dfd..f9c0edc0cc 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedTest.java @@ -20,7 +20,8 @@ public class OptionalNestedTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalNestedMapper.class ); + final GeneratedSource generatedSource = new GeneratedSource() + .addComparisonToFixtureFor( OptionalNestedMapper.class ); @ProcessorTest public void optionalToNonOptionalWhenEmpty() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java index 35bcd502cd..ce404409f0 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysTest.java @@ -18,7 +18,8 @@ public class OptionalNullCheckAlwaysTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalNullCheckAlwaysMapper.class ); + final GeneratedSource generatedSource = new GeneratedSource() + .addComparisonToFixtureFor( OptionalNullCheckAlwaysMapper.class ); @ProcessorTest public void optionalToOptionalWhenNull() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java index 57a656ef9f..5e2a23678b 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultTest.java @@ -20,7 +20,8 @@ public class NullValuePropertyToDefaultTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( NullValuePropertyToDefaultMapper.class ); + final GeneratedSource generatedSource = new GeneratedSource() + .addComparisonToFixtureFor( NullValuePropertyToDefaultMapper.class ); @ProcessorTest public void optionalToOptionalWhenNull() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java index 479bb74002..03e4b11de9 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultTest.java @@ -20,7 +20,8 @@ public class NullValueToDefaultTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( NullValueToDefaultMapper.class ); + final GeneratedSource generatedSource = new GeneratedSource() + .addComparisonToFixtureFor( NullValueToDefaultMapper.class ); @ProcessorTest public void constructorOptionalToOptionalWhenNull() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java index bb7a8ec02f..686e23bf68 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeTest.java @@ -20,7 +20,8 @@ public class OptionalSameTypeTest { @RegisterExtension - final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor( OptionalSameTypeMapper.class ); + final GeneratedSource generatedSource = new GeneratedSource() + .addComparisonToFixtureFor( OptionalSameTypeMapper.class ); @ProcessorTest public void constructorOptionalToOptionalWhenPresent() { diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java index b7d0d19b09..982d9ff4f1 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.beforeafter; import java.util.Optional; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java index 0294c84f63..015fdf82e5 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.differenttypes; import java.util.Optional; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java index 8a76a3ace3..1bb3a85dbc 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nested/OptionalNestedMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.nested; import java.util.Optional; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java index 6d8a7071e8..8d923e47e1 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullcheckalways/OptionalNullCheckAlwaysMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.nullcheckalways; import java.util.Optional; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java index 89925db100..c8ccacc1a6 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.nullvaluepropertytodefault; import java.util.Optional; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java index ab28bb682f..3097b3d21d 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluetodefault/NullValueToDefaultMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.nullvaluetodefault; import java.util.Optional; diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java index 1162d89c7e..3e467f9ef4 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/sametype/OptionalSameTypeMapperImpl.java @@ -1,3 +1,8 @@ +/* + * 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.optionalmapping.sametype; import java.util.Optional; From 563afa3ef4771f45f9483b81a88f3595e9faab20 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Mon, 20 Nov 2023 22:59:24 -0500 Subject: [PATCH 16/17] always return Optional.empty() for inner maps --- .../ap/internal/model/OptionalMappingMethod.ftl | 2 +- .../differenttypes/OptionalDifferentTypesTest.java | 12 +++--------- .../beforeafter/OptionalBeforeAfterMapperImpl.java | 2 +- .../OptionalDifferentTypesMapperImpl.java | 2 +- .../NullValuePropertyToDefaultMapperImpl.java | 2 +- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl index 6bd2b7fc7b..401f40fee5 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/OptionalMappingMethod.ftl @@ -15,7 +15,7 @@ if ( <@includeModel object=sourceParameterPresenceCheck.negate() /> ) { - <#if (!sourceParameter.type.optionalType && resultType.optionalType) || mapNullToDefault> + <#if resultType.optionalType || mapNullToDefault> return <@includeModel object=initDefaultValueForResultType/>; <#else> return<#if returnType.name != "void"> null; diff --git a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java index 7f21bfc12a..aae100ce72 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesTest.java @@ -39,14 +39,12 @@ public void constructorOptionalToOptionalWhenEmpty() { assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); } - // TODO Contentious - // Should null Optional map to null Optional, or explicitly to empty? @ProcessorTest public void constructorOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); - assertThat( target.getConstructorOptionalToOptional() ).isNull(); + assertThat( target.getConstructorOptionalToOptional() ).isEmpty(); } @ProcessorTest @@ -107,15 +105,13 @@ public void optionalToOptionalWhenEmpty() { assertThat( target.getOptionalToOptional() ).isEmpty(); } - // TODO Contentious - // Should null Optional map to null Optional, or explicitly to empty? @ProcessorTest public void optionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.setOptionalToOptional( null ); Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); - assertThat( target.getOptionalToOptional() ).isNull(); + assertThat( target.getOptionalToOptional() ).isEmpty(); } @ProcessorTest @@ -181,15 +177,13 @@ public void publicOptionalToOptionalWhenEmpty() { assertThat( target.publicOptionalToOptional ).isEmpty(); } - // TODO Contentious - // Should null Optional map to null Optional, or explicitly to empty? @ProcessorTest public void publicOptionalToOptionalWhenNull() { Source source = new Source( null, null, null ); source.publicOptionalToOptional = null; Target target = OptionalDifferentTypesMapper.INSTANCE.toTarget( source ); - assertThat( target.publicOptionalToOptional ).isNull(); + assertThat( target.publicOptionalToOptional ).isEmpty(); } @ProcessorTest diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java index 982d9ff4f1..8a3b57b4a2 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/beforeafter/OptionalBeforeAfterMapperImpl.java @@ -58,7 +58,7 @@ protected Optional subTypeOptionalToSubTypeOptional(Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java index 015fdf82e5..a5f6a4b0f1 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/differenttypes/OptionalDifferentTypesMapperImpl.java @@ -57,7 +57,7 @@ protected Target.SubType subTypeToSubType(Source.SubType subType) { protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { if ( optional == null ) { - return null; + return Optional.empty(); } Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); diff --git a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java index c8ccacc1a6..8bb4bb5c51 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/ap/test/optionalmapping/nullvaluepropertytodefault/NullValuePropertyToDefaultMapperImpl.java @@ -63,7 +63,7 @@ protected Target.SubType subTypeToSubType(Source.SubType subType) { protected Optional subTypeOptionalToSubTypeOptional(Optional optional) { if ( optional == null ) { - return null; + return Optional.empty(); } Optional optional1 = optional.map( subType -> subTypeToSubType( subType ) ); From 087ddc8c8220ed92f0462b9aaefff8134b7d9a28 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Mon, 20 Nov 2023 23:31:35 -0500 Subject: [PATCH 17/17] javadoc --- core/src/main/java/org/mapstruct/NullValueCheckStrategy.java | 4 ++-- .../org/mapstruct/ap/internal/model/InitDefaultValue.java | 2 +- .../ap/internal/util/accessor/OptionalValueAccessor.java | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java b/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java index 653c2eb4ff..22dba7c58b 100644 --- a/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java +++ b/core/src/main/java/org/mapstruct/NullValueCheckStrategy.java @@ -21,7 +21,7 @@ public enum NullValueCheckStrategy { /** - * This option includes a null check as well as an empty check for Optional type. When: + * This option includes a null check. When: *
      *
      *
        @@ -36,7 +36,7 @@ public enum NullValueCheckStrategy { ON_IMPLICIT_CONVERSION, /** - * This option always includes a null check as well as an empty check for Optional type. + * This option always includes a null check. */ ALWAYS; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.java b/processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.java index 7d2f009e3d..086f87ead9 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/InitDefaultValue.java @@ -24,7 +24,7 @@ *

        If no default value can be constructed, a null is returned instead. * TODO: Consider throwing an exception instead of returning null. * - * @author kenwang + * @author Ken Wang */ public class InitDefaultValue extends ModelElement { diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.java b/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.java index 21c8b34b4b..37ed2b88e5 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/accessor/OptionalValueAccessor.java @@ -11,6 +11,11 @@ import javax.lang.model.element.Modifier; import javax.lang.model.type.TypeMirror; +/** + * An {@link Accessor} for retrieving the value inside an {@link java.util.Optional}. + * + * @author Ken Wang + */ public class OptionalValueAccessor implements ReadAccessor { private final TypeMirror valueTypeMirror;