mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#44 Enabling types with more than one type parameter
This commit is contained in:
parent
7d26a3b43e
commit
ac9859c38d
@ -83,7 +83,9 @@ public class Mapper extends AbstractModelElement {
|
|||||||
|
|
||||||
addWithDependents( collection, typeToAdd.getCollectionImplementationType() );
|
addWithDependents( collection, typeToAdd.getCollectionImplementationType() );
|
||||||
addWithDependents( collection, typeToAdd.getIterableImplementationType() );
|
addWithDependents( collection, typeToAdd.getIterableImplementationType() );
|
||||||
addWithDependents( collection, typeToAdd.getElementType() );
|
for ( Type type : typeToAdd.getTypeParameters() ) {
|
||||||
|
addWithDependents( collection, type );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,6 +21,7 @@ package org.mapstruct.ap.model;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -32,7 +33,7 @@ import java.util.concurrent.ConcurrentMap;
|
|||||||
*
|
*
|
||||||
* @author Gunnar Morling
|
* @author Gunnar Morling
|
||||||
*/
|
*/
|
||||||
public class Type implements Comparable<Type> {
|
public class Type extends AbstractModelElement implements Comparable<Type> {
|
||||||
|
|
||||||
private static final Set<String> PRIMITIVE_TYPE_NAMES = new HashSet<String>(
|
private static final Set<String> PRIMITIVE_TYPE_NAMES = new HashSet<String>(
|
||||||
Arrays.asList( "boolean", "char", "byte", "short", "int", "long", "float", "double" )
|
Arrays.asList( "boolean", "char", "byte", "short", "int", "long", "float", "double" )
|
||||||
@ -54,7 +55,7 @@ public class Type implements Comparable<Type> {
|
|||||||
|
|
||||||
private final String packageName;
|
private final String packageName;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Type elementType;
|
private final List<Type> typeParameters;
|
||||||
private final boolean isEnumType;
|
private final boolean isEnumType;
|
||||||
private final boolean isCollectionType;
|
private final boolean isCollectionType;
|
||||||
private final boolean isIterableType;
|
private final boolean isIterableType;
|
||||||
@ -68,10 +69,10 @@ public class Type implements Comparable<Type> {
|
|||||||
return new Type(
|
return new Type(
|
||||||
pakkage.getName(),
|
pakkage.getName(),
|
||||||
clazz.getSimpleName(),
|
clazz.getSimpleName(),
|
||||||
null,
|
|
||||||
clazz.isEnum(),
|
clazz.isEnum(),
|
||||||
Collection.class.isAssignableFrom( clazz ),
|
Collection.class.isAssignableFrom( clazz ),
|
||||||
Iterable.class.isAssignableFrom( clazz )
|
Iterable.class.isAssignableFrom( clazz ),
|
||||||
|
Collections.<Type>emptyList()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -80,21 +81,21 @@ public class Type implements Comparable<Type> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Type(String name) {
|
public Type(String name) {
|
||||||
this( null, name, null, false, false, false );
|
this( null, name, false, false, false, Collections.<Type>emptyList() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type(String packageName, String name) {
|
public Type(String packageName, String name) {
|
||||||
this( packageName, name, null, false, false, false );
|
this( packageName, name, false, false, false, Collections.<Type>emptyList() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type(String packageName, String name, Type elementType, boolean isEnumType, boolean isCollectionType,
|
public Type(String packageName, String name, boolean isEnumType, boolean isCollectionType,
|
||||||
boolean isIterableType) {
|
boolean isIterableType, List<Type> typeParameters) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.elementType = elementType;
|
|
||||||
this.isEnumType = isEnumType;
|
this.isEnumType = isEnumType;
|
||||||
this.isCollectionType = isCollectionType;
|
this.isCollectionType = isCollectionType;
|
||||||
this.isIterableType = isIterableType;
|
this.isIterableType = isIterableType;
|
||||||
|
this.typeParameters = typeParameters;
|
||||||
|
|
||||||
if ( isCollectionType ) {
|
if ( isCollectionType ) {
|
||||||
collectionImplementationType = DEFAULT_COLLECTION_IMPLEMENTATION_TYPES.get( packageName + "." + name );
|
collectionImplementationType = DEFAULT_COLLECTION_IMPLEMENTATION_TYPES.get( packageName + "." + name );
|
||||||
@ -119,8 +120,8 @@ public class Type implements Comparable<Type> {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getElementType() {
|
public List<Type> getTypeParameters() {
|
||||||
return elementType;
|
return typeParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPrimitive() {
|
public boolean isPrimitive() {
|
||||||
@ -152,27 +153,17 @@ public class Type implements Comparable<Type> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public Set<Type> getImportTypes() {
|
||||||
if ( packageName == null ) {
|
return Collections.emptySet();
|
||||||
return name;
|
|
||||||
}
|
|
||||||
else if ( elementType == null ) {
|
|
||||||
return packageName + "." + name;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return packageName + "." + name + "<" + elementType + ">";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result
|
|
||||||
+ ( ( elementType == null ) ? 0 : elementType.hashCode() );
|
|
||||||
result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
|
result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
|
||||||
result = prime * result
|
result = prime * result + ( ( packageName == null ) ? 0 : packageName.hashCode() );
|
||||||
+ ( ( packageName == null ) ? 0 : packageName.hashCode() );
|
result = prime * result + ( ( typeParameters == null ) ? 0 : typeParameters.hashCode() );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,14 +179,6 @@ public class Type implements Comparable<Type> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Type other = (Type) obj;
|
Type other = (Type) obj;
|
||||||
if ( elementType == null ) {
|
|
||||||
if ( other.elementType != null ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( !elementType.equals( other.elementType ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( name == null ) {
|
if ( name == null ) {
|
||||||
if ( other.name != null ) {
|
if ( other.name != null ) {
|
||||||
return false;
|
return false;
|
||||||
@ -212,6 +195,14 @@ public class Type implements Comparable<Type> {
|
|||||||
else if ( !packageName.equals( other.packageName ) ) {
|
else if ( !packageName.equals( other.packageName ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ( typeParameters == null ) {
|
||||||
|
if ( other.typeParameters != null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( !typeParameters.equals( other.typeParameters ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,8 +356,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
private MappingMethod getIterableMappingMethod(List<Method> methods, Method method) {
|
private MappingMethod getIterableMappingMethod(List<Method> methods, Method method) {
|
||||||
TypeConversion conversion = getIterableConversion(
|
TypeConversion conversion = getIterableConversion(
|
||||||
conversions,
|
conversions,
|
||||||
method.getSourceType().getElementType(),
|
method.getSourceType().getTypeParameters().iterator().next(),
|
||||||
method.getTargetType().getElementType(),
|
method.getTargetType().getTypeParameters().iterator().next(),
|
||||||
method.getIterableMapping()
|
method.getIterableMapping()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -368,8 +368,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
method.getTargetType(),
|
method.getTargetType(),
|
||||||
getMappingMethodReference(
|
getMappingMethodReference(
|
||||||
methods,
|
methods,
|
||||||
method.getSourceType().getElementType(),
|
method.getSourceType().getTypeParameters().iterator().next(),
|
||||||
method.getTargetType().getElementType()
|
method.getTargetType().getTypeParameters().iterator().next()
|
||||||
),
|
),
|
||||||
conversion
|
conversion
|
||||||
);
|
);
|
||||||
@ -430,9 +430,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
Kind.ERROR,
|
Kind.ERROR,
|
||||||
String.format(
|
String.format(
|
||||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||||
property.getSourceType(),
|
property.getSourceType().getName(),
|
||||||
property.getSourceName(),
|
property.getSourceName(),
|
||||||
property.getTargetType(),
|
property.getTargetType().getName(),
|
||||||
property.getTargetName()
|
property.getTargetName()
|
||||||
),
|
),
|
||||||
method.getExecutable()
|
method.getExecutable()
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.util;
|
package org.mapstruct.ap.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
@ -43,20 +45,20 @@ public class TypeUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Type getType(DeclaredType type) {
|
public Type getType(DeclaredType type) {
|
||||||
Type elementType = null;
|
List<Type> typeParameters = new ArrayList<Type>();
|
||||||
|
|
||||||
boolean isIterableType = isIterableType( type );
|
boolean isIterableType = isIterableType( type );
|
||||||
if ( isIterableType && !type.getTypeArguments().isEmpty() ) {
|
for ( TypeMirror mirror : type.getTypeArguments() ) {
|
||||||
elementType = retrieveType( type.getTypeArguments().iterator().next() );
|
typeParameters.add( retrieveType( mirror ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Type(
|
return new Type(
|
||||||
elementUtils.getPackageOf( type.asElement() ).toString(),
|
elementUtils.getPackageOf( type.asElement() ).toString(),
|
||||||
type.asElement().getSimpleName().toString(),
|
type.asElement().getSimpleName().toString(),
|
||||||
elementType,
|
|
||||||
type.asElement().getKind() == ElementKind.ENUM,
|
type.asElement().getKind() == ElementKind.ENUM,
|
||||||
isCollectionType( type ),
|
isCollectionType( type ),
|
||||||
isIterableType
|
isIterableType,
|
||||||
|
typeParameters
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,15 +19,15 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
@Override
|
@Override
|
||||||
public ${targetType.name}<${targetType.elementType.name}> ${name}(${sourceType.name}<${sourceType.elementType.name}> ${parameterName}) {
|
public <@includeModel object=targetType/> ${name}(<@includeModel object=sourceType/> ${parameterName}) {
|
||||||
if ( ${parameterName} == null ) {
|
if ( ${parameterName} == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
<#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side -->
|
<#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side -->
|
||||||
<#if targetType.name == "Iterable" && targetType.packageName == "java.lang">${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><${targetType.elementType.name}> ${targetType.name?uncap_first} = new <#if targetType.iterableImplementationType??>${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><${targetType.elementType.name}>();
|
<#if targetType.name == "Iterable" && targetType.packageName == "java.lang">${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><<@includeModel object=targetType.typeParameters[0]/>> ${targetType.name?uncap_first} = new <#if targetType.iterableImplementationType??>${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><<@includeModel object=targetType.typeParameters[0]/>>();
|
||||||
|
|
||||||
for ( ${sourceType.elementType.name} ${sourceType.elementType.name?uncap_first} : ${parameterName} ) {
|
for ( <@includeModel object=sourceType.typeParameters[0]/> ${sourceType.typeParameters[0].name?uncap_first} : ${parameterName} ) {
|
||||||
<#if conversion??>
|
<#if conversion??>
|
||||||
<#if (conversion.exceptionTypes?size == 0) >
|
<#if (conversion.exceptionTypes?size == 0) >
|
||||||
${targetType.name?uncap_first}.add( <@includeModel object=conversion/> );
|
${targetType.name?uncap_first}.add( <@includeModel object=conversion/> );
|
||||||
@ -42,7 +42,7 @@
|
|||||||
</#list>
|
</#list>
|
||||||
</#if>
|
</#if>
|
||||||
<#else>
|
<#else>
|
||||||
${targetType.name?uncap_first}.add( ${elementMappingMethod.name}( ${sourceType.elementType.name?uncap_first} ) );
|
${targetType.name?uncap_first}.add( ${elementMappingMethod.name}( ${sourceType.typeParameters[0].name?uncap_first} ) );
|
||||||
</#if>
|
</#if>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
processor/src/main/resources/org.mapstruct.ap.model.Type.ftl
Normal file
21
processor/src/main/resources/org.mapstruct.ap.model.Type.ftl
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<#--
|
||||||
|
|
||||||
|
Copyright 2012-2013 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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
${name}<#if (typeParameters?size > 0) ><<#list typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, </#if></#list>></#if>
|
Loading…
x
Reference in New Issue
Block a user