Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.Strings;
import org.mapstruct.ap.internal.util.TypeUtils;
import org.mapstruct.ap.internal.version.VersionInformation;
import org.mapstruct.ap.spi.EnumTransformationStrategy;

import static org.mapstruct.ap.internal.gem.MappingConstantsGem.ANY_REMAINING;
Expand All @@ -46,6 +47,7 @@ public class ValueMappingMethod extends MappingMethod {
private final List<MappingEntry> valueMappings;
private final MappingEntry defaultTarget;
private final MappingEntry nullTarget;
private final VersionInformation versionInformation;

private final Type unexpectedValueMappingException;

Expand Down Expand Up @@ -128,19 +130,22 @@ else if ( sourceType.isString() && targetType.isEnumType() ) {
new AdditionalAnnotationsBuilder(
ctx.getElementUtils(),
ctx.getTypeFactory(),
ctx.getMessager() );
ctx.getMessager()
);

annotations.addAll( additionalAnnotationsBuilder.getProcessedAnnotations( method.getExecutable() ) );
}
// finally return a mapping
return new ValueMappingMethod( method,
return new ValueMappingMethod(
method,
annotations,
mappingEntries,
valueMappings.nullValueTarget,
valueMappings.defaultTargetValue,
determineUnexpectedValueMappingException(),
beforeMappingMethods,
afterMappingMethods
afterMappingMethods,
ctx.getVersionInformation()
);
}

Expand All @@ -154,8 +159,10 @@ private void initializeEnumTransformationStrategy() {

String nameTransformationStrategy = enumMapping.getNameTransformationStrategy();
if ( enumTransformationStrategies.containsKey( nameTransformationStrategy ) ) {
enumTransformationInvoker = new EnumTransformationStrategyInvoker( enumTransformationStrategies.get(
nameTransformationStrategy ), enumMapping.getNameTransformationConfiguration() );
enumTransformationInvoker = new EnumTransformationStrategyInvoker(
enumTransformationStrategies.get(
nameTransformationStrategy ), enumMapping.getNameTransformationConfiguration()
);
}
}

Expand All @@ -180,7 +187,7 @@ private String transform(String source) {
}
}

private List<MappingEntry> enumToEnumMapping(Method method, Type sourceType, Type targetType ) {
private List<MappingEntry> enumToEnumMapping(Method method, Type sourceType, Type targetType) {

List<MappingEntry> mappings = new ArrayList<>();
List<String> unmappedSourceConstants = new ArrayList<>( sourceType.getEnumConstants() );
Expand Down Expand Up @@ -252,7 +259,8 @@ else if ( NULL.equals( targetConstant ) ) {
}
// all sources should now be matched, there's no default to fall back to, so if sources remain,
// we have an issue.
ctx.getMessager().printMessage( method.getExecutable(),
ctx.getMessager().printMessage(
method.getExecutable(),
Message.VALUEMAPPING_UNMAPPED_SOURCES,
sourceErrorMessage,
targetErrorMessage,
Expand All @@ -264,7 +272,7 @@ else if ( NULL.equals( targetConstant ) ) {
return mappings;
}

private List<MappingEntry> enumToStringMapping(Method method, Type sourceType ) {
private List<MappingEntry> enumToStringMapping(Method method, Type sourceType) {

List<MappingEntry> mappings = new ArrayList<>();
List<String> unmappedSourceConstants = new ArrayList<>( sourceType.getEnumConstants() );
Expand Down Expand Up @@ -294,7 +302,7 @@ private List<MappingEntry> enumToStringMapping(Method method, Type sourceType )
return mappings;
}

private List<MappingEntry> stringToEnumMapping(Method method, Type targetType ) {
private List<MappingEntry> stringToEnumMapping(Method method, Type targetType) {

List<MappingEntry> mappings = new ArrayList<>();
List<String> unmappedSourceConstants = new ArrayList<>( targetType.getEnumConstants() );
Expand Down Expand Up @@ -439,7 +447,8 @@ private boolean reportErrorIfMappedTargetEnumConstantsDontExist(Method method, T

if ( valueMappings.nullTarget != null && NULL.equals( valueMappings.nullTarget.getTarget() )
&& !targetEnumConstants.contains( valueMappings.nullTarget.getTarget() ) ) {
ctx.getMessager().printMessage( method.getExecutable(),
ctx.getMessager().printMessage(
method.getExecutable(),
valueMappings.nullTarget.getMirror(),
valueMappings.nullTarget.getTargetAnnotationValue(),
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
Expand Down Expand Up @@ -554,22 +563,38 @@ private ValueMappingMethod(Method method,
String defaultTarget,
Type unexpectedValueMappingException,
List<LifecycleCallbackMethodReference> beforeMappingMethods,
List<LifecycleCallbackMethodReference> afterMappingMethods) {
List<LifecycleCallbackMethodReference> afterMappingMethods,
VersionInformation versionInformation) {
super( method, beforeMappingMethods, afterMappingMethods );
this.valueMappings = enumMappings;
this.nullTarget = new MappingEntry( null, nullTarget );
this.defaultTarget = new MappingEntry( null, defaultTarget != null ? defaultTarget : THROW_EXCEPTION);
this.defaultTarget = new MappingEntry( null, defaultTarget != null ? defaultTarget : THROW_EXCEPTION );
this.unexpectedValueMappingException = unexpectedValueMappingException;
this.overridden = method.overridesMethod();
this.annotations = annotations;
this.versionInformation = versionInformation;
}

public boolean isDefaultTargetRequired() {
if ( !versionInformation.isSourceVersionAtLeast14() ) {
return true;
}

Type sourceType = getSourceParameter().getType();
if ( !sourceType.isEnumType() ) {
return true;
}

return sourceType.getEnumConstants().size() != getValueMappings().size();
}

@Override
public Set<Type> getImportTypes() {
Set<Type> importTypes = super.getImportTypes();

if ( unexpectedValueMappingException != null && !unexpectedValueMappingException.isJavaLangType() ) {
if ( defaultTarget.isTargetAsException() || nullTarget.isTargetAsException() ||
if ( ( isDefaultTargetRequired() && defaultTarget.isTargetAsException() ) ||
nullTarget.isTargetAsException() ||
hasMappingWithTargetAsException() ) {
importTypes.addAll( unexpectedValueMappingException.getImportTypes() );
}
Expand Down Expand Up @@ -598,6 +623,10 @@ public MappingEntry getNullTarget() {
return nullTarget;
}

public VersionInformation getVersionInformation() {
return versionInformation;
}

public Type getUnexpectedValueMappingException() {
return unexpectedValueMappingException;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ public class DefaultVersionInformation implements VersionInformation {
private final String compiler;
private final boolean sourceVersionAtLeast9;
private final boolean sourceVersionAtLeast11;
private final boolean sourceVersionAtLeast14;
private final boolean sourceVersionAtLeast19;
private final boolean eclipseJDT;
private final boolean javac;

DefaultVersionInformation(String runtimeVersion, String runtimeVendor, String compiler,
SourceVersion sourceVersion) {
SourceVersion sourceVersion) {
this.runtimeVersion = runtimeVersion;
this.runtimeVendor = runtimeVendor;
this.compiler = compiler;
Expand All @@ -55,6 +56,7 @@ public class DefaultVersionInformation implements VersionInformation {
// If the difference between the source version and RELEASE_6 is more that 2 than we are at least on 9
this.sourceVersionAtLeast9 = sourceVersion.compareTo( SourceVersion.RELEASE_6 ) > 2;
this.sourceVersionAtLeast11 = sourceVersion.compareTo( SourceVersion.RELEASE_6 ) > 4;
this.sourceVersionAtLeast14 = sourceVersion.compareTo( SourceVersion.RELEASE_6 ) > 7;
this.sourceVersionAtLeast19 = sourceVersion.compareTo( SourceVersion.RELEASE_6 ) > 12;
}

Expand Down Expand Up @@ -88,6 +90,11 @@ public boolean isSourceVersionAtLeast11() {
return sourceVersionAtLeast11;
}

@Override
public boolean isSourceVersionAtLeast14() {
return sourceVersionAtLeast14;
}

Comment thread
hduelme marked this conversation as resolved.
@Override
public boolean isSourceVersionAtLeast19() {
return sourceVersionAtLeast19;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public interface VersionInformation {

boolean isSourceVersionAtLeast11();

boolean isSourceVersionAtLeast14();

boolean isSourceVersionAtLeast19();

boolean isEclipseJDTCompiler();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,35 @@
<#if nullTarget.targetAsException>throw new <@includeModel object=unexpectedValueMappingException />( "Unexpected enum constant: " + ${sourceParameter.name} );<#else>return <@writeTarget target=nullTarget.target/>;</#if>
}

<@includeModel object=resultType/> ${resultName};
<#if versionInformation.isSourceVersionAtLeast14()>
<#if valueMappings.empty>
<#if defaultTarget.targetAsException>
<@includeModel object=resultType/> ${resultName};
throw new <@includeModel object=unexpectedValueMappingException />( "Unexpected enum constant: " + ${sourceParameter.name} );
<#else>
<@includeModel object=resultType/> ${resultName} = <@writeTarget target=defaultTarget.target/>;
</#if>
<#else>
<@includeModel object=resultType/> ${resultName} = switch ( ${sourceParameter.name} ) {
<#list valueMappings as valueMapping>
case <@writeSource source=valueMapping.source/> -> <#if valueMapping.targetAsException > throw new <@includeModel object=unexpectedValueMappingException />( "Unexpected enum constant: " + ${sourceParameter.name} );<#else><@writeTarget target=valueMapping.target/>;</#if>
</#list>
<#if isDefaultTargetRequired()>
default -> <#if defaultTarget.targetAsException>throw new <@includeModel object=unexpectedValueMappingException/>( "Unexpected enum constant: " + ${sourceParameter.name} )<#else><@writeTarget target=defaultTarget.target/></#if>;
</#if>
};
</#if>
<#else>
<@includeModel object=resultType/> ${resultName};

switch ( ${sourceParameter.name} ) {
<#list valueMappings as valueMapping>
case <@writeSource source=valueMapping.source/>: <#if valueMapping.targetAsException >throw new <@includeModel object=unexpectedValueMappingException />( "Unexpected enum constant: " + ${sourceParameter.name} );<#else>${resultName} = <@writeTarget target=valueMapping.target/>;
break;</#if>
</#list>
default: <#if defaultTarget.targetAsException >throw new <@includeModel object=unexpectedValueMappingException />( "Unexpected enum constant: " + ${sourceParameter.name} )<#else>${resultName} = <@writeTarget target=defaultTarget.target/></#if>;
}
switch ( ${sourceParameter.name} ) {
<#list valueMappings as valueMapping>
case <@writeSource source=valueMapping.source/>: <#if valueMapping.targetAsException >throw new <@includeModel object=unexpectedValueMappingException />( "Unexpected enum constant: " + ${sourceParameter.name} );<#else>${resultName} = <@writeTarget target=valueMapping.target/>;
break;</#if>
</#list>
default: <#if defaultTarget.targetAsException >throw new <@includeModel object=unexpectedValueMappingException />( "Unexpected enum constant: " + ${sourceParameter.name} )<#else>${resultName} = <@writeTarget target=defaultTarget.target/></#if>;
}
</#if>
<#list beforeMappingReferencesWithMappingTarget as callback>
<#if callback_index = 0>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* 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.nestedbeans;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.processing.Generated;

@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2026-06-12T22:15:18+0200",
comments = "version: , compiler: javac, environment: Java 21.0.11 (Eclipse Adoptium)"
)
public class UserDtoMapperClassicImpl implements UserDtoMapperClassic {

@Override
public UserDto userToUserDto(User user) {
if ( user == null ) {
return null;
}

UserDto userDto = new UserDto();

userDto.setName( user.getName() );
userDto.setCar( carToCarDto( user.getCar() ) );
userDto.setSecondCar( carToCarDto( user.getSecondCar() ) );
userDto.setHouse( houseToHouseDto( user.getHouse() ) );

return userDto;
}

@Override
public CarDto carToCarDto(Car car) {
if ( car == null ) {
return null;
}

CarDto carDto = new CarDto();

carDto.setName( car.getName() );
carDto.setYear( car.getYear() );
carDto.setWheels( mapWheels( car.getWheels() ) );

return carDto;
}

@Override
public HouseDto houseToHouseDto(House house) {
if ( house == null ) {
return null;
}

HouseDto houseDto = new HouseDto();

houseDto.setName( house.getName() );
houseDto.setYear( house.getYear() );
houseDto.setRoof( roofToRoofDto( house.getRoof() ) );

return houseDto;
}

@Override
public RoofDto roofToRoofDto(Roof roof) {
if ( roof == null ) {
return null;
}

RoofDto roofDto = new RoofDto();

roofDto.setColor( String.valueOf( roof.getColor() ) );
roofDto.setType( mapRoofType( roof.getType() ) );

return roofDto;
}

@Override
public List<WheelDto> mapWheels(List<Wheel> wheels) {
if ( wheels == null ) {
return null;
}

List<WheelDto> list = new ArrayList<>( wheels.size() );
for ( Wheel wheel : wheels ) {
list.add( mapWheel( wheel ) );
}

return list;
}

@Override
public WheelDto mapWheel(Wheel wheels) {
if ( wheels == null ) {
return null;
}

WheelDto wheelDto = new WheelDto();

wheelDto.setFront( wheels.isFront() );
wheelDto.setRight( wheels.isRight() );

return wheelDto;
}

@Override
public ExternalRoofType mapRoofType(RoofType roofType) {
if ( roofType == null ) {
return null;
}

ExternalRoofType externalRoofType = switch ( roofType ) {
case OPEN -> ExternalRoofType.OPEN;
case BOX -> ExternalRoofType.BOX;
case GAMBREL -> ExternalRoofType.GAMBREL;
};

return externalRoofType;
}
}
Loading
Loading