highly WIP

This commit is contained in:
thunderhook 2024-09-22 22:24:10 +02:00
parent 30651b989b
commit d9566bab76
3 changed files with 57 additions and 7 deletions

View File

@ -5,8 +5,7 @@
*/ */
package org.mapstruct.ap.internal.model; package org.mapstruct.ap.internal.model;
import static org.mapstruct.ap.internal.util.Collections.first; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -14,10 +13,13 @@ import java.util.Set;
import org.mapstruct.ap.internal.model.assignment.LocalVarWrapper; import org.mapstruct.ap.internal.model.assignment.LocalVarWrapper;
import org.mapstruct.ap.internal.model.assignment.SetterWrapper; import org.mapstruct.ap.internal.model.assignment.SetterWrapper;
import org.mapstruct.ap.internal.model.common.Assignment; import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.model.source.SelectionParameters;
import static org.mapstruct.ap.internal.util.Collections.first;
/** /**
* A {@link MappingMethod} implemented by a {@link Mapper} class which maps one iterable type to another. The collection * A {@link MappingMethod} implemented by a {@link Mapper} class which maps one iterable type to another. The collection
* elements are mapped either by a {@link TypeConversion} or another mapping method. * elements are mapped either by a {@link TypeConversion} or another mapping method.
@ -26,12 +28,21 @@ import org.mapstruct.ap.internal.model.source.SelectionParameters;
*/ */
public class IterableMappingMethod extends ContainerMappingMethod { public class IterableMappingMethod extends ContainerMappingMethod {
private Method iterableConditionMethod;
public static class Builder extends ContainerMappingMethodBuilder<Builder, IterableMappingMethod> { public static class Builder extends ContainerMappingMethodBuilder<Builder, IterableMappingMethod> {
private Method iterableConditionMethod;
public Builder() { public Builder() {
super( Builder.class, "collection element" ); super( Builder.class, "collection element" );
} }
public Builder iterableConditionMethod(Method iterableConditionMethod) {
this.iterableConditionMethod = iterableConditionMethod;
return this;
}
@Override @Override
protected Type getElementType(Type parameterType) { protected Type getElementType(Type parameterType) {
return parameterType.isArrayType() ? parameterType.getComponentType() : first( return parameterType.isArrayType() ? parameterType.getComponentType() : first(
@ -65,17 +76,43 @@ public class IterableMappingMethod extends ContainerMappingMethod {
loopVariableName, loopVariableName,
beforeMappingMethods, beforeMappingMethods,
afterMappingMethods, afterMappingMethods,
selectionParameters selectionParameters,
iterableConditionMethod
); );
} }
} }
public boolean hasIterableConditionMethod() {
return getIterableConditionMethod() != null;
}
public Method getIterableConditionMethod() {
return iterableConditionMethod;
}
public MethodReference getIterableConditionMethodReference() {
ArrayList<ParameterBinding> parameterBindings = new ArrayList<>();
parameterBindings.add(
ParameterBinding.fromTypeAndName(
iterableConditionMethod.getParameters().get( 0 ).getType(),
getLoopVariableName()
)
);
return MethodReference.forForgedMethod(
iterableConditionMethod,
parameterBindings
);
}
private IterableMappingMethod(Method method, List<Annotation> annotations, private IterableMappingMethod(Method method, List<Annotation> annotations,
Collection<String> existingVariables, Assignment parameterAssignment, Collection<String> existingVariables, Assignment parameterAssignment,
MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName, MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName,
List<LifecycleCallbackMethodReference> beforeMappingReferences, List<LifecycleCallbackMethodReference> beforeMappingReferences,
List<LifecycleCallbackMethodReference> afterMappingReferences, List<LifecycleCallbackMethodReference> afterMappingReferences,
SelectionParameters selectionParameters) { SelectionParameters selectionParameters, Method iterableConditionMethod) {
super( super(
method, method,
annotations, annotations,
@ -88,6 +125,7 @@ public class IterableMappingMethod extends ContainerMappingMethod {
afterMappingReferences, afterMappingReferences,
selectionParameters selectionParameters
); );
this.iterableConditionMethod = iterableConditionMethod;
} }
@Override @Override

View File

@ -25,6 +25,7 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter; import javax.lang.model.util.ElementFilter;
import org.mapstruct.ap.internal.gem.BuilderGem; import org.mapstruct.ap.internal.gem.BuilderGem;
import org.mapstruct.ap.internal.gem.ConditionStrategyGem;
import org.mapstruct.ap.internal.gem.DecoratedWithGem; import org.mapstruct.ap.internal.gem.DecoratedWithGem;
import org.mapstruct.ap.internal.gem.InheritConfigurationGem; import org.mapstruct.ap.internal.gem.InheritConfigurationGem;
import org.mapstruct.ap.internal.gem.InheritInverseConfigurationGem; import org.mapstruct.ap.internal.gem.InheritInverseConfigurationGem;
@ -340,10 +341,18 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
this.messager.note( 1, Message.ITERABLEMAPPING_CREATE_NOTE, method ); this.messager.note( 1, Message.ITERABLEMAPPING_CREATE_NOTE, method );
Method iterableConditionMethod = methods.stream()
.filter( m -> m.getConditionOptions()
.isStrategyApplicable( ConditionStrategyGem.ITERABLE_ELEMENTS ) )
.findFirst()
.orElse( null );
// TODO here are all methods - select them via MethodResolver (like PresenceCheckMethodResolver) and add it to the builder
IterableMappingMethod iterableMappingMethod = createWithElementMappingMethod( IterableMappingMethod iterableMappingMethod = createWithElementMappingMethod(
method, method,
mappingOptions, mappingOptions,
new IterableMappingMethod.Builder() new IterableMappingMethod.Builder()
.iterableConditionMethod( iterableConditionMethod )
); );
hasFactoryMethod = iterableMappingMethod.getFactoryMethod() != null; hasFactoryMethod = iterableMappingMethod.getFactoryMethod() != null;

View File

@ -24,7 +24,6 @@
<#if resultType.arrayType> <#if resultType.arrayType>
<#if existingInstanceMapping> <#if existingInstanceMapping>
<#-- we can't clear an existing array, so we've got to clear by setting values to default --> <#-- we can't clear an existing array, so we've got to clear by setting values to default -->
// test
${resultName}[${index2Name}] = ${resultElementType.null}; ${resultName}[${index2Name}] = ${resultElementType.null};
} }
return<#if returnType.name != "void"> ${resultName}</#if>; return<#if returnType.name != "void"> ${resultName}</#if>;
@ -74,9 +73,13 @@
} }
<#else> <#else>
for ( <@includeModel object=sourceElementType/> ${loopVariableName} : ${sourceParameter.name} ) { for ( <@includeModel object=sourceElementType/> ${loopVariableName} : ${sourceParameter.name} ) {
if ( countryIsNotNull( employeeDto ) ) { <#if hasIterableConditionMethod()>
if ( <@includeModel object=iterableConditionMethodReference /> ) {
<@includeModel object=elementAssignment targetBeanName=resultName targetWriteAccessorName="add" targetType=resultElementType/> <@includeModel object=elementAssignment targetBeanName=resultName targetWriteAccessorName="add" targetType=resultElementType/>
} }
<#else>
<@includeModel object=elementAssignment targetBeanName=resultName targetWriteAccessorName="add" targetType=resultElementType/>
</#if>
} }
</#if> </#if>
<#list afterMappingReferences as callback> <#list afterMappingReferences as callback>