diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java index 6584f2612..be2d17d04 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java @@ -46,7 +46,6 @@ import org.mapstruct.ap.internal.model.dependency.GraphAnalyzer.GraphAnalyzerBui import org.mapstruct.ap.internal.model.source.ForgedMethod; import org.mapstruct.ap.internal.model.source.ForgedMethodHistory; import org.mapstruct.ap.internal.model.source.Mapping; -import org.mapstruct.ap.internal.model.source.MappingOptions; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.PropertyEntry; import org.mapstruct.ap.internal.model.source.SelectionParameters; @@ -298,38 +297,15 @@ public class BeanMappingMethod extends NormalTypeMappingMethod { private void handleDefinedNestedTargetMapping(Set handledTargets) { - Map optionsByNestedTarget = - method.getMappingOptions().groupByPoppedTargetReferences(); - for ( Entry entryByTP : optionsByNestedTarget.entrySet() ) { + NestedTargetPropertyMappingHolder holder = new NestedTargetPropertyMappingHolder.Builder() + .mappingContext( ctx ) + .method( method ) + .existingVariableNames( existingVariableNames ) + .build(); - Map optionsBySourceParam = entryByTP.getValue().groupBySourceParameter(); - boolean forceUpdateMethod = optionsBySourceParam.keySet().size() > 1; - for ( Entry entryByParam : optionsBySourceParam.entrySet() ) { - - SourceReference sourceRef = new SourceReference.BuilderFromProperty() - .sourceParameter( entryByParam.getKey() ) - .name( entryByTP.getKey().getName() ) - .build(); - - PropertyMapping propertyMapping = new PropertyMappingBuilder() - .mappingContext( ctx ) - .sourceMethod( method ) - .targetProperty( entryByTP.getKey() ) - .targetPropertyName( entryByTP.getKey().getName() ) - .sourceReference( sourceRef ) - .existingVariableNames( existingVariableNames ) - .dependsOn( entryByParam.getValue().collectNestedDependsOn() ) - .forgeMethodWithMappingOptions( entryByParam.getValue() ) - .forceUpdateMethod( forceUpdateMethod ) - .build(); - unprocessedSourceParameters.remove( sourceRef.getParameter() ); - - if ( propertyMapping != null ) { - propertyMappings.add( propertyMapping ); - } - } - handledTargets.add( entryByTP.getKey().getName() ); - } + unprocessedSourceParameters.removeAll( holder.getProcessedSourceParameters() ); + propertyMappings.addAll( holder.getPropertyMappings() ); + handledTargets.addAll( holder.getHandledTargets() ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/NestedTargetPropertyMappingHolder.java b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedTargetPropertyMappingHolder.java new file mode 100644 index 000000000..d2542dd4a --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedTargetPropertyMappingHolder.java @@ -0,0 +1,126 @@ +/** + * 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 java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.mapstruct.ap.internal.model.common.Parameter; +import org.mapstruct.ap.internal.model.source.MappingOptions; +import org.mapstruct.ap.internal.model.source.Method; +import org.mapstruct.ap.internal.model.source.PropertyEntry; +import org.mapstruct.ap.internal.model.source.SourceReference; + +/** + * This is a helper class that holds the generated {@link PropertyMapping}(s) and all the information associated with + * it for nested target properties. + * + * @author Filip Hrisafov + */ +public class NestedTargetPropertyMappingHolder { + + private final List processedSourceParameters; + private final Set handledTargets; + private final List propertyMappings; + + public NestedTargetPropertyMappingHolder( + List processedSourceParameters, Set handledTargets, + List propertyMappings) { + this.processedSourceParameters = processedSourceParameters; + this.handledTargets = handledTargets; + this.propertyMappings = propertyMappings; + } + + public List getProcessedSourceParameters() { + return processedSourceParameters; + } + + public Set getHandledTargets() { + return handledTargets; + } + + public List getPropertyMappings() { + return propertyMappings; + } + + public static class Builder { + + private Method method; + private MappingBuilderContext mappingContext; + private Set existingVariableNames; + + public Builder method(Method method) { + this.method = method; + return this; + } + + public Builder mappingContext(MappingBuilderContext mappingContext) { + this.mappingContext = mappingContext; + return this; + } + + public Builder existingVariableNames(Set existingVariableNames) { + this.existingVariableNames = existingVariableNames; + return this; + } + + public NestedTargetPropertyMappingHolder build() { + List processedSourceParameters = new ArrayList(); + Set handledTargets = new HashSet(); + List propertyMappings = new ArrayList(); + + Map optionsByNestedTarget = + method.getMappingOptions().groupByPoppedTargetReferences(); + for ( Map.Entry entryByTP : optionsByNestedTarget.entrySet() ) { + + Map optionsBySourceParam = entryByTP.getValue().groupBySourceParameter(); + boolean forceUpdateMethod = optionsBySourceParam.keySet().size() > 1; + for ( Map.Entry entryByParam : optionsBySourceParam.entrySet() ) { + + SourceReference sourceRef = new SourceReference.BuilderFromProperty() + .sourceParameter( entryByParam.getKey() ) + .name( entryByTP.getKey().getName() ) + .build(); + + PropertyMapping propertyMapping = new PropertyMapping.PropertyMappingBuilder() + .mappingContext( mappingContext ) + .sourceMethod( method ) + .targetProperty( entryByTP.getKey() ) + .targetPropertyName( entryByTP.getKey().getName() ) + .sourceReference( sourceRef ) + .existingVariableNames( existingVariableNames ) + .dependsOn( entryByParam.getValue().collectNestedDependsOn() ) + .forgeMethodWithMappingOptions( entryByParam.getValue() ) + .forceUpdateMethod( forceUpdateMethod ) + .build(); + processedSourceParameters.add( sourceRef.getParameter() ); + + if ( propertyMapping != null ) { + propertyMappings.add( propertyMapping ); + } + } + handledTargets.add( entryByTP.getKey().getName() ); + } + return new NestedTargetPropertyMappingHolder( processedSourceParameters, handledTargets, propertyMappings ); + } + } +}