diff --git a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java index ed584658f..eb99589b1 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/BeanMappingMethod.java @@ -20,6 +20,7 @@ package org.mapstruct.ap.model; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -74,6 +75,7 @@ public class BeanMappingMethod extends MappingMethod { private List qualifiers; private NullValueMappingStrategyPrism nullValueMappingStrategy; private TypeMirror resultTypeMirror; + private final Collection existingVariableNames = new HashSet(); public Builder mappingContext(MappingBuilderContext mappingContext) { this.ctx = mappingContext; @@ -88,6 +90,7 @@ public class BeanMappingMethod extends MappingMethod { for ( Parameter sourceParameter : method.getSourceParameters() ) { unprocessedSourceParameters.add( sourceParameter ); } + existingVariableNames.addAll( method.getParameterNames() ); return this; } @@ -148,7 +151,14 @@ public class BeanMappingMethod extends MappingMethod { } } - return new BeanMappingMethod( method, propertyMappings, factoryMethod, mapNullToDefault, resultType ); + return new BeanMappingMethod( + method, + propertyMappings, + factoryMethod, + mapNullToDefault, + resultType, + existingVariableNames + ); } /** @@ -210,6 +220,7 @@ public class BeanMappingMethod extends MappingMethod { .qualifiers( mapping.getQualifiers() ) .resultType( mapping.getResultType() ) .dateFormat( mapping.getDateFormat() ) + .existingVariableNames( existingVariableNames ) .build(); handledTargets.add( mapping.getTargetName() ); unprocessedSourceParameters.remove( sourceRef.getParameter() ); @@ -231,6 +242,7 @@ public class BeanMappingMethod extends MappingMethod { .dateFormat( mapping.getDateFormat() ) .qualifiers( mapping.getQualifiers() ) .resultType( mapping.getResultType() ) + .existingVariableNames( existingVariableNames ) .build(); handledTargets.add( mapping.getTargetName() ); } @@ -243,6 +255,7 @@ public class BeanMappingMethod extends MappingMethod { .souceMethod( method ) .javaExpression( mapping.getJavaExpression() ) .targetAccessor( targetProperty ) + .existingVariableNames( existingVariableNames ) .build(); handledTargets.add( mapping.getTargetName() ); } @@ -319,6 +332,7 @@ public class BeanMappingMethod extends MappingMethod { .qualifiers( mapping != null ? mapping.getQualifiers() : null ) .resultType( mapping != null ? mapping.getResultType() : null ) .dateFormat( mapping != null ? mapping.getDateFormat() : null ) + .existingVariableNames( existingVariableNames ) .build(); unprocessedSourceParameters.remove( sourceParameter ); @@ -379,6 +393,7 @@ public class BeanMappingMethod extends MappingMethod { .qualifiers( mapping != null ? mapping.getQualifiers() : null ) .resultType( mapping != null ? mapping.getResultType() : null ) .dateFormat( mapping != null ? mapping.getDateFormat() : null ) + .existingVariableNames( existingVariableNames ) .build(); propertyMappings.add( propertyMapping ); @@ -466,8 +481,9 @@ public class BeanMappingMethod extends MappingMethod { List propertyMappings, MethodReference factoryMethod, boolean mapNullToDefault, - Type resultType ) { - super( method ); + Type resultType, + Collection existingVariableNames ) { + super( method, existingVariableNames ); this.propertyMappings = propertyMappings; // intialize constant mappings as all mappings, but take out the ones that can be contributed to a diff --git a/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java index fcab698d0..2e01439f8 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java @@ -19,6 +19,7 @@ package org.mapstruct.ap.model; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -45,8 +46,16 @@ public abstract class MappingMethod extends ModelElement { private final Accessibility accessibility; private final List thrownTypes; private final boolean isStatic; + private final String resultName; - protected MappingMethod(Method method) { + /** + * constructor to be overloaded when local variable names are required prior to calling this constructor. (e.g. + * for property mappings). It is supposed to be initialized with at least the parameter names. + * + * @param method + * @param existingVariableNames + */ + protected MappingMethod(Method method, Collection existingVariableNames ) { this.name = method.getName(); this.parameters = method.getParameters(); this.returnType = method.getReturnType(); @@ -54,6 +63,34 @@ public abstract class MappingMethod extends ModelElement { this.accessibility = method.getAccessibility(); this.thrownTypes = method.getThrownTypes(); this.isStatic = method.isStatic(); + this.resultName = initResultName( existingVariableNames ); + } + + protected MappingMethod(Method method ) { + this.name = method.getName(); + this.parameters = method.getParameters(); + this.returnType = method.getReturnType(); + this.targetParameter = method.getMappingTargetParameter(); + this.accessibility = method.getAccessibility(); + this.thrownTypes = method.getThrownTypes(); + this.isStatic = method.isStatic(); + this.resultName = initResultName( method.getParameterNames() ); + } + + private String initResultName(Collection existingVarNames) { + if ( targetParameter != null ) { + return targetParameter.getName(); + } + else if ( getResultType().isArrayType() ) { + String name = getSaveVariableName( getResultType().getComponentType().getName() + "Tmp", existingVarNames ); + existingVarNames.add( name ); + return name; + } + else { + String name = getSaveVariableName( getResultType().getName(), existingVarNames ); + existingVarNames.add( name ); + return name; + } } public String getName() { @@ -81,15 +118,7 @@ public abstract class MappingMethod extends ModelElement { } public String getResultName() { - if ( targetParameter != null ) { - return targetParameter.getName(); - } - else if ( getResultType().isArrayType() ) { - return getSaveVariableName( getResultType().getComponentType().getName() + "Tmp", getParameterNames() ); - } - else { - return getSaveVariableName( getResultType().getName(), getParameterNames() ); - } + return resultName; } public Type getReturnType() { @@ -139,4 +168,6 @@ public abstract class MappingMethod extends ModelElement { public String toString() { return returnType + " " + getName() + "(" + join( parameters, ", " ) + ")"; } + + } diff --git a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java index 27a64d324..7646e6146 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java @@ -19,6 +19,7 @@ package org.mapstruct.ap.model; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Set; import javax.lang.model.element.ExecutableElement; @@ -27,10 +28,10 @@ import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.model.assignment.AdderWrapper; import org.mapstruct.ap.model.assignment.ArrayCopyWrapper; import org.mapstruct.ap.model.assignment.Assignment; -import org.mapstruct.ap.model.assignment.GetterCollectionOrMapWrapper; +import org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps; import org.mapstruct.ap.model.assignment.NewCollectionOrMapWrapper; import org.mapstruct.ap.model.assignment.NullCheckWrapper; -import org.mapstruct.ap.model.assignment.SetterCollectionOrMapWrapper; +import org.mapstruct.ap.model.assignment.SetterWrapperForCollectionsAndMaps; import org.mapstruct.ap.model.assignment.SetterWrapper; import org.mapstruct.ap.model.common.ModelElement; import org.mapstruct.ap.model.common.Parameter; @@ -72,6 +73,7 @@ public class PropertyMapping extends ModelElement { private List qualifiers; private TypeMirror resultType; private SourceReference sourceReference; + private Collection existingVariableNames; public PropertyMappingBuilder mappingContext(MappingBuilderContext mappingContext) { this.ctx = mappingContext; @@ -113,6 +115,11 @@ public class PropertyMapping extends ModelElement { return this; } + public PropertyMappingBuilder existingVariableNames(Collection existingVariableNames) { + this.existingVariableNames = existingVariableNames; + return this; + } + private enum TargetAccessorType { GETTER, @@ -245,18 +252,20 @@ public class PropertyMapping extends ModelElement { result = new SetterWrapper( result, method.getThrownTypes() ); // target accessor is setter, so wrap the setter in setter map/ collection handling - result = new SetterCollectionOrMapWrapper( + result = new SetterWrapperForCollectionsAndMaps( result, targetAccessor.getSimpleName().toString(), newCollectionOrMap ); } else { - // wrap the assignment in the setter method - result = new SetterWrapper( result, method.getThrownTypes() ); - // target accessor is getter, so wrap the setter in getter map/ collection handling - result = new GetterCollectionOrMapWrapper( result ); + result = new GetterWrapperForCollectionsAndMaps( + result, + method.getThrownTypes(), + targetType, + existingVariableNames + ); } // For collections and maps include a null check, when the assignment type is DIRECT. @@ -453,6 +462,7 @@ public class PropertyMapping extends ModelElement { private String dateFormat; private List qualifiers; private TypeMirror resultType; + private Collection existingVariableNames; public ConstantMappingBuilder mappingContext(MappingBuilderContext mappingContext) { this.ctx = mappingContext; @@ -489,6 +499,11 @@ public class PropertyMapping extends ModelElement { return this; } + public ConstantMappingBuilder existingVariableNames(Collection existingVariableNames) { + this.existingVariableNames = existingVariableNames; + return this; + } + public PropertyMapping build() { // source @@ -520,12 +535,18 @@ public class PropertyMapping extends ModelElement { if ( assignment != null ) { - // target accessor is setter, so decorate assignment as setter - assignment = new SetterWrapper( assignment, method.getThrownTypes() ); - - // wrap when dealing with getter only on target - if ( Executables.isGetterMethod( targetAccessor ) ) { - assignment = new GetterCollectionOrMapWrapper( assignment ); + if ( Executables.isSetterMethod( targetAccessor ) ) { + // target accessor is setter, so decorate assignment as setter + assignment = new SetterWrapper( assignment, method.getThrownTypes() ); + } + else { + // wrap when dealing with getter only on target + assignment = new GetterWrapperForCollectionsAndMaps( + assignment, + method.getThrownTypes(), + targetType, + existingVariableNames + ); } } else { @@ -548,6 +569,7 @@ public class PropertyMapping extends ModelElement { private SourceMethod method; private String javaExpression; private ExecutableElement targetAccessor; + private Collection existingVariableNames; public JavaExpressionMappingBuilder mappingContext(MappingBuilderContext mappingContext) { this.ctx = mappingContext; @@ -569,20 +591,30 @@ public class PropertyMapping extends ModelElement { return this; } + public JavaExpressionMappingBuilder existingVariableNames(Collection existingVariableNames) { + this.existingVariableNames = existingVariableNames; + return this; + } + public PropertyMapping build() { Assignment assignment = AssignmentFactory.createDirect( javaExpression ); - assignment = new SetterWrapper( assignment, method.getThrownTypes() ); Type targetType; if ( Executables.isSetterMethod( targetAccessor ) ) { + // setter, so wrap in setter + assignment = new SetterWrapper( assignment, method.getThrownTypes() ); targetType = ctx.getTypeFactory().getSingleParameter( targetAccessor ).getType(); } else { targetType = ctx.getTypeFactory().getReturnType( targetAccessor ); - // target accessor is getter, so wrap the setter in getter map/ collection handling - assignment = new GetterCollectionOrMapWrapper( assignment ); + assignment = new GetterWrapperForCollectionsAndMaps( + assignment, + method.getThrownTypes(), + targetType, + existingVariableNames + ); } return new PropertyMapping( targetAccessor.getSimpleName().toString(), targetType, assignment ); diff --git a/processor/src/main/java/org/mapstruct/ap/model/assignment/GetterWrapperForCollectionsAndMaps.java b/processor/src/main/java/org/mapstruct/ap/model/assignment/GetterWrapperForCollectionsAndMaps.java new file mode 100644 index 000000000..47d9c7f64 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/model/assignment/GetterWrapperForCollectionsAndMaps.java @@ -0,0 +1,84 @@ +/** + * Copyright 2012-2015 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.model.assignment; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.mapstruct.ap.model.common.Type; +import org.mapstruct.ap.util.Strings; + +/** + * This wrapper handles the situation were an assignment must be done via a target getter method because there + * is no setter available. + * + * The wrapper checks if there is an collection or map initialized on the target bean (not null). If so it uses the + * addAll (for collections) or putAll (for maps). The collection / map is cleared in case of a pre-existing target + * {@link org.mapstruct.MappingTarget }before adding the source entries. The goal is that the same collection / map + * is used as target. + * + * Nothing can be added if the getter on the target returns null. + * + * @author Sjaak Derksen + */ +public class GetterWrapperForCollectionsAndMaps extends AssignmentWrapper { + + private final List exceptionTypesToExclude; + private final Type targetType; + private final String localVarName; + + + public GetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment, List exceptionTypesToExclude, + Type targetType, Collection existingVariableNames ) { + super( decoratedAssignment ); + this.exceptionTypesToExclude = exceptionTypesToExclude; + this.targetType = targetType; + this.localVarName = Strings.getSaveVariableName( "target" + targetType.getName(), existingVariableNames ); + existingVariableNames.add( localVarName ); + } + + @Override + public List getExceptionTypes() { + List parentExceptionTypes = super.getExceptionTypes(); + List result = new ArrayList( parentExceptionTypes ); + for ( Type exceptionTypeToExclude : exceptionTypesToExclude ) { + for ( Type parentExceptionType : parentExceptionTypes ) { + if ( parentExceptionType.isAssignableTo( exceptionTypeToExclude ) ) { + result.remove( parentExceptionType ); + } + } + } + return result; + } + + @Override + public Set getImportTypes() { + Set imported = new HashSet(); + imported.addAll( super.getImportTypes() ); + imported.add( targetType ); /* is a local var */ + return imported; + } + + public String getLocalVarName() { + return localVarName; + } + +} diff --git a/processor/src/main/java/org/mapstruct/ap/model/assignment/SetterCollectionOrMapWrapper.java b/processor/src/main/java/org/mapstruct/ap/model/assignment/SetterWrapperForCollectionsAndMaps.java similarity index 94% rename from processor/src/main/java/org/mapstruct/ap/model/assignment/SetterCollectionOrMapWrapper.java rename to processor/src/main/java/org/mapstruct/ap/model/assignment/SetterWrapperForCollectionsAndMaps.java index c7fe06564..a6794d96a 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/assignment/SetterCollectionOrMapWrapper.java +++ b/processor/src/main/java/org/mapstruct/ap/model/assignment/SetterWrapperForCollectionsAndMaps.java @@ -35,12 +35,12 @@ import org.mapstruct.ap.model.common.Type; * * @author Sjaak Derksen */ -public class SetterCollectionOrMapWrapper extends AssignmentWrapper { +public class SetterWrapperForCollectionsAndMaps extends AssignmentWrapper { private final String targetGetterName; private final Assignment newCollectionOrMapAssignment; - public SetterCollectionOrMapWrapper(Assignment decoratedAssignment, + public SetterWrapperForCollectionsAndMaps(Assignment decoratedAssignment, String targetSetterName, Assignment newCollectionOrMapAssignment) { super( decoratedAssignment ); diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterCollectionOrMapWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps.ftl similarity index 50% rename from processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterCollectionOrMapWrapper.ftl rename to processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps.ftl index 6d90f32e9..807dd5ae7 100644 --- a/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterCollectionOrMapWrapper.ftl +++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.GetterWrapperForCollectionsAndMaps.ftl @@ -22,19 +22,31 @@ if ( ${ext.targetBeanName}.${ext.targetAccessorName}() != null ) { <#if ext.existingInstanceMapping> ${ext.targetBeanName}.${ext.targetAccessorName}().clear(); - <#if ext.targetType.collectionType> - <@includeModel object=assignment - targetBeanName=ext.targetBeanName - raw=ext.raw - existingInstanceMapping=ext.existingInstanceMapping - targetAccessorName="${ext.targetAccessorName}().addAll" - targetType=ext.targetType/> - <#else> - <@includeModel object=assignment - targetBeanName=ext.targetBeanName - raw=ext.raw - existingInstanceMapping=ext.existingInstanceMapping - targetAccessorName="${ext.targetAccessorName}().putAll" - targetType=ext.targetType/> + <#if (exceptionTypes?size == 0) > + <@_assignmentLine/> + <#else> + try { + <@_assignmentLine/> + } + <#list exceptionTypes as exceptionType> + catch ( <@includeModel object=exceptionType/> e ) { + throw new RuntimeException( e ); + } + } +<#macro _assignmentLine> + <@includeModel object=ext.targetType/> ${localVarName} = <@_assignment/>; + if ( ${localVarName} != null ) { + ${ext.targetBeanName}.${ext.targetAccessorName}().<#if ext.targetType.collectionType>addAll<#else>putAll( ${localVarName} ); + } + +<#macro _assignment> + <@includeModel object=assignment + targetBeanName=ext.targetBeanName + raw=ext.raw + existingInstanceMapping=ext.existingInstanceMapping + targetReadAccessorName=ext.targetReadAccessorName + targetWriteAccessorName=ext.targetWriteAccessorName + targetType=ext.targetType/> + \ No newline at end of file diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterCollectionOrMapWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapperForCollectionsAndMaps.ftl similarity index 100% rename from processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterCollectionOrMapWrapper.ftl rename to processor/src/main/resources/org.mapstruct.ap.model.assignment.SetterWrapperForCollectionsAndMaps.ftl diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Issue289Mapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Issue289Mapper.java new file mode 100644 index 000000000..535465b30 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Issue289Mapper.java @@ -0,0 +1,41 @@ +/** + * Copyright 2012-2015 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.test.bugs._289; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface Issue289Mapper { + + Issue289Mapper INSTANCE = Mappers.getMapper( Issue289Mapper.class ); + + TargetWithoutSetter sourceToTargetWithoutSetter(Source source); + + void sourceToTargetWithoutSetter(Source source, @MappingTarget TargetWithoutSetter target); + + TargetWithSetter sourceToTargetWithSetter(Source source); + + TargetElement sourceElementToTargetElement(SourceElement source); + + + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Issue289Test.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Issue289Test.java new file mode 100644 index 000000000..0a6d9ac1c --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Issue289Test.java @@ -0,0 +1,81 @@ +/** + * Copyright 2012-2015 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.test.bugs._289; + +import static org.fest.assertions.Assertions.assertThat; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * Reproducer for https://github.com/mapstruct/mapstruct/issues/289. + * + * @author Sjaak Derksen + */ +@IssueKey( "289" ) + @WithClasses( { + Issue289Mapper.class, + Source.class, + TargetWithoutSetter.class, + TargetWithSetter.class, + SourceElement.class, + TargetElement.class + } ) +@RunWith(AnnotationProcessorTestRunner.class) +public class Issue289Test { + + + @Test + public void shouldLeaveEmptyTargetSetWhenSourceIsNullAndGetterOnlyForCreateMethod() { + + Source source = new Source(); + source.setCollection( null ); + + TargetWithoutSetter target = Issue289Mapper.INSTANCE.sourceToTargetWithoutSetter( source ); + + assertThat( target.getCollection() ).isEmpty(); + } + + @Test + public void shouldLeaveEmptyTargetSetWhenSourceIsNullAndGetterOnlyForUpdateMethod() { + + Source source = new Source(); + source.setCollection( null ); + TargetWithoutSetter target = new TargetWithoutSetter(); + target.getCollection().add( new TargetElement() ); + + Issue289Mapper.INSTANCE.sourceToTargetWithoutSetter( source, target ); + + assertThat( target.getCollection() ).isEmpty(); + } + + + @Test + public void shouldLeaveNullTargetSetWhenSourceIsNullForCreateMethod() { + + Source source = new Source(); + source.setCollection( null ); + + TargetWithSetter target = Issue289Mapper.INSTANCE.sourceToTargetWithSetter( source ); + + assertThat( target.getCollection() ).isNull(); + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/model/assignment/GetterCollectionOrMapWrapper.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Source.java similarity index 51% rename from processor/src/main/java/org/mapstruct/ap/model/assignment/GetterCollectionOrMapWrapper.java rename to processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Source.java index 5ba79a63f..72138d9fb 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/assignment/GetterCollectionOrMapWrapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/Source.java @@ -16,26 +16,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mapstruct.ap.model.assignment; +package org.mapstruct.ap.test.bugs._289; + +import java.util.Collection; /** - * This wrapper handles the situation were an assignment must be done via a target getter method because there - * is no setter available. - * - * The wrapper checks if there is an collection or map initialized on the target bean (not null). If so it uses the - * addAll (for collections) or putAll (for maps). The collection / map is cleared in case of a pre-existing target - * {@link org.mapstruct.MappingTarget }before adding the source entries. The goal is that the same collection / map - * is used as target. - * - * Nothing can be added if the getter on the target returns null. * * @author Sjaak Derksen */ -public class GetterCollectionOrMapWrapper extends AssignmentWrapper { +public class Source { + private Collection collection; - public GetterCollectionOrMapWrapper(Assignment decoratedAssignment) { - super( decoratedAssignment ); + public Collection getCollection() { + return collection; + } + + public void setCollection(Collection collection) { + this.collection = collection; } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/SourceElement.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/SourceElement.java new file mode 100644 index 000000000..7414818a0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/SourceElement.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2015 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.test.bugs._289; + +/** + * + * @author Sjaak Derksen + */ +public class SourceElement { + + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetElement.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetElement.java new file mode 100644 index 000000000..e7925a6cf --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetElement.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2015 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.test.bugs._289; + +/** + * + * @author Sjaak Derksen + */ +public class TargetElement { + + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetWithSetter.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetWithSetter.java new file mode 100644 index 000000000..7f7381910 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetWithSetter.java @@ -0,0 +1,39 @@ +/** + * Copyright 2012-2015 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.test.bugs._289; + +import java.util.Collection; + +/** + * + * @author Sjaak Derksen + */ +public class TargetWithSetter { + + private Collection collection; + + public Collection getCollection() { + return collection; + } + + public void setCollection( Collection collection ) { + this.collection = collection; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetWithoutSetter.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetWithoutSetter.java new file mode 100644 index 000000000..398488d18 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_289/TargetWithoutSetter.java @@ -0,0 +1,36 @@ +/** + * Copyright 2012-2015 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.test.bugs._289; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * + * @author Sjaak Derksen + */ +public class TargetWithoutSetter { + + private final Collection collection = new ArrayList(); + + public Collection getCollection() { + return collection; + } + +}