All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mapstruct.ap.internal.model.CollectionAssignmentBuilder Maven / Gradle / Ivy

There is a newer version: 1.6.3
Show newest version
/*
 * 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;

import org.mapstruct.ap.internal.model.assignment.ExistingInstanceSetterWrapperForCollectionsAndMaps;
import org.mapstruct.ap.internal.model.assignment.GetterWrapperForCollectionsAndMaps;
import org.mapstruct.ap.internal.model.assignment.SetterWrapperForCollectionsAndMaps;
import org.mapstruct.ap.internal.model.assignment.SetterWrapperForCollectionsAndMapsWithNullCheck;
import org.mapstruct.ap.internal.model.assignment.UpdateWrapper;
import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.SourceRHS;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.gem.CollectionMappingStrategyGem;
import org.mapstruct.ap.internal.gem.NullValueCheckStrategyGem;
import org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem;
import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.accessor.Accessor;
import org.mapstruct.ap.internal.util.accessor.AccessorType;

import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.SET_TO_DEFAULT;
import static org.mapstruct.ap.internal.gem.NullValuePropertyMappingStrategyGem.SET_TO_NULL;

/**
 * A builder that is used for creating an assignment to a collection.
 *
 * The created assignments to the following null checks:
 * 
    *
  • source-null-check - For this the {@link SetterWrapperForCollectionsAndMapsWithNullCheck} is used when a * direct assignment is done or the {@link org.mapstruct.NullValueCheckStrategy} is * {@link org.mapstruct.NullValueCheckStrategy#ALWAYS}. It is also done in * {@link ExistingInstanceSetterWrapperForCollectionsAndMaps} which extends * {@link SetterWrapperForCollectionsAndMapsWithNullCheck}
  • *
  • target-null-check - Done in the {@link ExistingInstanceSetterWrapperForCollectionsAndMaps}
  • *
  • local-var-null-check - Done in {@link ExistingInstanceSetterWrapperForCollectionsAndMaps}, and * {@link SetterWrapperForCollectionsAndMapsWithNullCheck}
  • *
* * A local-var-null-check is needed in the following cases: * *
    *
  • Presence check with direct assignment - We need a null check before setting, because we use the copy * constructor
  • *
  • Presence check for existing instance mapping - We need the null check because we call addAll / putAll.
  • *
  • No Presence check and direct assignment - We use the copy constructor
  • *
  • No Presence check and {@link org.mapstruct.NullValueCheckStrategy#ALWAYS} - the user requested one
  • *
* * @author Filip Hrisafov */ public class CollectionAssignmentBuilder { private MappingBuilderContext ctx; private Method method; private Accessor targetReadAccessor; private Type targetType; private String targetPropertyName; private AccessorType targetAccessorType; private Assignment assignment; private SourceRHS sourceRHS; private NullValueCheckStrategyGem nvcs; private NullValuePropertyMappingStrategyGem nvpms; public CollectionAssignmentBuilder mappingBuilderContext(MappingBuilderContext ctx) { this.ctx = ctx; return this; } public CollectionAssignmentBuilder method(Method method) { this.method = method; return this; } public CollectionAssignmentBuilder targetReadAccessor(Accessor targetReadAccessor) { this.targetReadAccessor = targetReadAccessor; return this; } public CollectionAssignmentBuilder targetType(Type targetType) { this.targetType = targetType; return this; } public CollectionAssignmentBuilder targetPropertyName(String targetPropertyName) { this.targetPropertyName = targetPropertyName; return this; } public CollectionAssignmentBuilder targetAccessorType(AccessorType targetAccessorType) { this.targetAccessorType = targetAccessorType; return this; } /** * @param assignment the assignment that needs to be invoked * * @return this builder for chaining */ public CollectionAssignmentBuilder assignment(Assignment assignment) { this.assignment = assignment; return this; } /** * @param sourceRHS the source right hand side for getting the property for mapping * * @return this builder for chaining */ public CollectionAssignmentBuilder rightHandSide(SourceRHS sourceRHS) { this.sourceRHS = sourceRHS; return this; } public CollectionAssignmentBuilder nullValueCheckStrategy( NullValueCheckStrategyGem nvcs ) { this.nvcs = nvcs; return this; } public CollectionAssignmentBuilder nullValuePropertyMappingStrategy( NullValuePropertyMappingStrategyGem nvpms ) { this.nvpms = nvpms; return this; } public Assignment build() { Assignment result = assignment; CollectionMappingStrategyGem cms = method.getOptions().getMapper().getCollectionMappingStrategy(); boolean targetImmutable = cms == CollectionMappingStrategyGem.TARGET_IMMUTABLE || targetReadAccessor == null; if ( targetAccessorType == AccessorType.SETTER || targetAccessorType.isFieldAssignment() ) { if ( result.isCallingUpdateMethod() && !targetImmutable ) { // call to an update method if ( targetReadAccessor == null ) { ctx.getMessager().printMessage( method.getExecutable(), Message.PROPERTYMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE, targetPropertyName ); } Assignment factoryMethod = ObjectFactoryMethodResolver .getFactoryMethod( method, targetType, SelectionParameters.forSourceRHS( sourceRHS ), ctx ); result = new UpdateWrapper( result, method.getThrownTypes(), factoryMethod, targetAccessorType.isFieldAssignment(), targetType, true, nvpms == SET_TO_NULL && !targetType.isPrimitive(), nvpms == SET_TO_DEFAULT ); } else if ( method.isUpdateMethod() && !targetImmutable ) { result = new ExistingInstanceSetterWrapperForCollectionsAndMaps( result, method.getThrownTypes(), targetType, nvcs, nvpms, ctx.getTypeFactory(), targetAccessorType.isFieldAssignment() ); } else if ( result.getType() == Assignment.AssignmentType.DIRECT || nvcs == NullValueCheckStrategyGem.ALWAYS ) { result = new SetterWrapperForCollectionsAndMapsWithNullCheck( result, method.getThrownTypes(), targetType, ctx.getTypeFactory(), targetAccessorType.isFieldAssignment() ); } else { //TODO init default value // target accessor is setter, so wrap the setter in setter map/ collection handling result = new SetterWrapperForCollectionsAndMaps( result, method.getThrownTypes(), targetType, targetAccessorType.isFieldAssignment() ); } } else { if ( targetImmutable ) { ctx.getMessager().printMessage( method.getExecutable(), Message.PROPERTYMAPPING_NO_WRITE_ACCESSOR_FOR_TARGET_TYPE, targetPropertyName ); } // target accessor is getter, so wrap the setter in getter map/ collection handling result = new GetterWrapperForCollectionsAndMaps( result, method.getThrownTypes(), targetType, targetAccessorType.isFieldAssignment() ); } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy