METAGEN-20 support raw collections and honor targetEntity
This commit is contained in:
parent
d4dac16e32
commit
b78ebb332c
|
@ -79,8 +79,7 @@ public class TypeUtils {
|
||||||
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
|
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
|
||||||
if ( type instanceof TypeVariable ) {
|
if ( type instanceof TypeVariable ) {
|
||||||
final TypeMirror compositeUpperBound = ( ( TypeVariable ) type ).getUpperBound();
|
final TypeMirror compositeUpperBound = ( ( TypeVariable ) type ).getUpperBound();
|
||||||
final Types types = context.getProcessingEnvironment()
|
final Types types = context.getProcessingEnvironment().getTypeUtils();
|
||||||
.getTypeUtils();
|
|
||||||
final List<? extends TypeMirror> upperBounds = types.directSupertypes( compositeUpperBound );
|
final List<? extends TypeMirror> upperBounds = types.directSupertypes( compositeUpperBound );
|
||||||
if (upperBounds.size() == 0) {
|
if (upperBounds.size() == 0) {
|
||||||
return compositeUpperBound.toString();
|
return compositeUpperBound.toString();
|
||||||
|
@ -89,7 +88,6 @@ public class TypeUtils {
|
||||||
//take the first one
|
//take the first one
|
||||||
return extractClosestRealTypeAsString( upperBounds.get( 0 ), context );
|
return extractClosestRealTypeAsString( upperBounds.get( 0 ), context );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return type.toString();
|
return type.toString();
|
||||||
|
|
|
@ -22,8 +22,10 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
|
import javax.lang.model.element.AnnotationValue;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.Name;
|
import javax.lang.model.element.Name;
|
||||||
import javax.lang.model.element.PackageElement;
|
import javax.lang.model.element.PackageElement;
|
||||||
|
@ -43,7 +45,11 @@ import javax.persistence.Embedded;
|
||||||
import javax.persistence.EmbeddedId;
|
import javax.persistence.EmbeddedId;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.MappedSuperclass;
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
|
@ -348,8 +354,11 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
String fqElementName = returnedElement.getQualifiedName()
|
String fqElementName = returnedElement.getQualifiedName()
|
||||||
.toString(); // WARNING: .toString() is necessary here since Name equals does not compare to String
|
.toString(); // WARNING: .toString() is necessary here since Name equals does not compare to String
|
||||||
String collection = COLLECTIONS.get( fqElementName );
|
String collection = COLLECTIONS.get( fqElementName );
|
||||||
|
final List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors();
|
||||||
|
String targetEntity = getTargetEntity( annotations );
|
||||||
if ( collection != null ) {
|
if ( collection != null ) {
|
||||||
if ( element.getAnnotation( ElementCollection.class ) != null ) {
|
if ( containsAnnotation( annotations, ElementCollection.class ) ) {
|
||||||
|
//FIXME I don't understand why this code is different between Elementcollection and a regular collection but it needs to take targetClass into account
|
||||||
TypeMirror collectionElementType = getCollectionElementType( t, fqElementName );
|
TypeMirror collectionElementType = getCollectionElementType( t, fqElementName );
|
||||||
final TypeElement collectionElement = ( TypeElement ) context.getProcessingEnvironment()
|
final TypeElement collectionElement = ( TypeElement ) context.getProcessingEnvironment()
|
||||||
.getTypeUtils()
|
.getTypeUtils()
|
||||||
|
@ -361,11 +370,12 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
if ( collection.equals( "javax.persistence.metamodel.MapAttribute" ) ) {
|
if ( collection.equals( "javax.persistence.metamodel.MapAttribute" ) ) {
|
||||||
return new AnnotationMetaMap(
|
return new AnnotationMetaMap(
|
||||||
parent, element, collection, getKeyType( t ), getElementType( t )
|
//FIXME support targetEntity for map's key @MapKeyClass
|
||||||
|
parent, element, collection, getKeyType( t ), getElementType( t, targetEntity )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new AnnotationMetaCollection( parent, element, collection, getElementType( t ) );
|
return new AnnotationMetaCollection( parent, element, collection, getElementType( t, targetEntity ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -414,6 +424,63 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean containsAnnotation(List<? extends AnnotationMirror> annotations, Class<?> annotation) {
|
||||||
|
String annString = annotation.getName();
|
||||||
|
for ( AnnotationMirror mirror : annotations ) {
|
||||||
|
if ( annString.equals( mirror.getAnnotationType().toString() ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns targetEntity or null if no targetEntity is here or if equals to void
|
||||||
|
*/
|
||||||
|
private String getTargetEntity(List<? extends AnnotationMirror> annotations) {
|
||||||
|
final String elementCollection = ElementCollection.class.getName();
|
||||||
|
|
||||||
|
for ( AnnotationMirror mirror : annotations ) {
|
||||||
|
final String annotation = mirror.getAnnotationType().toString();
|
||||||
|
if ( elementCollection.equals( annotation ) ) {
|
||||||
|
final String targetEntity = getTargetEntity( mirror );
|
||||||
|
if (targetEntity != null) return targetEntity;
|
||||||
|
}
|
||||||
|
else if ( OneToMany.class.getName().equals( annotation ) ) {
|
||||||
|
final String targetEntity = getTargetEntity( mirror );
|
||||||
|
if (targetEntity != null) return targetEntity;
|
||||||
|
}
|
||||||
|
else if ( ManyToMany.class.getName().equals( annotation ) ) {
|
||||||
|
final String targetEntity = getTargetEntity( mirror );
|
||||||
|
if (targetEntity != null) return targetEntity;
|
||||||
|
}
|
||||||
|
else if ( ManyToOne.class.getName().equals( annotation ) ) {
|
||||||
|
final String targetEntity = getTargetEntity( mirror );
|
||||||
|
if (targetEntity != null) return targetEntity;
|
||||||
|
}
|
||||||
|
else if ( OneToOne.class.getName().equals( annotation ) ) {
|
||||||
|
final String targetEntity = getTargetEntity( mirror );
|
||||||
|
if (targetEntity != null) return targetEntity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTargetEntity(AnnotationMirror mirror) {
|
||||||
|
String targetEntity = null;
|
||||||
|
final Map<? extends ExecutableElement, ? extends AnnotationValue> attributes = mirror.getElementValues();
|
||||||
|
for ( Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : attributes.entrySet() ) {
|
||||||
|
final String simpleName = entry.getKey().getSimpleName().toString();
|
||||||
|
if ( "targetEntity".equals( simpleName ) ) {
|
||||||
|
targetEntity = entry.getValue().toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetEntity = ( "void.class".equals( targetEntity ) ) ? null : targetEntity;
|
||||||
|
return targetEntity != null && targetEntity.endsWith( ".class" ) ?
|
||||||
|
targetEntity.substring( 0, targetEntity.length() - 6 ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
public String generateImports() {
|
public String generateImports() {
|
||||||
return importContext.generateImports();
|
return importContext.generateImports();
|
||||||
}
|
}
|
||||||
|
@ -438,13 +505,23 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
return TypeUtils.extractClosestRealTypeAsString( t.getTypeArguments().get( 0 ), context );
|
return TypeUtils.extractClosestRealTypeAsString( t.getTypeArguments().get( 0 ), context );
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getElementType(DeclaredType declaredType) {
|
private String getElementType(DeclaredType declaredType, String targetEntity) {
|
||||||
if ( declaredType.getTypeArguments().size() == 1 ) {
|
if (targetEntity != null) return targetEntity;
|
||||||
final TypeMirror type = declaredType.getTypeArguments().get( 0 );
|
final List<? extends TypeMirror> mirrors = declaredType.getTypeArguments();
|
||||||
|
if ( mirrors.size() == 1 ) {
|
||||||
|
final TypeMirror type = mirrors.get( 0 );
|
||||||
return TypeUtils.extractClosestRealTypeAsString( type, context );
|
return TypeUtils.extractClosestRealTypeAsString( type, context );
|
||||||
}
|
}
|
||||||
|
else if ( mirrors.size() == 2 ) {
|
||||||
|
return TypeUtils.extractClosestRealTypeAsString( mirrors.get( 1 ), context );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return TypeUtils.extractClosestRealTypeAsString( declaredType.getTypeArguments().get( 1 ), context );
|
//for 0 or many
|
||||||
|
//0 is expected, many is not
|
||||||
|
if ( mirrors.size() > 2) {
|
||||||
|
context.logMessage( Diagnostic.Kind.WARNING, "Unable to find the closest solid type" + declaredType );
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class Parent {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OneToMany
|
@OneToMany(targetEntity = void.class)
|
||||||
@JoinColumn(name="parent_fk", nullable = false)
|
@JoinColumn(name="parent_fk", nullable = false)
|
||||||
public Set<Child> getChildren() {
|
public Set<Child> getChildren() {
|
||||||
return children;
|
return children;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package org.hibernate.jpamodelgen.test.rawTypes;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.JoinTable;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class A implements java.io.Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
protected int value;
|
||||||
|
|
||||||
|
|
||||||
|
public A() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManyToMany(targetEntity = B.class, cascade = CascadeType.ALL)
|
||||||
|
@JoinTable(name = "tbl_A_B",
|
||||||
|
joinColumns =
|
||||||
|
@JoinColumn(
|
||||||
|
name = "A_FK", referencedColumnName = "ID"),
|
||||||
|
inverseJoinColumns =
|
||||||
|
@JoinColumn(
|
||||||
|
name = "B_FK", referencedColumnName = "ID")
|
||||||
|
)
|
||||||
|
protected Collection bCol = new java.util.ArrayList();
|
||||||
|
|
||||||
|
|
||||||
|
public Collection getBCol() {
|
||||||
|
return bCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBCol(Collection bCol) {
|
||||||
|
this.bCol = bCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAName(String aName) {
|
||||||
|
this.name = aName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getAValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.hibernate.jpamodelgen.test.rawTypes;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class B implements java.io.Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
protected int value;
|
||||||
|
|
||||||
|
|
||||||
|
@ManyToMany(targetEntity = A.class, mappedBy = "bCol", cascade = CascadeType.ALL)
|
||||||
|
protected Collection aCol = new java.util.ArrayList();
|
||||||
|
|
||||||
|
|
||||||
|
public B() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Collection getACol() {
|
||||||
|
return aCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setACol(Collection aCol) {
|
||||||
|
this.aCol = aCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
// $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.rawTypes;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.test.util.CompilationTest;
|
||||||
|
|
||||||
|
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertClassGenerated;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Emmanuel Bernard
|
||||||
|
*/
|
||||||
|
public class RawTypesTest extends CompilationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerics() {
|
||||||
|
assertClassGenerated( A.class.getName() + "_" );
|
||||||
|
assertClassGenerated( B.class.getName() + "_" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTestPackage() {
|
||||||
|
return A.class.getPackage().getName();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue