From d4dac16e32986272b0f1dbc40cdb2f8febc23a30 Mon Sep 17 00:00:00 2001 From: Emmanuel Bernard Date: Fri, 15 Jan 2010 17:58:18 +0000 Subject: [PATCH] METAGEN-15 use the first upper bound when the type to be exported is a generic. --- .../hibernate/jpamodelgen/ClassWriter.java | 2 +- .../org/hibernate/jpamodelgen/Context.java | 1 + .../JPAMetaModelEntityProcessor.java | 9 ++- .../hibernate/jpamodelgen/MetaAttribute.java | 8 +- .../org/hibernate/jpamodelgen/TypeUtils.java | 23 ++++++ .../annotation/AnnotationMetaEntity.java | 9 ++- .../jpamodelgen/xml/XmlMetaEntity.java | 20 +++-- .../jpamodelgen/test/generics/Child.java | 35 +++++++++ .../test/generics/GenericsTest.java | 43 +++++++++++ .../jpamodelgen/test/generics/Parent.java | 77 +++++++++++++++++++ 10 files changed, 209 insertions(+), 18 deletions(-) create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Child.java create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Parent.java diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java index bdf13716a7..9ce6f27e80 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java @@ -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 ) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java index a1a24bebb4..20aca8c788 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java @@ -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() ); } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java index f9b0be969f..5f59f4a588 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java @@ -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 ) ) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaAttribute.java index 946447ff6a..4ae7cf4b66 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaAttribute.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaAttribute.java @@ -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(); } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java index 26a7f0d01e..7ae7706040 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/TypeUtils.java @@ -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 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(); + } + } } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java index 49ec1c3cde..f5daa4c359 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java @@ -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 ); } } + + } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java index 2dbae22142..f1ca58d6e2 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java @@ -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 members = new ArrayList(); 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() ); } } diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Child.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Child.java new file mode 100644 index 0000000000..c7cfbb3244 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Child.java @@ -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; + } +} + diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java new file mode 100644 index 0000000000..0034c95b88 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java @@ -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(); + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Parent.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Parent.java new file mode 100644 index 0000000000..82fabf61bc --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/Parent.java @@ -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 { + private Set siblings; + + @OneToMany + @JoinColumn(name="siblings_fk") + public Set getSiblings() { + return siblings; + } + + public void setSiblings(Set siblings) { + this.siblings = siblings; + } + } + + private Integer id; + private String name; + private Set children; + private Relatives 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 getChildren() { + return children; + } + + public void setChildren(Set children) { + this.children = children; + } + + @Embedded + public Relatives getSiblings() { + return siblings; + } + + public void setSiblings(Relatives siblings) { + this.siblings = siblings; + } +}