Content-Length: 637139 | pFad | http://github.com/mapstruct/mapstruct/pull/3616/files

DC #3617 support for target this enum mapping. by Zegveld · Pull Request #3616 · mapstruct/mapstruct · GitHub
Skip to content

#3617 support for target this enum mapping. #3616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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 @@ -235,7 +235,7 @@ else if ( !method.isUpdateMethod() ) {

this.unprocessedTargetProperties = new LinkedHashMap<>( accessors );

if ( !method.isUpdateMethod() && !hasFactoryMethod ) {
if ( !method.isUpdateMethod() && !hasFactoryMethod && !isCorrectlyDefinedTargetThisForEnumTarget() ) {
ConstructorAccessor constructorAccessor = getConstructorAccessor( resultTypeToMap );
if ( constructorAccessor != null ) {

Expand Down Expand Up @@ -310,6 +310,8 @@ else if ( !method.isUpdateMethod() ) {
// map parameters without a mapping
applyParameterNameBasedMapping();

// map this enum mapping
applyTargetThisMappingForEnumTarget();
}

// Process the unprocessed defined targets
Expand Down Expand Up @@ -514,7 +516,8 @@ private SubclassMapping createSubclassMapping(SubclassMappingOptions subclassMap
private boolean isAbstractReturnTypeAllowed() {
return !method.getOptions().getSubclassMappings().isEmpty()
&& ( method.getOptions().getBeanMapping().getSubclassExhaustiveStrategy().isAbstractReturnTypeAllowed()
|| isCorrectlySealed() );
|| isCorrectlySealed() )
|| isCorrectlyDefinedTargetThisForEnumTarget();
}

private boolean isCorrectlySealed() {
Expand Down Expand Up @@ -756,7 +759,9 @@ else if ( !returnType.hasAccessibleConstructor() ) {

private boolean isReturnTypeAbstractOrCanBeConstructed(Type returnType) {
boolean error = true;
if ( !returnType.isAbstract() && !returnType.hasAccessibleConstructor() ) {
if ( !returnType.isAbstract()
&& !returnType.hasAccessibleConstructor()
&& !isCorrectlyDefinedTargetThisForEnumTarget() ) {
ctx
.getMessager()
.printMessage(
Expand Down Expand Up @@ -1532,6 +1537,38 @@ private void applyTargetThisMapping() {
}
}

/**
* When a single target this mapping is present, and the current target type is an enum.
*/
private void applyTargetThisMappingForEnumTarget() {
if ( !isCorrectlyDefinedTargetThisForEnumTarget() ) {
return;
}

for ( MappingReference targetThis : this.targetThisReferences ) {
PropertyMapping propertyMapping = new PropertyMappingBuilder().mappingContext( ctx )
.sourceMethod( method )
.sourcePropertyName( "test" )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to have no effect in this case, however this seems fishy - maybe just not set sourcePropertyName at all?

.sourceReference( targetThis.getSourceReference() )
.targetType( this.method.getReturnType() )
.forgedNamedBased( false )
.existingVariableNames( existingVariableNames )
.forgeMethodWithMappingReferences( MappingReferences.empty() )
.options( method.getOptions().getBeanMapping() )
.build();

if ( propertyMapping != null ) {
propertyMappings.add( propertyMapping );
}
}
}

private boolean isCorrectlyDefinedTargetThisForEnumTarget() {
return this.method.getOptions().getMappings().size() == 1
&& this.method.getOptions().getMappings().iterator().next().getTargetName().equals( "." )
&& this.method.getReturnType().isEnumType();
}

/**
* Iterates over all target properties and all source parameters.
* <p>
Expand Down Expand Up @@ -2115,6 +2152,10 @@ private boolean doesNotNeedPresenceCheckForSourceParameter(PropertyMapping mappi
return mapping.getAssignment().isSourceReferenceParameter();
}

public boolean shouldDirectlyReturnOnlyMappingResult() {
return this.returnTypeToConstruct.isEnumType() && this.propertyMappings.size() == 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could come up with more tests. I have no idea what scenarios could be tested, but after checking the coverage report we could provide a test where this.propertyMappings.size() is != 1

Not quite sure though, my coverage report seems to be a bit buggy.

}

@Override
public int hashCode() {
//Needed for Checkstyle, otherwise it fails due to EqualsHashCode rule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@
*/
package org.mapstruct.ap.internal.model;

import static org.mapstruct.ap.internal.gem.NullValueCheckStrategyGem.ALWAYS;
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.IGNORE;
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.SET_TO_DEFAULT;
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.SET_TO_NULL;
import static org.mapstruct.ap.internal.model.ForgedMethod.forElementMapping;
import static org.mapstruct.ap.internal.model.ForgedMethod.forParameterMapping;
import static org.mapstruct.ap.internal.model.ForgedMethod.forPropertyMapping;
import static org.mapstruct.ap.internal.model.common.Assignment.AssignmentType.DIRECT;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import javax.lang.model.element.AnnotationMirror;

import org.mapstruct.ap.internal.gem.BuilderGem;
Expand All @@ -20,6 +30,7 @@
import org.mapstruct.ap.internal.model.assignment.ArrayCopyWrapper;
import org.mapstruct.ap.internal.model.assignment.EnumConstantWrapper;
import org.mapstruct.ap.internal.model.assignment.GetterWrapperForCollectionsAndMaps;
import org.mapstruct.ap.internal.model.assignment.ResultWrapper;
import org.mapstruct.ap.internal.model.assignment.SetterWrapper;
import org.mapstruct.ap.internal.model.assignment.StreamAdderWrapper;
import org.mapstruct.ap.internal.model.assignment.UpdateWrapper;
Expand Down Expand Up @@ -51,15 +62,6 @@
import org.mapstruct.ap.internal.util.accessor.AccessorType;
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;

import static org.mapstruct.ap.internal.gem.NullValueCheckStrategyGem.ALWAYS;
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.IGNORE;
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.SET_TO_DEFAULT;
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.SET_TO_NULL;
import static org.mapstruct.ap.internal.model.ForgedMethod.forElementMapping;
import static org.mapstruct.ap.internal.model.ForgedMethod.forParameterMapping;
import static org.mapstruct.ap.internal.model.ForgedMethod.forPropertyMapping;
import static org.mapstruct.ap.internal.model.common.Assignment.AssignmentType.DIRECT;

/**
* Represents the mapping between a source and target property, e.g. from {@code String Source#foo} to
* {@code int Target#bar}. Name and type of source and target property can differ. If they have different types, the
Expand Down Expand Up @@ -160,6 +162,11 @@ public static class PropertyMappingBuilder extends MappingBuilderBase<PropertyMa
super( PropertyMappingBuilder.class );
}

public PropertyMappingBuilder targetType(Type targetType) {
this.targetType = targetType;
return this;
}

public PropertyMappingBuilder sourceReference(SourceReference sourceReference) {
this.sourceReference = sourceReference;
return this;
Expand Down Expand Up @@ -278,6 +285,9 @@ public PropertyMapping build() {
else if ( targetType.isArrayType() && sourceType.isArrayType() && assignment.getType() == DIRECT ) {
assignment = assignToArray( targetType, assignment );
}
else if ( targetType.isEnumType() && targetType == this.method.getResultType() ) {
assignment = assignToReturn( assignment );
}
else {
assignment = assignToPlain( targetType, targetWriteAccessorType, assignment );
}
Expand All @@ -290,7 +300,7 @@ else if ( targetType.isArrayType() && sourceType.isArrayType() && assignment.get
sourcePropertyName,
targetPropertyName,
rightHandSide.getSourceParameterName(),
targetWriteAccessor.getSimpleName(),
targetWriteAccessor == null ? "" : targetWriteAccessor.getSimpleName(),
targetReadAccessor,
targetType,
assignment,
Expand Down Expand Up @@ -393,6 +403,12 @@ private Assignment getDefaultValueAssignment( Assignment rhs ) {
return null;
}

private Assignment assignToReturn(Assignment assignment) {

return new ResultWrapper( assignment );

}

private Assignment assignToPlain(Type targetType, AccessorType targetAccessorType,
Assignment rightHandSide) {

Expand Down
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.internal.model.assignment;

import org.mapstruct.ap.internal.model.common.Assignment;

/**
* Decorates an assignment as a return variable.
*
* @author Ben Zegveld
*/
public class ResultWrapper extends AssignmentWrapper {

public ResultWrapper(Assignment decoratedAssignment) {
super( decoratedAssignment, false );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@


<@includeModel object=returnTypeToConstruct/> ${resultName} = <@includeModel object=factoryMethod targetType=returnTypeToConstruct/>;
<#else >
<#elseif shouldDirectlyReturnOnlyMappingResult()>
<@includeModel object=returnTypeToConstruct/> ${resultName};
<#else>
<@includeModel object=returnTypeToConstruct/> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod targetType=returnTypeToConstruct/><#else>new <@includeModel object=returnTypeToConstruct/>()</#if>;
</#if>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<#--

Copyright MapStruct Authors.

Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0

-->
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.assignment.ReturnWrapper" -->
${ext.targetBeanName} = <@_assignment/>;
<#macro _assignment>
<@includeModel object=assignment
targetBeanName=ext.targetBeanName
existingInstanceMapping=ext.existingInstanceMapping
targetReadAccessorName=ext.targetReadAccessorName
targetWriteAccessorName=ext.targetWriteAccessorName
targetPropertyName=ext.targetPropertyName
targetType=ext.targetType/>
</#macro>
Original file line number Diff line number Diff line change
@@ -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.bugs._2421;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingConstants;
import org.mapstruct.ValueMapping;

@Mapper
abstract class Issue2421Mapper {

@Mapping( target = ".", source = "value" )
@ValueMapping( target = "C", source = MappingConstants.ANY_REMAINING )
public abstract EnumExample dtoTestToEnum(InnerDtoTest innerDtoTest);

}

enum EnumExample {
A, B, C
}

class InnerDtoTest {
private String value;

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

class TargetTest {
private EnumExample enumExampleValue;

public EnumExample getEnumExampleValue() {
return enumExampleValue;
}

public void setEnumExampleValue(EnumExample enumExampleValue) {
this.enumExampleValue = enumExampleValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2421;

import org.mapstruct.ap.testutil.ProcessorTest;
import org.mapstruct.ap.testutil.WithClasses;

public class Issue2421Test {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, we would need to change the issue number to 3617 - might aswell add @IssueKey("3617") here.


@ProcessorTest
@WithClasses( Issue2421Mapper.class )
void shouldCompile() {
}
}
Loading








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/mapstruct/mapstruct/pull/3616/files

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy