diff --git a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/ReferencedCustomMapper.java b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/ReferencedCustomMapper.java index 64644dbf3..ae4257028 100644 --- a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/ReferencedCustomMapper.java +++ b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/ReferencedCustomMapper.java @@ -27,6 +27,11 @@ import org.mapstruct.TargetType; * */ public class ReferencedCustomMapper { + + public String convert(YetAnotherType source){ + return source.toString(); + } + public long incrementingIntToLong(int source) { return source + 1; } diff --git a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Source.java b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Source.java index c5d9ec8db..8cf1ff9cb 100644 --- a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Source.java +++ b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Source.java @@ -18,6 +18,8 @@ */ package org.mapstruct.itest.simple; +import java.util.List; + public class Source { private int foo; @@ -27,6 +29,7 @@ public class Source { private int zip; private String someType; private SomeType forNested; + private List extendsBound; public int getFoo() { return foo; @@ -83,4 +86,13 @@ public class Source { public void setForNested(SomeType forNested) { this.forNested = forNested; } + + public List getExtendsBound() { + return extendsBound; + } + + public void setExtendsBound(List extendsBound) { + this.extendsBound = extendsBound; + } + } diff --git a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetAbstractMapper.java b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetAbstractMapper.java index 68a874ae0..5cd0624d4 100644 --- a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetAbstractMapper.java +++ b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetAbstractMapper.java @@ -35,7 +35,10 @@ public abstract class SourceTargetAbstractMapper { }) public abstract Target sourceToTarget(Source source); - @Mapping(target = "forNested", ignore = true) + @Mappings({ + @Mapping(target = "forNested", ignore = true), + @Mapping(target = "extendsBound", ignore = true) + }) public abstract Source targetToSource(Target target); protected void isNeverCalled(Source source) { diff --git a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java index cde06a908..21f609221 100644 --- a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java +++ b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java @@ -37,6 +37,9 @@ public interface SourceTargetMapper { Target sourceToTarget(Source source); @InheritInverseConfiguration - @Mapping(target = "forNested", ignore = true) + @Mappings({ + @Mapping(target = "forNested", ignore = true), + @Mapping(target = "extendsBound", ignore = true) + }) Source targetToSource(Target target); } diff --git a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Target.java b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Target.java index 4c98dd646..1e7937971 100644 --- a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Target.java +++ b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/Target.java @@ -18,6 +18,7 @@ */ package org.mapstruct.itest.simple; +import java.util.List; import org.mapstruct.itest.simple.SomeType; public class Target { @@ -29,6 +30,7 @@ public class Target { private String zip; private SomeType someType; private String fromNested; + private List extendsBound; public Long getFoo() { return foo; @@ -85,4 +87,12 @@ public class Target { public void setFromNested(String fromNested) { this.fromNested = fromNested; } + + public List getExtendsBound() { + return extendsBound; + } + + public void setExtendsBound(List extendsBound) { + this.extendsBound = extendsBound; + } } diff --git a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/YetAnotherType.java b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/YetAnotherType.java new file mode 100644 index 000000000..91bbbce83 --- /dev/null +++ b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/YetAnotherType.java @@ -0,0 +1,40 @@ +/** + * 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.itest.simple; + +/** + * @author Andreas Gudian + * + */ +public class YetAnotherType { + private String value; + + public YetAnotherType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java index e836a5fd7..a45a64f99 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java @@ -90,21 +90,18 @@ public class IterableMappingMethod extends MappingMethod { } public IterableMappingMethod build() { + + Type sourceParameterType = first( method.getSourceParameters() ).getType(); Type resultType = method.getResultType(); - Type sourceElementType = sourceParameterType.isArrayType() ? sourceParameterType.getComponentType() : - sourceParameterType.getTypeParameters().get( 0 ); - Type targetElementType = resultType.isArrayType() ? resultType.getComponentType() : - resultType.getTypeParameters().get( 0 ); - - - String elementTypeName = sourceParameterType.isArrayType() ? - sourceParameterType.getComponentType().getName() : - sourceParameterType.getTypeParameters().get( 0 ).getName(); + Type sourceElementType = sourceParameterType.isArrayType() ? sourceParameterType.getComponentType() + : first( sourceParameterType.getTypeParameters() ).getTypeBound(); + Type targetElementType = resultType.isArrayType() ? resultType.getComponentType() + : first( resultType.getTypeParameters() ).getTypeBound(); String loopVariableName = - Strings.getSaveVariableName( elementTypeName, method.getParameterNames() ); + Strings.getSaveVariableName( sourceElementType.getName(), method.getParameterNames() ); Assignment assignment = ctx.getMappingResolver().getTargetAssignment( method, @@ -230,7 +227,7 @@ public class IterableMappingMethod extends MappingMethod { return sourceParameterType.getComponentType(); } else { - return sourceParameterType.getTypeParameters().get( 0 ); + return sourceParameterType.getTypeParameters().get( 0 ).getTypeBound(); } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java index 494809c5d..3b2d7ec01 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java @@ -113,8 +113,8 @@ public class MapMappingMethod extends MappingMethod { List resultTypeParams = method.getResultType().getTypeParameters(); // find mapping method or conversion for key - Type keySourceType = sourceTypeParams.get( 0 ); - Type keyTargetType = resultTypeParams.get( 0 ); + Type keySourceType = sourceTypeParams.get( 0 ).getTypeBound(); + Type keyTargetType = resultTypeParams.get( 0 ).getTypeBound(); Assignment keyAssignment = ctx.getMappingResolver().getTargetAssignment( method, @@ -134,8 +134,8 @@ public class MapMappingMethod extends MappingMethod { } // find mapping method or conversion for value - Type valueSourceType = sourceTypeParams.get( 1 ); - Type valueTargetType = resultTypeParams.get( 1 ); + Type valueSourceType = sourceTypeParams.get( 1 ).getTypeBound(); + Type valueTargetType = resultTypeParams.get( 1 ).getTypeBound(); Assignment valueAssignment = ctx.getMappingResolver().getTargetAssignment( method, 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 3c30e6c3b..23ecc7d81 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java @@ -504,9 +504,9 @@ public class PropertyMapping extends ModelElement { private String getName(Type type) { StringBuilder builder = new StringBuilder(); for ( Type typeParam : type.getTypeParameters() ) { - builder.append( typeParam.getName().replace( "[]", "Array" ) ); + builder.append( typeParam.getIdentification() ); } - builder.append( type.getName().replace( "[]", "Array" ) ); + builder.append( type.getIdentification() ); return builder.toString(); } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java index cfa8c505b..6fdd4f083 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java @@ -37,6 +37,8 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; @@ -90,6 +92,10 @@ public class Type extends ModelElement implements Comparable { private List adders = null; private List alternativeTargetAccessors = null; + + private Type boundingBase = null; + + //CHECKSTYLE:OFF public Type(Types typeUtils, Elements elementUtils, TypeFactory typeFactory, TypeMirror typeMirror, TypeElement typeElement, @@ -222,6 +228,29 @@ public class Type extends ModelElement implements Comparable { return componentType != null; } + public boolean isTypeVar() { + return (typeMirror.getKind() == TypeKind.TYPEVAR); + } + + public boolean isWildCardSuperBound() { + boolean result = false; + if ( typeMirror.getKind() == TypeKind.WILDCARD ) { + WildcardType wildcardType = (WildcardType) typeMirror; + result = wildcardType.getSuperBound() != null; + } + return result; + } + + public boolean isWildCardExtendsBound() { + boolean result = false; + if ( typeMirror.getKind() == TypeKind.WILDCARD ) { + WildcardType wildcardType = (WildcardType) typeMirror; + result = wildcardType.getExtendsBound() != null; + } + return result; + } + + public String getFullyQualifiedName() { return qualifiedName; } @@ -608,7 +637,8 @@ public class Type extends ModelElement implements Comparable { } /** - * A valid Java expression most suitable for representing null - useful for dealing with primitives from FTL. + * @return A valid Java expression most suitable for representing null - useful for dealing with primitives + * from FTL. */ public String getNull() { if ( !isPrimitive() || isArrayType() ) { @@ -675,4 +705,60 @@ public class Type extends ModelElement implements Comparable { public String toString() { return typeMirror.toString(); } + + + /** + * + * @return an identification that can be used as part in a forged method name. + */ + public String getIdentification() { + if ( isArrayType() ) { + return componentType.getName() + "Array"; + } + else { + return getTypeBound().getName(); + } + } + + /** + * Establishes the type bound: + *
    + *
  1. {@code}, returns Number
  2. + *
  3. {@code}, returns Number
  4. + *
  5. {@code}, returns Object
  6. + *
  7. {@code, returns Number}
  8. + *
+ * @return the bound for this parameter + */ + public Type getTypeBound() { + + if ( boundingBase != null ) { + return boundingBase; + } + boundingBase = this; + if ( typeMirror.getKind() == TypeKind.WILDCARD ) { + WildcardType wildCardType = (WildcardType) typeMirror; + if ( wildCardType.getExtendsBound() != null ) { + boundingBase = typeFactory.getType( wildCardType.getExtendsBound() ); + } + else if ( wildCardType.getSuperBound() != null ) { + boundingBase = typeFactory.getType( wildCardType.getSuperBound() ); + } + else { + String wildCardName = wildCardType.toString(); + if ( "?".equals( wildCardName ) ) { + boundingBase = typeFactory.getType( Object.class ); + } + } + } + else if ( typeMirror.getKind() == TypeKind.TYPEVAR ) { + TypeVariable typeVariableType = (TypeVariable) typeMirror; + if ( typeVariableType.getUpperBound() != null ) { + boundingBase = typeFactory.getType( typeVariableType.getUpperBound() ); + } + // Lowerbounds intentionally left out: Type variables otherwise have a lower bound of NullType. + } + return boundingBase; + } + } diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java index cdaf4ac2e..8e9f69add 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java @@ -208,7 +208,7 @@ public class TypeFactory { typeUtils, elementUtils, this, mirror, typeElement, - getTypeParameters( mirror ), + getTypeParameters( mirror, false ), implementationType, componentType, packageName, @@ -346,7 +346,7 @@ public class TypeFactory { return thrownTypes; } - private List getTypeParameters(TypeMirror mirror) { + private List getTypeParameters(TypeMirror mirror, boolean isImplementationType) { if ( mirror.getKind() != TypeKind.DECLARED ) { return java.util.Collections.emptyList(); } @@ -355,7 +355,12 @@ public class TypeFactory { List typeParameters = new ArrayList( declaredType.getTypeArguments().size() ); for ( TypeMirror typeParameter : declaredType.getTypeArguments() ) { - typeParameters.add( getType( typeParameter ) ); + if ( isImplementationType ) { + typeParameters.add( getType( typeParameter ).getTypeBound() ); + } + else { + typeParameters.add( getType( typeParameter ) ); + } } return typeParameters; @@ -395,7 +400,7 @@ public class TypeFactory { declaredType.getTypeArguments().toArray( new TypeMirror[] { } ) ), implementationType.getTypeElement(), - getTypeParameters( mirror ), + getTypeParameters( mirror, true ), null, null, implementationType.getPackageName(), diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java index 7ca9ebe80..7fad882e7 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java @@ -410,6 +410,29 @@ public class MethodRetrievalProcessor implements ModelElementProcessor <@includeModel object=keyAssignment targetWriteAccessorName=keyVariableName - targetType=resultType.typeParameters[0]/> + targetType=resultType.typeParameters[0].typeBound/> <#-- value --> <@includeModel object=valueAssignment targetWriteAccessorName=valueVariableName - targetType=resultType.typeParameters[1]/> + targetType=resultType.typeParameters[1].typeBound/> ${resultName}.put( ${keyVariableName}, ${valueVariableName} ); } <#if returnType.name != "void"> diff --git a/processor/src/test/java/org/mapstruct/ap/test/bugs/_306/Source.java b/processor/src/test/java/org/mapstruct/ap/test/bugs/_306/Source.java index 372fac95a..1c0c5623a 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/bugs/_306/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/bugs/_306/Source.java @@ -32,4 +32,5 @@ public class Source { public void setFooSet(Set fooSet) { this.fooSet = fooSet; } + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/BeanMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/BeanMapper.java new file mode 100644 index 000000000..f81c2dd65 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/BeanMapper.java @@ -0,0 +1,46 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public abstract class BeanMapper { + + public static final BeanMapper STM = Mappers.getMapper( BeanMapper.class ); + + public abstract CunningPlan transformA(GoodIdea in); + + BigDecimal map(JAXBElement value) { + return value != null ? value.getValue() : null; + } + + JAXBElement map(BigDecimal value) { + return new JAXBElement( new QName( "test" ), BigDecimal.class, value ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/CunningPlan.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/CunningPlan.java new file mode 100644 index 000000000..d39ba55bc --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/CunningPlan.java @@ -0,0 +1,50 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import javax.xml.bind.JAXBElement; + +/** + * + * @author Sjaak Derksen + */ +public class CunningPlan { + + + private BigDecimal content; + private JAXBElement description; + + public BigDecimal getContent() { + return content; + } + + public void setContent(BigDecimal content) { + this.content = content; + } + + public JAXBElement getDescription() { + return description; + } + + public void setDescription(JAXBElement description) { + this.description = description; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/ExtendsBoundSource.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/ExtendsBoundSource.java new file mode 100644 index 000000000..76b10a9eb --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/ExtendsBoundSource.java @@ -0,0 +1,49 @@ +/** + * 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.collection.wildcard; + +import java.util.List; +import java.util.Map; + +/** + * + * @author Sjaak Derksen + */ +public class ExtendsBoundSource { + + private List elements; + Map entries; + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } + + public Map getEntries() { + return entries; + } + + public void setEntries(Map entries) { + this.entries = entries; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/ExtendsBoundSourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/ExtendsBoundSourceTargetMapper.java new file mode 100644 index 000000000..d2083eeb4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/ExtendsBoundSourceTargetMapper.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.collection.wildcard; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public interface ExtendsBoundSourceTargetMapper { + + ExtendsBoundSourceTargetMapper STM = Mappers.getMapper( ExtendsBoundSourceTargetMapper.class ); + + Target map(ExtendsBoundSource source); + + Plan map(Idea in); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/GoodIdea.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/GoodIdea.java new file mode 100644 index 000000000..fe5db039a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/GoodIdea.java @@ -0,0 +1,49 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import javax.xml.bind.JAXBElement; + +/** + * + * @author Sjaak Derksen + */ +public class GoodIdea { + + private JAXBElement content; + private BigDecimal description; + + public JAXBElement getContent() { + return content; + } + + public void setContent(JAXBElement content) { + this.content = content; + } + + public BigDecimal getDescription() { + return description; + } + + public void setDescription(BigDecimal description) { + this.description = description; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Idea.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Idea.java new file mode 100644 index 000000000..40f964ec2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Idea.java @@ -0,0 +1,27 @@ +/** + * 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.collection.wildcard; + +/** + * + * @author Sjaak Derksen + */ +public class Idea { + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableExtendsBoundTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableExtendsBoundTargetMapper.java new file mode 100644 index 000000000..9f84424ac --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableExtendsBoundTargetMapper.java @@ -0,0 +1,33 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import java.util.List; +import org.mapstruct.Mapper; + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public interface IterableExtendsBoundTargetMapper { + + List map(List in); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableSuperBoundSourceMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableSuperBoundSourceMapper.java new file mode 100644 index 000000000..19e32d32c --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableSuperBoundSourceMapper.java @@ -0,0 +1,33 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import java.util.List; +import org.mapstruct.Mapper; + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public interface IterableSuperBoundSourceMapper { + + List map(List in); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableTypeVarBoundMapperOnMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableTypeVarBoundMapperOnMapper.java new file mode 100644 index 000000000..ec6942e63 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableTypeVarBoundMapperOnMapper.java @@ -0,0 +1,33 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import java.util.List; +import org.mapstruct.Mapper; + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public interface IterableTypeVarBoundMapperOnMapper { + + List map(List in); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableTypeVarBoundMapperOnMethod.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableTypeVarBoundMapperOnMethod.java new file mode 100644 index 000000000..91ddf35cf --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/IterableTypeVarBoundMapperOnMethod.java @@ -0,0 +1,33 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import java.util.List; +import org.mapstruct.Mapper; + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public interface IterableTypeVarBoundMapperOnMethod { + + List map(List in); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Plan.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Plan.java new file mode 100644 index 000000000..27363d465 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Plan.java @@ -0,0 +1,27 @@ +/** + * 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.collection.wildcard; + +/** + * + * @author Sjaak Derksen + */ +public class Plan { + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Source.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Source.java new file mode 100644 index 000000000..d0c301e13 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Source.java @@ -0,0 +1,49 @@ +/** + * 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.collection.wildcard; + +import java.util.List; +import java.util.Map; + +/** + * + * @author Sjaak Derksen + */ +public class Source { + + private List elements; + Map entries; + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } + + public Map getEntries() { + return entries; + } + + public void setEntries(Map entries) { + this.entries = entries; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/SourceSuperBoundTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/SourceSuperBoundTargetMapper.java new file mode 100644 index 000000000..f76a35290 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/SourceSuperBoundTargetMapper.java @@ -0,0 +1,38 @@ +/** + * 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.collection.wildcard; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + + +/** + * + * @author Sjaak Derksen + */ +@Mapper +public interface SourceSuperBoundTargetMapper { + + SourceSuperBoundTargetMapper STM = Mappers.getMapper( SourceSuperBoundTargetMapper.class ); + + SuperBoundTarget map(Source source); + + Plan map(Idea in); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/SuperBoundTarget.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/SuperBoundTarget.java new file mode 100644 index 000000000..6cb7060ec --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/SuperBoundTarget.java @@ -0,0 +1,50 @@ +/** + * 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.collection.wildcard; + +import java.util.List; +import java.util.Map; + +/** + * + * @author Sjaak Derksen + */ +public class SuperBoundTarget { + + private List elements; + private Map entries; + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } + + public Map getEntries() { + return entries; + } + + public void setEntries(Map entries) { + this.entries = entries; + } + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Target.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Target.java new file mode 100644 index 000000000..8a30cec6c --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/Target.java @@ -0,0 +1,50 @@ +/** + * 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.collection.wildcard; + +import java.util.List; +import java.util.Map; + +/** + * + * @author Sjaak Derksen + */ +public class Target { + + private List elements; + private Map entries; + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } + + public Map getEntries() { + return entries; + } + + public void setEntries(Map entries) { + this.entries = entries; + } + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/WildCardTest.java b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/WildCardTest.java new file mode 100644 index 000000000..6eaaaa678 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/wildcard/WildCardTest.java @@ -0,0 +1,154 @@ +/** + * 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.collection.wildcard; + +import java.math.BigDecimal; +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; +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.compilation.annotation.CompilationResult; +import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic; +import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * Reproducer for https://github.com/mapstruct/mapstruct/issues/527. + * + * @author Sjaak Derksen + */ +@IssueKey("527") +@RunWith(AnnotationProcessorTestRunner.class) +public class WildCardTest { + + @Test + @WithClasses({ + ExtendsBoundSourceTargetMapper.class, + ExtendsBoundSource.class, + Target.class, + Plan.class, + Idea.class + }) + public void shouldGenerateExtendsBoundSourceForgedIterableMethod() { + + ExtendsBoundSource source = new ExtendsBoundSource(); + + Target target = ExtendsBoundSourceTargetMapper.STM.map( source ); + + assertThat( target ).isNotNull(); + assertThat( target.getElements() ).isNull(); + + } + + @Test + @WithClasses({ + SourceSuperBoundTargetMapper.class, + Source.class, + SuperBoundTarget.class, + Plan.class, + Idea.class + }) + public void shouldGenerateSuperBoundTargetForgedIterableMethod() { + + Source source = new Source(); + + SuperBoundTarget target = SourceSuperBoundTargetMapper.STM.map( source ); + + assertThat( target ).isNotNull(); + assertThat( target.getElements() ).isNull(); + + } + + @Test + @WithClasses({ IterableSuperBoundSourceMapper.class }) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = IterableSuperBoundSourceMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 32, + messageRegExp = "Can't generate mapping method for a wildcard super bound source." ) + } + ) + public void shouldFailOnSuperBoundSource() { + } + + @Test + @WithClasses({ IterableExtendsBoundTargetMapper.class }) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = IterableExtendsBoundTargetMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 32, + messageRegExp = "Can't generate mapping method for a wildcard extends bound result." ) + } + ) + public void shouldFailOnExtendsBoundTarget() { + } + + @Test + @WithClasses({ IterableTypeVarBoundMapperOnMethod.class }) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = IterableTypeVarBoundMapperOnMethod.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 32, + messageRegExp = "Can't generate mapping method for a generic type variable target." ) + } + ) + public void shouldFailOnTypeVarSource() { + } + + @Test + @WithClasses({ IterableTypeVarBoundMapperOnMapper.class }) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = IterableTypeVarBoundMapperOnMapper.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 32, + messageRegExp = "Can't generate mapping method for a generic type variable source." ) + } + ) + public void shouldFailOnTypeVarTarget() { + } + + + @Test + @WithClasses( { BeanMapper.class, GoodIdea.class, CunningPlan.class } ) + public void shouldMapBean() { + + GoodIdea aGoodIdea = new GoodIdea(); + aGoodIdea.setContent( new JAXBElement( new QName( "test" ), BigDecimal.class, BigDecimal.ONE ) ); + aGoodIdea.setDescription( BigDecimal.ZERO ); + + CunningPlan aCunningPlan = BeanMapper.STM.transformA( aGoodIdea ); + + assertThat( aCunningPlan ).isNotNull(); + assertThat( aCunningPlan.getContent() ).isEqualTo( BigDecimal.ONE ); + assertThat( aCunningPlan.getDescription() ).isNotNull(); + assertThat( aCunningPlan.getDescription().getValue() ).isEqualTo( BigDecimal.ZERO ); + } + +}