#527 selection and forging of iterable - and map mapping methods with wildcards, extends for source, super for target

This commit is contained in:
sjaakd 2015-04-05 21:59:06 +02:00
parent a1baed46b0
commit 2ece25a086
31 changed files with 975 additions and 26 deletions

View File

@ -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;
}

View File

@ -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<? extends YetAnotherType> extendsBound;
public int getFoo() {
return foo;
@ -83,4 +86,13 @@ public class Source {
public void setForNested(SomeType forNested) {
this.forNested = forNested;
}
public List<? extends YetAnotherType> getExtendsBound() {
return extendsBound;
}
public void setExtendsBound(List<? extends YetAnotherType> extendsBound) {
this.extendsBound = extendsBound;
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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<String> extendsBound;
public Long getFoo() {
return foo;
@ -85,4 +87,12 @@ public class Target {
public void setFromNested(String fromNested) {
this.fromNested = fromNested;
}
public List<String> getExtendsBound() {
return extendsBound;
}
public void setExtendsBound(List<String> extendsBound) {
this.extendsBound = extendsBound;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -113,8 +113,8 @@ public class MapMappingMethod extends MappingMethod {
List<Type> 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,

View File

@ -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();
}
}

View File

@ -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<Type> {
private List<ExecutableElement> adders = null;
private List<ExecutableElement> 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<Type> {
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<Type> {
}
/**
* 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<Type> {
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:
* <ol>
* <li>{@code<? extends Number>}, returns Number</li>
* <li>{@code<? super Number>}, returns Number</li>
* <li>{@code<?>}, returns Object</li>
* <li>{@code<T extends Number>, returns Number}</li>
* </ol>
* @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;
}
}

View File

@ -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<Type> getTypeParameters(TypeMirror mirror) {
private List<Type> getTypeParameters(TypeMirror mirror, boolean isImplementationType) {
if ( mirror.getKind() != TypeKind.DECLARED ) {
return java.util.Collections.emptyList();
}
@ -355,7 +355,12 @@ public class TypeFactory {
List<Type> typeParameters = new ArrayList<Type>( 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(),

View File

@ -410,6 +410,29 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
return false;
}
for ( Type typeParameter : resultType.getTypeParameters() ) {
if ( typeParameter.isTypeVar() ) {
messager.printMessage( method, Message.RETRIEVAL_TYPE_VAR_RESULT );
return false;
}
if ( typeParameter.isWildCardExtendsBound() ) {
messager.printMessage( method, Message.RETRIEVAL_WILDCARD_EXTENDS_BOUND_RESULT );
return false;
}
}
for ( Type typeParameter : parameterType.getTypeParameters() ) {
if ( typeParameter.isWildCardSuperBound() ) {
messager.printMessage( method, Message.RETRIEVAL_WILDCARD_SUPER_BOUND_SOURCE );
return false;
}
if ( typeParameter.isTypeVar() ) {
messager.printMessage( method, Message.RETRIEVAL_TYPE_VAR_SOURCE );
return false;
}
}
return true;
}

View File

@ -88,6 +88,12 @@ public enum Message {
RETRIEVAL_PRIMITIVE_RETURN( "Can't generate mapping method with primitive return type." ),
RETRIEVAL_ENUM_TO_NON_ENUM( "Can't generate mapping method from enum type to non-enum type." ),
RETRIEVAL_NON_ENUM_TO_ENUM( "Can't generate mapping method from non-enum type to enum type." ),
RETRIEVAL_TYPE_VAR_SOURCE( "Can't generate mapping method for a generic type variable source." ),
RETRIEVAL_TYPE_VAR_RESULT( "Can't generate mapping method for a generic type variable target." ),
RETRIEVAL_WILDCARD_SUPER_BOUND_SOURCE( "Can't generate mapping method for a wildcard super bound source." ),
RETRIEVAL_WILDCARD_EXTENDS_BOUND_RESULT( "Can't generate mapping method for a wildcard extends bound result." ),
INHERITCONFIGURATION_BOTH( "Method cannot be annotated with both a @InheritConfiguration and @InheritInverseConfiguration." ),
INHERITINVERSECONFIGURATION_DUPLICATES( "Several matching inverse methods exist: %s(). Specify a name explicitly." ),

View File

@ -44,11 +44,11 @@
<#-- key -->
<@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">

View File

@ -32,4 +32,5 @@ public class Source {
public void setFooSet(Set<String> fooSet) {
this.fooSet = fooSet;
}
}

View File

@ -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<? extends BigDecimal> value) {
return value != null ? value.getValue() : null;
}
JAXBElement<? super BigDecimal> map(BigDecimal value) {
return new JAXBElement( new QName( "test" ), BigDecimal.class, value );
}
}

View File

@ -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<? super BigDecimal> description;
public BigDecimal getContent() {
return content;
}
public void setContent(BigDecimal content) {
this.content = content;
}
public JAXBElement<? super BigDecimal> getDescription() {
return description;
}
public void setDescription(JAXBElement<? super BigDecimal> description) {
this.description = description;
}
}

View File

@ -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<? extends Idea> elements;
Map<? extends Idea, ? extends Idea> entries;
public List<? extends Idea> getElements() {
return elements;
}
public void setElements(List<? extends Idea> elements) {
this.elements = elements;
}
public Map<? extends Idea, ? extends Idea> getEntries() {
return entries;
}
public void setEntries(Map<? extends Idea, ? extends Idea> entries) {
this.entries = entries;
}
}

View File

@ -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);
}

View File

@ -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<? extends BigDecimal> content;
private BigDecimal description;
public JAXBElement<? extends BigDecimal> getContent() {
return content;
}
public void setContent(JAXBElement<? extends BigDecimal> content) {
this.content = content;
}
public BigDecimal getDescription() {
return description;
}
public void setDescription(BigDecimal description) {
this.description = description;
}
}

View File

@ -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 {
}

View File

@ -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<? extends BigDecimal> map(List<BigDecimal> in);
}

View File

@ -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<BigDecimal> map(List<? super BigDecimal> in);
}

View File

@ -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<T extends BigDecimal> {
List<BigDecimal> map(List<T> in);
}

View File

@ -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 {
<T extends BigDecimal> List<T> map(List<BigDecimal> in);
}

View File

@ -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 {
}

View File

@ -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<Idea> elements;
Map<Idea, Idea> entries;
public List<Idea> getElements() {
return elements;
}
public void setElements(List<Idea> elements) {
this.elements = elements;
}
public Map<Idea, Idea> getEntries() {
return entries;
}
public void setEntries(Map<Idea, Idea> entries) {
this.entries = entries;
}
}

View File

@ -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);
}

View File

@ -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<? super Plan> elements;
private Map<? super Plan, ? super Plan> entries;
public List<? super Plan> getElements() {
return elements;
}
public void setElements(List<? super Plan> elements) {
this.elements = elements;
}
public Map<? super Plan, ? super Plan> getEntries() {
return entries;
}
public void setEntries(Map<? super Plan, ? super Plan> entries) {
this.entries = entries;
}
}

View File

@ -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<Plan> elements;
private Map<Plan, Plan> entries;
public List<Plan> getElements() {
return elements;
}
public void setElements(List<Plan> elements) {
this.elements = elements;
}
public Map<Plan, Plan> getEntries() {
return entries;
}
public void setEntries(Map<Plan, Plan> entries) {
this.entries = entries;
}
}

View File

@ -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 );
}
}