Skip to content

Commit

Permalink
tried to support arrays as target - stopped because of null values in…
Browse files Browse the repository at this point in the history
… target array - intermediate method used for lists and then `resultList.toArray(new Employee[0]);` would be nice - or somehow using a list in the forged method anyways:

```
public Employee[] mapListToArray(List<EmployeeDto> employees) {
    if (employees == null) {
        return null;
    }

    List<Employee> resultList = new ArrayList<>();
    for ( EmployeeDto employeeDto : employees ) {
        if ( countryIsNotNull( employeeDto ) ) {
            resultList.add(map(employeeDto));
        }
    }

    return resultList.toArray(new Employee[0]);
}
```
  • Loading branch information
thunderhook committed Sep 22, 2024
1 parent d9566ba commit 728b42a
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,7 @@ protected IterableMappingMethod instantiateMappingMethod(Method method, Collecti
}

public boolean hasIterableConditionMethod() {
return getIterableConditionMethod() != null;
}

public Method getIterableConditionMethod() {
return iterableConditionMethod;
return iterableConditionMethod != null;
}

public MethodReference getIterableConditionMethodReference() {
Expand All @@ -101,10 +97,7 @@ public MethodReference getIterableConditionMethodReference() {
)
);

return MethodReference.forForgedMethod(
iterableConditionMethod,
parameterBindings
);
return MethodReference.forForgedMethod( iterableConditionMethod, parameterBindings );
}

