mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#634 Using DeclaredType instead of TypeElement when resolving property accessors of mapped bean types; That way accessor parameter/return types referring to type parameters of the bean will be resolved correctly
This commit is contained in:
parent
4997f3f292
commit
8a28f12999
@ -33,7 +33,7 @@ import java.util.Map.Entry;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
@ -407,8 +407,7 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
ExecutableElement sourceAccessor = getSourceAccessor( targetProperty.getKey(), candidates );
|
ExecutableElement sourceAccessor = getSourceAccessor( targetProperty.getKey(), candidates );
|
||||||
if ( sourceAccessor != null ) {
|
if ( sourceAccessor != null ) {
|
||||||
Mapping mapping = method.getSingleMappingByTargetPropertyName( targetProperty.getKey() );
|
Mapping mapping = method.getSingleMappingByTargetPropertyName( targetProperty.getKey() );
|
||||||
|
DeclaredType sourceType = (DeclaredType) sourceParameter.getType().getTypeMirror();
|
||||||
TypeElement sourceType = sourceParameter.getType().getTypeElement();
|
|
||||||
|
|
||||||
SourceReference sourceRef = new SourceReference.BuilderFromProperty()
|
SourceReference sourceRef = new SourceReference.BuilderFromProperty()
|
||||||
.sourceParameter( sourceParameter )
|
.sourceParameter( sourceParameter )
|
||||||
|
@ -30,6 +30,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.model.assignment.AdderWrapper;
|
import org.mapstruct.ap.internal.model.assignment.AdderWrapper;
|
||||||
@ -130,16 +131,19 @@ public class PropertyMapping extends ModelElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Type determineTargetType() {
|
private Type determineTargetType() {
|
||||||
|
// This is a bean mapping method, so we know the result is a declared type
|
||||||
|
DeclaredType resultType = (DeclaredType) method.getResultType().getTypeMirror();
|
||||||
|
|
||||||
switch ( targetWriteAccessorType ) {
|
switch ( targetWriteAccessorType ) {
|
||||||
case ADDER:
|
case ADDER:
|
||||||
case SETTER:
|
case SETTER:
|
||||||
return ctx.getTypeFactory()
|
return ctx.getTypeFactory()
|
||||||
.getSingleParameter( method.getResultType().getTypeElement(), targetWriteAccessor )
|
.getSingleParameter( resultType, targetWriteAccessor )
|
||||||
.getType();
|
.getType();
|
||||||
case GETTER:
|
case GETTER:
|
||||||
default:
|
default:
|
||||||
return ctx.getTypeFactory()
|
return ctx.getTypeFactory()
|
||||||
.getReturnType( method.getResultType().getTypeElement(), targetWriteAccessor );
|
.getReturnType( resultType, targetWriteAccessor );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ import javax.lang.model.element.Modifier;
|
|||||||
import javax.lang.model.element.Name;
|
import javax.lang.model.element.Name;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.element.VariableElement;
|
import javax.lang.model.element.VariableElement;
|
||||||
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.type.WildcardType;
|
import javax.lang.model.type.WildcardType;
|
||||||
@ -396,7 +397,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
// first check if there's a setter method.
|
// first check if there's a setter method.
|
||||||
ExecutableElement adderMethod = null;
|
ExecutableElement adderMethod = null;
|
||||||
if ( Executables.isSetterMethod( candidate ) ) {
|
if ( Executables.isSetterMethod( candidate ) ) {
|
||||||
Type targetType = typeFactory.getSingleParameter( typeElement, candidate ).getType();
|
Type targetType = typeFactory.getSingleParameter( (DeclaredType) typeMirror, candidate ).getType();
|
||||||
// ok, the current accessor is a setter. So now the strategy determines what to use
|
// ok, the current accessor is a setter. So now the strategy determines what to use
|
||||||
if ( cmStrategy == CollectionMappingStrategyPrism.ADDER_PREFERRED ) {
|
if ( cmStrategy == CollectionMappingStrategyPrism.ADDER_PREFERRED ) {
|
||||||
adderMethod = getAdderForType( targetType, targetPropertyName );
|
adderMethod = getAdderForType( targetType, targetPropertyName );
|
||||||
@ -405,7 +406,9 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
else if ( Executables.isGetterMethod( candidate ) ) {
|
else if ( Executables.isGetterMethod( candidate ) ) {
|
||||||
// the current accessor is a getter (no setter available). But still, an add method is according
|
// the current accessor is a getter (no setter available). But still, an add method is according
|
||||||
// to the above strategy (SETTER_PREFERRED || ADDER_PREFERRED) preferred over the getter.
|
// to the above strategy (SETTER_PREFERRED || ADDER_PREFERRED) preferred over the getter.
|
||||||
Type targetType = typeFactory.getReturnType( typeFactory.getMethodType( typeElement, candidate ) );
|
Type targetType = typeFactory.getReturnType(
|
||||||
|
typeFactory.getMethodType( (DeclaredType) typeMirror, candidate )
|
||||||
|
);
|
||||||
adderMethod = getAdderForType( targetType, targetPropertyName );
|
adderMethod = getAdderForType( targetType, targetPropertyName );
|
||||||
}
|
}
|
||||||
if ( adderMethod != null ) {
|
if ( adderMethod != null ) {
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.internal.model.common;
|
package org.mapstruct.ap.internal.model.common;
|
||||||
|
|
||||||
import static org.mapstruct.ap.internal.util.workarounds.SpecificCompilerWorkarounds.replaceTypeElementIfNecessary;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -256,13 +254,12 @@ public class TypeFactory {
|
|||||||
* @param method the method
|
* @param method the method
|
||||||
* @return the ExecutableType representing the method as part of usedMapper
|
* @return the ExecutableType representing the method as part of usedMapper
|
||||||
*/
|
*/
|
||||||
public ExecutableType getMethodType(TypeElement includingType, ExecutableElement method) {
|
public ExecutableType getMethodType(DeclaredType includingType, ExecutableElement method) {
|
||||||
DeclaredType asType = (DeclaredType) replaceTypeElementIfNecessary( elementUtils, includingType ).asType();
|
TypeMirror asMemberOf = typeUtils.asMemberOf( includingType, method );
|
||||||
TypeMirror asMemberOf = typeUtils.asMemberOf( asType, method );
|
|
||||||
return (ExecutableType) asMemberOf;
|
return (ExecutableType) asMemberOf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameter getSingleParameter(TypeElement includingType, ExecutableElement method) {
|
public Parameter getSingleParameter(DeclaredType includingType, ExecutableElement method) {
|
||||||
List<? extends VariableElement> parameters = method.getParameters();
|
List<? extends VariableElement> parameters = method.getParameters();
|
||||||
|
|
||||||
if ( parameters.size() != 1 ) {
|
if ( parameters.size() != 1 ) {
|
||||||
@ -273,7 +270,7 @@ public class TypeFactory {
|
|||||||
return Collections.first( getParameters( includingType, method ) );
|
return Collections.first( getParameters( includingType, method ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Parameter> getParameters(TypeElement includingType, ExecutableElement method) {
|
public List<Parameter> getParameters(DeclaredType includingType, ExecutableElement method) {
|
||||||
return getParameters( getMethodType( includingType, method ), method );
|
return getParameters( getMethodType( includingType, method ), method );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +296,7 @@ public class TypeFactory {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getReturnType(TypeElement includingType, ExecutableElement method) {
|
public Type getReturnType(DeclaredType includingType, ExecutableElement method) {
|
||||||
return getReturnType( getMethodType( includingType, method ) );
|
return getReturnType( getMethodType( includingType, method ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +304,7 @@ public class TypeFactory {
|
|||||||
return getType( method.getReturnType() );
|
return getType( method.getReturnType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Type> getThrownTypes(TypeElement includingType, ExecutableElement method) {
|
public List<Type> getThrownTypes(DeclaredType includingType, ExecutableElement method) {
|
||||||
return getThrownTypes( getMethodType( includingType, method ) );
|
return getThrownTypes( getMethodType( includingType, method ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
import javax.lang.model.type.DeclaredType;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||||
import org.mapstruct.ap.internal.model.common.Type;
|
import org.mapstruct.ap.internal.model.common.Type;
|
||||||
@ -176,7 +177,9 @@ public class SourceReference {
|
|||||||
Map<String, ExecutableElement> sourceReadAccessors = newType.getPropertyReadAccessors();
|
Map<String, ExecutableElement> sourceReadAccessors = newType.getPropertyReadAccessors();
|
||||||
for ( Map.Entry<String, ExecutableElement> getter : sourceReadAccessors.entrySet() ) {
|
for ( Map.Entry<String, ExecutableElement> getter : sourceReadAccessors.entrySet() ) {
|
||||||
if ( getter.getKey().equals( entryName ) ) {
|
if ( getter.getKey().equals( entryName ) ) {
|
||||||
newType = typeFactory.getReturnType( newType.getTypeElement(), getter.getValue() );
|
newType = typeFactory.getReturnType(
|
||||||
|
(DeclaredType) newType.getTypeMirror(), getter.getValue()
|
||||||
|
);
|
||||||
sourceEntries.add( new PropertyEntry( entryName, getter.getValue(), newType ) );
|
sourceEntries.add( new PropertyEntry( entryName, getter.getValue(), newType ) );
|
||||||
matchFound = true;
|
matchFound = true;
|
||||||
break;
|
break;
|
||||||
|
@ -32,7 +32,6 @@ import javax.lang.model.element.TypeElement;
|
|||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.ExecutableType;
|
import javax.lang.model.type.ExecutableType;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
|
||||||
@ -86,8 +85,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
mapperConfig.getAnnotationMirror() );
|
mapperConfig.getAnnotationMirror() );
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SourceMethod> prototypeMethods =
|
List<SourceMethod> prototypeMethods = retrievePrototypeMethods( mapperConfig );
|
||||||
retrievePrototypeMethods( mapperConfig.getMapperConfigMirror(), mapperConfig );
|
|
||||||
return retrieveMethods( mapperTypeElement, mapperTypeElement, mapperConfig, prototypeMethods );
|
return retrieveMethods( mapperTypeElement, mapperTypeElement, mapperConfig, prototypeMethods );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,16 +94,16 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SourceMethod> retrievePrototypeMethods(TypeMirror typeMirror, MapperConfiguration mapperConfig ) {
|
private List<SourceMethod> retrievePrototypeMethods(MapperConfiguration mapperConfig ) {
|
||||||
if ( typeMirror == null || typeMirror.getKind() == TypeKind.VOID ) {
|
if ( mapperConfig.config() == null ) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeElement typeElement = asTypeElement( typeMirror );
|
TypeElement typeElement = asTypeElement( mapperConfig.config() );
|
||||||
List<SourceMethod> methods = new ArrayList<SourceMethod>();
|
List<SourceMethod> methods = new ArrayList<SourceMethod>();
|
||||||
for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, typeElement ) ) {
|
for ( ExecutableElement executable : getAllEnclosedExecutableElements( elementUtils, typeElement ) ) {
|
||||||
|
|
||||||
ExecutableType methodType = typeFactory.getMethodType( typeElement, executable );
|
ExecutableType methodType = typeFactory.getMethodType( mapperConfig.config(), executable );
|
||||||
List<Parameter> parameters = typeFactory.getParameters( methodType, executable );
|
List<Parameter> parameters = typeFactory.getParameters( methodType, executable );
|
||||||
boolean containsTargetTypeParameter = SourceMethod.containsTargetTypeParameter( parameters );
|
boolean containsTargetTypeParameter = SourceMethod.containsTargetTypeParameter( parameters );
|
||||||
|
|
||||||
@ -158,7 +156,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
|
|
||||||
//Add all methods of used mappers in order to reference them in the aggregated model
|
//Add all methods of used mappers in order to reference them in the aggregated model
|
||||||
if ( usedMapper.equals( mapperToImplement ) ) {
|
if ( usedMapper.equals( mapperToImplement ) ) {
|
||||||
for ( TypeMirror mapper : mapperConfig.uses() ) {
|
for ( DeclaredType mapper : mapperConfig.uses() ) {
|
||||||
methods.addAll( retrieveMethods(
|
methods.addAll( retrieveMethods(
|
||||||
asTypeElement( mapper ),
|
asTypeElement( mapper ),
|
||||||
mapperToImplement,
|
mapperToImplement,
|
||||||
@ -170,8 +168,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeElement asTypeElement(TypeMirror usedMapper) {
|
private TypeElement asTypeElement(DeclaredType type) {
|
||||||
return (TypeElement) ( (DeclaredType) usedMapper ).asElement();
|
return (TypeElement) type.asElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceMethod getMethod(TypeElement usedMapper,
|
private SourceMethod getMethod(TypeElement usedMapper,
|
||||||
@ -180,7 +178,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
MapperConfiguration mapperConfig,
|
MapperConfiguration mapperConfig,
|
||||||
List<SourceMethod> prototypeMethods) {
|
List<SourceMethod> prototypeMethods) {
|
||||||
|
|
||||||
ExecutableType methodType = typeFactory.getMethodType( usedMapper, method );
|
ExecutableType methodType = typeFactory.getMethodType( (DeclaredType) usedMapper.asType(), method );
|
||||||
List<Parameter> parameters = typeFactory.getParameters( methodType, method );
|
List<Parameter> parameters = typeFactory.getParameters( methodType, method );
|
||||||
Type returnType = typeFactory.getReturnType( methodType );
|
Type returnType = typeFactory.getReturnType( methodType );
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.internal.util;
|
package org.mapstruct.ap.internal.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -26,7 +25,6 @@ import java.util.Set;
|
|||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeKind;
|
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
|
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
|
||||||
@ -49,6 +47,7 @@ public class MapperConfiguration {
|
|||||||
|
|
||||||
private final MapperPrism mapperPrism;
|
private final MapperPrism mapperPrism;
|
||||||
private final MapperConfigPrism mapperConfigPrism;
|
private final MapperConfigPrism mapperConfigPrism;
|
||||||
|
private final DeclaredType config;
|
||||||
|
|
||||||
public static MapperConfiguration getInstanceOn(Element e) {
|
public static MapperConfiguration getInstanceOn(Element e) {
|
||||||
return new MapperConfiguration( MapperPrism.getInstanceOn( e ) );
|
return new MapperConfiguration( MapperPrism.getInstanceOn( e ) );
|
||||||
@ -56,11 +55,15 @@ public class MapperConfiguration {
|
|||||||
|
|
||||||
private MapperConfiguration(MapperPrism mapperPrism) {
|
private MapperConfiguration(MapperPrism mapperPrism) {
|
||||||
this.mapperPrism = mapperPrism;
|
this.mapperPrism = mapperPrism;
|
||||||
TypeMirror typeMirror = mapperPrism.config();
|
|
||||||
if ( typeMirror.getKind().equals( TypeKind.DECLARED ) ) {
|
if ( mapperPrism.values.config() != null ) {
|
||||||
this.mapperConfigPrism = MapperConfigPrism.getInstanceOn( ( (DeclaredType) typeMirror ).asElement() );
|
// TODO #737 Only a declared type makes sense here; Validate and raise graceful error;
|
||||||
|
// Also validate that @MapperConfig is present
|
||||||
|
this.config = (DeclaredType) mapperPrism.config();
|
||||||
|
this.mapperConfigPrism = MapperConfigPrism.getInstanceOn( config.asElement() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
this.config = null;
|
||||||
this.mapperConfigPrism = null;
|
this.mapperConfigPrism = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,12 +86,22 @@ public class MapperConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TypeMirror> uses() {
|
public Set<DeclaredType> uses() {
|
||||||
Set<TypeMirror> uses = new LinkedHashSet<TypeMirror>( mapperPrism.uses() );
|
Set<DeclaredType> uses = new LinkedHashSet<DeclaredType>();
|
||||||
if ( mapperConfigPrism != null ) {
|
|
||||||
uses.addAll( mapperConfigPrism.uses() );
|
for ( TypeMirror usedMapperType : mapperPrism.uses() ) {
|
||||||
|
// TODO #737 Only declared type make sense here; Validate and raise graceful error;
|
||||||
|
uses.add( (DeclaredType) usedMapperType );
|
||||||
}
|
}
|
||||||
return new ArrayList<TypeMirror>( uses );
|
|
||||||
|
if ( mapperConfigPrism != null ) {
|
||||||
|
for ( TypeMirror usedMapperType : mapperConfigPrism.uses() ) {
|
||||||
|
// TODO #737 Only declared type make sense here; Validate and raise graceful error;
|
||||||
|
uses.add( (DeclaredType) usedMapperType );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TypeMirror> imports() {
|
public List<TypeMirror> imports() {
|
||||||
@ -155,8 +168,8 @@ public class MapperConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeMirror getMapperConfigMirror() {
|
public DeclaredType config() {
|
||||||
return mapperPrism.config();
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.generics.container;
|
||||||
|
|
||||||
|
public class Bar {
|
||||||
|
|
||||||
|
private long value;
|
||||||
|
|
||||||
|
public Bar() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bar(long value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(long value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.generics.container;
|
||||||
|
|
||||||
|
public class Foo {
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public Foo(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.generics.container;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
Bar.class,
|
||||||
|
Foo.class,
|
||||||
|
Source.class,
|
||||||
|
Target.class,
|
||||||
|
SourceTargetMapper.class,
|
||||||
|
})
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
public class GenericContainerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IssueKey("634")
|
||||||
|
public void canMapGenericSourceTypeToGenericTargetType() {
|
||||||
|
List<Foo> items = Arrays.asList( new Foo( "42" ), new Foo( "84" ) );
|
||||||
|
Source<Foo> source = new Source<Foo>( items );
|
||||||
|
|
||||||
|
Target<Bar> target = SourceTargetMapper.INSTANCE.mapSourceToTarget( source );
|
||||||
|
|
||||||
|
assertThat( target.getContent() ).onProperty( "value" ).containsExactly( 42L, 84L );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.generics.container;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Source<T> {
|
||||||
|
|
||||||
|
private final List<T> items;
|
||||||
|
|
||||||
|
public Source(List<T> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> getContent() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.generics.container;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface SourceTargetMapper {
|
||||||
|
|
||||||
|
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
|
||||||
|
|
||||||
|
Bar mapFooToBar(Foo foo);
|
||||||
|
|
||||||
|
Target<Bar> mapSourceToTarget(Source<Foo> source);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.generics.container;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Target<T> {
|
||||||
|
|
||||||
|
private List<T> content;
|
||||||
|
|
||||||
|
public List<T> getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(List<T> content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user