Skip to content
Open
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 @@ -54,6 +54,8 @@
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.model.dependency.GraphAnalyzer;
import org.mapstruct.ap.internal.model.dependency.GraphAnalyzer.GraphAnalyzerBuilder;
import org.mapstruct.ap.internal.model.presence.NullPresenceCheck;
import org.mapstruct.ap.internal.model.presence.OptionalPresenceCheck;
import org.mapstruct.ap.internal.model.source.BeanMappingOptions;
import org.mapstruct.ap.internal.model.source.MappingOptions;
import org.mapstruct.ap.internal.model.source.Method;
Expand Down Expand Up @@ -2310,6 +2312,21 @@ public PresenceCheck getPresenceCheckByParameter(Parameter parameter) {
return presenceChecksByParameter.get( parameter.getName() );
}

/**
* Returns {@code true} if the presence check for the given parameter is a built-in
* null or optional presence check, as opposed to a custom
* {@link org.mapstruct.SourceParameterCondition} method.
* Used by the template to decide whether to generate a default value fallback
* in the else branch of the parameter presence check.
*
* @param parameter the source parameter
* @return {@code true} for built-in null/optional checks, {@code false} for custom condition methods
*/
public boolean isBuiltInPresenceCheckByParameter(Parameter parameter) {
PresenceCheck check = getPresenceCheckByParameter( parameter );
return check instanceof NullPresenceCheck || check instanceof OptionalPresenceCheck;
}

public List<Parameter> getSourceParametersNeedingPresenceCheck() {
return getSourceParameters().stream()
.filter( this::needsPresenceCheck )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,26 @@
<@includeModel object=propertyMapping existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
</#list>
}
<#if isBuiltInPresenceCheckByParameter(sourceParam)>
<#assign hasConstructorDefaults = false>
<#list constructorPropertyMappingsByParameter(sourceParam) as pm>
<#if pm.defaultValueAssignment??><#assign hasConstructorDefaults = true><#break></#if>
</#list>
<#if hasConstructorDefaults>
else {
<#list constructorPropertyMappingsByParameter(sourceParam) as propertyMapping>
<#if propertyMapping.defaultValueAssignment??>
<@includeModel object=propertyMapping.defaultValueAssignment
existingInstanceMapping=existingInstanceMapping
targetReadAccessorName=propertyMapping.targetReadAccessorName
targetWriteAccessorName=propertyMapping.targetWriteAccessorName
targetPropertyName=propertyMapping.name
targetType=propertyMapping.targetType/>
</#if>
</#list>
}
</#if>
</#if>
</#if>
</#list>
<#list sourceParametersNotNeedingPresenceCheck as sourceParam>
Expand All @@ -94,6 +114,26 @@
</#list>
<#if mapNullToDefault>
}
<#if isBuiltInPresenceCheckByParameter(sourceParameters[0])>
<#assign hasSingleConstructorDefaults = false>
<#list constructorPropertyMappingsByParameter(sourceParameters[0]) as pm>
<#if pm.defaultValueAssignment??><#assign hasSingleConstructorDefaults = true><#break></#if>
</#list>
<#if hasSingleConstructorDefaults>
else {
<#list constructorPropertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
<#if propertyMapping.defaultValueAssignment??>
<@includeModel object=propertyMapping.defaultValueAssignment
existingInstanceMapping=existingInstanceMapping
targetReadAccessorName=propertyMapping.targetReadAccessorName
targetWriteAccessorName=propertyMapping.targetWriteAccessorName
targetPropertyName=propertyMapping.name
targetType=propertyMapping.targetType/>
</#if>
</#list>
}
</#if>
</#if>
</#if>
</#if>
<#list constructorConstantMappings as constantMapping>
Expand Down Expand Up @@ -129,6 +169,27 @@
<@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
</#list>
}
<#if !existingInstanceMapping && isBuiltInPresenceCheckByParameter(sourceParam)>
<#assign hasDefaults = false>
<#list propertyMappingsByParameter(sourceParam) as pm>
<#if pm.defaultValueAssignment??><#assign hasDefaults = true><#break></#if>
</#list>
<#if hasDefaults>
else {
<#list propertyMappingsByParameter(sourceParam) as propertyMapping>
<#if propertyMapping.defaultValueAssignment??>
<@includeModel object=propertyMapping.defaultValueAssignment
targetBeanName=resultName
existingInstanceMapping=existingInstanceMapping
targetReadAccessorName=propertyMapping.targetReadAccessorName
targetWriteAccessorName=propertyMapping.targetWriteAccessorName
targetPropertyName=propertyMapping.name
targetType=propertyMapping.targetType/>
</#if>
</#list>
}
</#if>
</#if>
</#if>
</#list>
<#list sourceParametersNotNeedingPresenceCheck as sourceParam>
Expand All @@ -149,6 +210,27 @@
<@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
</#list>
<#if mapNullToDefault>}</#if>
<#if mapNullToDefault && !existingInstanceMapping && isBuiltInPresenceCheckByParameter(sourceParameters[0])>
<#assign hasSingleDefaults = false>
<#list propertyMappingsByParameter(sourceParameters[0]) as pm>
<#if pm.defaultValueAssignment??><#assign hasSingleDefaults = true><#break></#if>
</#list>
<#if hasSingleDefaults>
else {
<#list propertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
<#if propertyMapping.defaultValueAssignment??>
<@includeModel object=propertyMapping.defaultValueAssignment
targetBeanName=resultName
existingInstanceMapping=existingInstanceMapping
targetReadAccessorName=propertyMapping.targetReadAccessorName
targetWriteAccessorName=propertyMapping.targetWriteAccessorName
targetPropertyName=propertyMapping.name
targetType=propertyMapping.targetType/>
</#if>
</#list>
}
</#if>
</#if>
</#if>
<#list constantMappings as constantMapping>
<@includeModel object=constantMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2436;

public class ConstructorTarget {

private final String property1;
private final String property2;

public ConstructorTarget(String property1, String property2) {
this.property1 = property1;
this.property2 = property2;
}

public String getProperty1() {
return property1;
}

public String getProperty2() {
return property2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2436;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.SourceParameterCondition;
import org.mapstruct.factory.Mappers;

@Mapper
public interface Issue2436ConditionMapper {

Issue2436ConditionMapper INSTANCE = Mappers.getMapper( Issue2436ConditionMapper.class );

@Mapping(target = "property1", source = "source1.property1", defaultValue = "default1")
@Mapping(target = "property2", source = "source2.property2", defaultValue = "default2")
@Mapping(target = "property3", ignore = true)
Target map(Source1 source1, Source2 source2);

@SourceParameterCondition
default boolean isValid(Source1 source1) {
return source1 != null && source1.getProperty1() != null;
}
}
Original file line number Diff line number Diff line change
@@ -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.bugs._2436;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface Issue2436ConstructorMapper {

Issue2436ConstructorMapper INSTANCE = Mappers.getMapper( Issue2436ConstructorMapper.class );

@Mapping(target = "property1", source = "source1.property1", defaultValue = "default1")
@Mapping(target = "property2", source = "source2.property2", defaultValue = "default2")
ConstructorTarget map(Source1 source1, Source2 source2);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2436;

import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.NullValueMappingStrategy;
import org.mapstruct.factory.Mappers;

@Mapper
public interface Issue2436ConstructorReturnDefaultMapper {

Issue2436ConstructorReturnDefaultMapper INSTANCE =
Mappers.getMapper( Issue2436ConstructorReturnDefaultMapper.class );

@BeanMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
@Mapping(target = "property1", source = "source1.property1", defaultValue = "default1")
@Mapping(target = "property2", source = "source1.property1", defaultValue = "default2")
ConstructorTarget map(Source1 source1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2436;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface Issue2436Mapper {

Issue2436Mapper INSTANCE = Mappers.getMapper( Issue2436Mapper.class );

@Mapping(target = "property1", source = "source1.property1", defaultValue = "default1")
@Mapping(target = "property2", source = "source2.property2", defaultExpression = "java(\"default2\")")
@Mapping(target = "property3", source = "source1.property1")
Target map(Source1 source1, Source2 source2);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2436;

import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.NullValueMappingStrategy;
import org.mapstruct.factory.Mappers;

@Mapper
public interface Issue2436ReturnDefaultMapper {

Issue2436ReturnDefaultMapper INSTANCE = Mappers.getMapper( Issue2436ReturnDefaultMapper.class );

@BeanMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
@Mapping(target = "property1", source = "source1.property1", defaultValue = "default1")
@Mapping(target = "property2", source = "source1.property1")
@Mapping(target = "property3", ignore = true)
Target map(Source1 source1);
}
Loading