private IterableMappingMethod(Method method, List<Annotation> annotations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</#list>
<#if overridden>@Override</#if>
<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@throws/> {
<#list beforeMappingReferencesWithoutMappingTarget as callback>
<#list beforeMappingReferencesWithoutMappingTarget as callback>
<@includeModel object=callback targetBeanName=resultName targetType=resultType/>
<#if !callback_has_next>

Expand Down Expand Up @@ -41,37 +41,52 @@
</#if>
}

<#if resultType.arrayType>
<#if !existingInstanceMapping>
<#assign elementTypeString><@includeModel object=resultElementType/></#assign>
${elementTypeString}[] ${resultName} = new ${elementTypeString?keep_before('[]')}[<@iterableSize/>]${elementTypeString?replace('[^\\[\\]]+', '', 'r')};
</#if>
<#else>
<#-- <#if resultType.arrayType>-->
<#-- <#if !existingInstanceMapping>-->
<#-- <#assign elementTypeString><@includeModel object=resultElementType/></#assign>-->
<#-- ${elementTypeString}[] ${resultName} = new ${elementTypeString?keep_before('[]')}[<@iterableSize/>]${elementTypeString?replace('[^\\[\\]]+', '', 'r')};-->
<#-- </#if>-->
<#-- <#else>-->
<#if existingInstanceMapping>
${resultName}.clear();
<#else>
<#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side -->
<@iterableLocalVarDef/> ${resultName} = <@includeModel object=iterableCreation useSizeIfPossible=true/>;
</#if>
</#if>
<#-- </#if>-->
<#list beforeMappingReferencesWithMappingTarget as callback>
<@includeModel object=callback targetBeanName=resultName targetType=resultType/>
<#if !callback_has_next>

</#if>
</#list>
<#if resultType.arrayType>
int ${index1Name} = 0;
for ( <@includeModel object=sourceElementType/> ${loopVariableName} : ${sourceParameter.name} ) {
<#if existingInstanceMapping>
if ( ( ${index1Name} >= ${resultName}.length ) || ( ${index1Name} >= <@iterableSize/> ) ) {
break;
}
</#if>
<@includeModel object=elementAssignment targetWriteAccessorName=resultName+"[${index1Name}]" targetType=resultElementType isTargetDefined=true/>
${index1Name}++;
}
<#else>

</#if>
<#if true>
<#-- <#if resultType.arrayType>-->
<#-- int ${index1Name} = 0;-->
<#-- for ( <@includeModel object=sourceElementType/> ${loopVariableName} : ${sourceParameter.name} ) {-->
<#-- <#if existingInstanceMapping>-->
<#-- if ( ( ${index1Name} >= ${resultName}.length ) || ( ${index1Name} >= <@iterableSize/> ) ) {-->
<#-- break;-->
<#-- }-->
<#-- </#if>-->
<#-- <#if hasIterableConditionMethod()>-->
<#-- if ( <@includeModel object=iterableConditionMethodReference /> ) {-->
<#-- <@includeModel object=elementAssignment targetWriteAccessorName=resultName+"[${index1Name}]" targetType=resultElementType isTargetDefined=true/>-->
<#-- ${index1Name}++;-->
<#-- }-->
<#-- <#else>-->
<#-- <@includeModel object=elementAssignment targetWriteAccessorName=resultName+"[${index1Name}]" targetType=resultElementType isTargetDefined=true/>-->
<#-- ${index1Name}++;-->
<#-- </#if>-->
<#-- }-->
<#-- Employee[] employeeTmp = employees.stream()-->
<#-- .filter(this::countryIsNotNull)-->
<#-- .map(this::map)-->
<#-- .toArray(Employee[]::new);-->
<#-- <#else>-->
for ( <@includeModel object=sourceElementType/> ${loopVariableName} : ${sourceParameter.name} ) {
<#if hasIterableConditionMethod()>
if ( <@includeModel object=iterableConditionMethodReference /> ) {
Expand All @@ -90,7 +105,11 @@
</#list>

<#if returnType.name != "void">
return ${resultName};
<#if hasIterableConditionMethod() && resultType.arrayType>
${resultName}.toArray( new <@includeModel object=resultElementType/>[0] );
<#else>
return ${resultName};
</#if>
</#if>
}
<#macro throws>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ public interface IterableElementConditionMapper {
@Mapping(target = "ssid", source = "uniqueIdNumber")
Employee map(EmployeeDto employee);

List<Employee> map(List<EmployeeDto> employees);
List<Employee> mapListToList(List<EmployeeDto> employees);

List<Employee> mapArrayToList(EmployeeDto[] employees);

// Employee[] mapListToArray(List<EmployeeDto> employees);
//
// Employee[] mapArrayToArray(EmployeeDto[] employees);


@IterableElementCondition
default boolean countryIsNotNull(EmployeeDto value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
package org.mapstruct.ap.test.conditional.iterable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.mapstruct.ap.test.conditional.Employee;
import org.mapstruct.ap.test.conditional.EmployeeDto;
Expand All @@ -22,16 +24,58 @@
@IssueKey("1610")
@WithClasses({
Employee.class,
EmployeeDto.class
EmployeeDto.class,
IterableElementConditionMapper.class,
})
public class IterableElementConditionTest {

@ProcessorTest
@WithClasses({
IterableElementConditionMapper.class
})
public void conditionalMethodWithSourceParameter() {
IterableElementConditionMapper mapper = IterableElementConditionMapper.INSTANCE;
public void conditionalMethodListToList() {

List<Employee> result = IterableElementConditionMapper.INSTANCE.mapListToList( setupList() );

assertThatOnlyFilteredValuesMapped( result );
}

@ProcessorTest
public void conditionalMethodArrayToList() {

List<Employee> result = IterableElementConditionMapper.INSTANCE.mapArrayToList( setupArray() );

assertThatOnlyFilteredValuesMapped( result );
}

// @ProcessorTest
// public void conditionalMethodListToArray() {
//
// Employee[] result = IterableElementConditionMapper.INSTANCE.mapListToArray( setupList() );
//
// assertThatOnlyFilteredValuesMapped( result );
// }
//
// @ProcessorTest
// public void conditionalMethodArrayToArray() {
//
// Employee[] result = IterableElementConditionMapper.INSTANCE.mapArrayToArray( setupArray() );
//
// assertThatOnlyFilteredValuesMapped( result );
// }

private static void assertThatOnlyFilteredValuesMapped(List<Employee> result) {
assertThat( result )
.singleElement()
.satisfies(
d -> assertThat( d.getName() ).isEqualTo( "Tester" )
);
}

private static void assertThatOnlyFilteredValuesMapped(Employee[] result) {
assertThatOnlyFilteredValuesMapped(
Arrays.stream( result ).collect( Collectors.toList() )
);
}

private static ArrayList<EmployeeDto> setupList() {

EmployeeDto dtoWithoutCountry = new EmployeeDto();
dtoWithoutCountry.setName( "Tester" );
Expand All @@ -47,13 +91,11 @@ public void conditionalMethodWithSourceParameter() {
employees.add( dtoWithoutCountry );
employees.add( dtoWithCountry );

List<Employee> result = mapper.map( employees );
assertThat( result )
.singleElement()
.satisfies(
d -> assertThat(d.getName()).isEqualTo( "Tester" )
);
return employees;
}

private static EmployeeDto[] setupArray() {
return setupList().toArray( new EmployeeDto[0] );
}

}

0 comments on commit 728b42a

Please sign in to comment.