METAGEN-15 use the first upper bound when the type to be exported is a generic.

This commit is contained in:
Emmanuel Bernard 2010-01-15 17:58:18 +00:00 committed by Strong Liu
parent 33d734f33a
commit d4dac16e32
10 changed files with 209 additions and 18 deletions

View File

@ -62,7 +62,7 @@ public class ClassWriter {
}
catch ( FilerException filerEx ) {
context.logMessage(
Diagnostic.Kind.ERROR, "Problem with Processing Environment Filer: " + filerEx.getMessage()
Diagnostic.Kind.WARNING, "Problem with Processing Environment Filer: " + filerEx.getMessage()
);
}
catch ( IOException ioEx ) {

View File

@ -110,6 +110,7 @@ public class Context {
return;
}
ClassWriter.writeFile( new AnnotationMetaEntity( element, this, defaultAccessTypeForHierarchy ), this );
TypeUtils.extractClosestRealTypeAsString( element.asType(), this );
elementsAlreadyProcessed.add( element.getQualifiedName().toString() );
}

View File

@ -226,7 +226,8 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
}
XmlMetaEntity metaEntity = new XmlMetaEntity(
entity, packageName, getXmlMappedType( fullyQualifiedClassName )
entity, packageName, getXmlMappedType( fullyQualifiedClassName ),
context
);
if ( context.getMetaEntitiesToProcess().containsKey( fullyQualifiedClassName ) ) {
@ -264,7 +265,8 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
}
XmlMetaEntity metaEntity = new XmlMetaEntity(
embeddable, packageName, getXmlMappedType( fullyQualifiedClassName )
embeddable, packageName, getXmlMappedType( fullyQualifiedClassName ),
context
);
if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) {
@ -292,7 +294,8 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
}
XmlMetaEntity metaEntity = new XmlMetaEntity(
mappedSuperClass, packageName, getXmlMappedType( fullyQualifiedClassName )
mappedSuperClass, packageName, getXmlMappedType( fullyQualifiedClassName ),
context
);
if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) {

View File

@ -21,11 +21,11 @@ package org.hibernate.jpamodelgen;
* @author Hardy Ferentschik
*/
public interface MetaAttribute {
String getDeclarationString();
String getDeclarationString();
String getMetaType();
String getMetaType();
String getPropertyName();
String getPropertyName();
String getTypeDeclaration();
String getTypeDeclaration();
}

View File

@ -18,6 +18,7 @@
package org.hibernate.jpamodelgen;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.type.TypeMirror;
@ -25,6 +26,8 @@ import javax.lang.model.type.TypeKind;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.Types;
/**
* Utility class.
@ -72,4 +75,24 @@ public class TypeUtils {
return null;
}
}
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
if ( type instanceof TypeVariable ) {
final TypeMirror compositeUpperBound = ( ( TypeVariable ) type ).getUpperBound();
final Types types = context.getProcessingEnvironment()
.getTypeUtils();
final List<? extends TypeMirror> upperBounds = types.directSupertypes( compositeUpperBound );
if (upperBounds.size() == 0) {
return compositeUpperBound.toString();
}
else {
//take the first one
return extractClosestRealTypeAsString( upperBounds.get( 0 ), context );
}
}
else {
return type.toString();
}
}
}

View File

@ -435,15 +435,18 @@ public class AnnotationMetaEntity implements MetaEntity {
}
private String getKeyType(DeclaredType t) {
return t.getTypeArguments().get( 0 ).toString();
return TypeUtils.extractClosestRealTypeAsString( t.getTypeArguments().get( 0 ), context );
}
private String getElementType(DeclaredType declaredType) {
if ( declaredType.getTypeArguments().size() == 1 ) {
return declaredType.getTypeArguments().get( 0 ).toString();
final TypeMirror type = declaredType.getTypeArguments().get( 0 );
return TypeUtils.extractClosestRealTypeAsString( type, context );
}
else {
return declaredType.getTypeArguments().get( 1 ).toString();
return TypeUtils.extractClosestRealTypeAsString( declaredType.getTypeArguments().get( 1 ), context );
}
}
}

View File

@ -26,10 +26,12 @@ import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import org.hibernate.jpamodelgen.Context;
import org.hibernate.jpamodelgen.MetaAttribute;
import org.hibernate.jpamodelgen.ImportContextImpl;
import org.hibernate.jpamodelgen.MetaEntity;
import org.hibernate.jpamodelgen.ImportContext;
import org.hibernate.jpamodelgen.TypeUtils;
import org.hibernate.jpamodelgen.xml.jaxb.Attributes;
import org.hibernate.jpamodelgen.xml.jaxb.Basic;
import org.hibernate.jpamodelgen.xml.jaxb.ElementCollection;
@ -65,31 +67,35 @@ public class XmlMetaEntity implements MetaEntity {
final private List<MetaAttribute> members = new ArrayList<MetaAttribute>();
private TypeElement element;
private Context context;
public XmlMetaEntity(Entity ormEntity, String packageName, TypeElement element) {
public XmlMetaEntity(Entity ormEntity, String packageName, TypeElement element, Context context) {
this.clazzName = ormEntity.getClazz();
this.packageName = packageName;
importContext = new ImportContextImpl( getPackageName() );
this.context = context;
this.importContext = new ImportContextImpl( getPackageName() );
this.element = element;
Attributes attributes = ormEntity.getAttributes();
parseAttributes( attributes );
}
public XmlMetaEntity(MappedSuperclass mappedSuperclass, String packageName, TypeElement element) {
public XmlMetaEntity(MappedSuperclass mappedSuperclass, String packageName, TypeElement element, Context context) {
this.clazzName = mappedSuperclass.getClazz();
this.packageName = packageName;
importContext = new ImportContextImpl( getPackageName() );
this.context = context;
this.importContext = new ImportContextImpl( getPackageName() );
this.element = element;
Attributes attributes = mappedSuperclass.getAttributes();
parseAttributes( attributes );
}
public XmlMetaEntity(Embeddable embeddable, String packageName, TypeElement element) {
public XmlMetaEntity(Embeddable embeddable, String packageName, TypeElement element, Context context) {
this.clazzName = embeddable.getClazz();
this.packageName = packageName;
importContext = new ImportContextImpl( getPackageName() );
this.context = context;
this.importContext = new ImportContextImpl( getPackageName() );
this.element = element;
EmbeddableAttributes attributes = embeddable.getAttributes();
@ -164,7 +170,7 @@ public class XmlMetaEntity implements MetaEntity {
for ( Element elem : element.getEnclosedElements() ) {
if ( elem.getSimpleName().toString().equals( propertyName ) ) {
DeclaredType type = ( ( DeclaredType ) elem.asType() );
types[0] = type.getTypeArguments().get( 0 ).toString();
types[0] = TypeUtils.extractClosestRealTypeAsString(type.getTypeArguments().get( 0 ), context);
types[1] = COLLECTIONS.get( type.asElement().toString() );
}
}

View File

@ -0,0 +1,35 @@
package org.hibernate.jpamodelgen.test.generics;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author Emmanuel Bernard
*/
@Entity
@Table(name="ejb_child")
public class Child {
private Integer id;
private String name;
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,43 @@
// $Id$
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual 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.hibernate.jpamodelgen.test.generics;
import org.testng.annotations.Test;
import org.hibernate.jpamodelgen.test.elementcollection.House;
import org.hibernate.jpamodelgen.test.util.CompilationTest;
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertClassGenerated;
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertNoGeneratedSourceFile;
/**
* @author Emmanuel Bernard
*/
public class GenericsTest extends CompilationTest {
@Test
public void testGenerics() {
assertClassGenerated( Parent.class.getName() + "_" );
assertClassGenerated( Child.class.getName() + "_" );
}
@Override
protected String getTestPackage() {
return Parent.class.getPackage().getName();
}
}

View File

@ -0,0 +1,77 @@
package org.hibernate.jpamodelgen.test.generics;
import java.util.Set;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* @author Emmanuel Bernard
*/
@Entity
@Table(name="ejb_parent")
public class Parent {
@Embeddable
public static class Relatives<T> {
private Set<T> siblings;
@OneToMany
@JoinColumn(name="siblings_fk")
public Set<T> getSiblings() {
return siblings;
}
public void setSiblings(Set<T> siblings) {
this.siblings = siblings;
}
}
private Integer id;
private String name;
private Set<Child> children;
private Relatives<Child> siblings;
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany
@JoinColumn(name="parent_fk", nullable = false)
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
@Embedded
public Relatives<Child> getSiblings() {
return siblings;
}
public void setSiblings(Relatives<Child> siblings) {
this.siblings = siblings;
}
}