![JAR search and dependency download from the Maven repository](/logo.png)
org.mapstruct.ap.internal.model.CollectionAssignmentBuilder Maven / Gradle / Ivy
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.internal.model;
import org.mapstruct.ap.internal.model.assignment.Assignment;
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.Type;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.accessor.Accessor;
/**
* 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 PropertyMapping.TargetWriteAccessorType targetAccessorType;
private Assignment rhs;
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(PropertyMapping.TargetWriteAccessorType targetAccessorType) {
this.targetAccessorType = targetAccessorType;
return this;
}
public CollectionAssignmentBuilder rightHandSide(Assignment rhs) {
this.rhs = rhs;
return this;
}
public Assignment build() {
Assignment result = rhs;
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
boolean targetImmutable = cms == CollectionMappingStrategyPrism.TARGET_IMMUTABLE;
if ( targetAccessorType == PropertyMapping.TargetWriteAccessorType.SETTER ||
targetAccessorType == PropertyMapping.TargetWriteAccessorType.FIELD ) {
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 = ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
result = new UpdateWrapper(
result,
method.getThrownTypes(),
factoryMethod,
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType ),
targetType,
true
);
}
else if ( method.isUpdateMethod() && !targetImmutable ) {
result = new ExistingInstanceSetterWrapperForCollectionsAndMaps(
result,
method.getThrownTypes(),
targetType,
method.getMapperConfiguration().getNullValueCheckStrategy(),
ctx.getTypeFactory(),
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType )
);
}
else if ( result.getType() == Assignment.AssignmentType.DIRECT ||
method.getMapperConfiguration().getNullValueCheckStrategy() == NullValueCheckStrategyPrism.ALWAYS ) {
result = new SetterWrapperForCollectionsAndMapsWithNullCheck(
result,
method.getThrownTypes(),
targetType,
ctx.getTypeFactory(),
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType )
);
}
else {
// target accessor is setter, so wrap the setter in setter map/ collection handling
result = new SetterWrapperForCollectionsAndMaps(
result,
method.getThrownTypes(),
targetType,
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType )
);
}
}
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,
PropertyMapping.TargetWriteAccessorType.isFieldAssignment( targetAccessorType )
);
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy