Skip to content

Commit 1a6924c

Browse files
committed
HHH-14724 Fix generation of problematic metamodel classes which use TYPE_USE annotations
1 parent 0fdf431 commit 1a6924c

File tree

3 files changed

+184
-2
lines changed

3 files changed

+184
-2
lines changed

tooling/metamodel-generator/hibernate-jpamodelgen.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ dependencies {
3030

3131
testCompile libraries.junit
3232
testCompile libraries.jpa
33-
testCompile libraries.validation
33+
testCompile libraries.validation
3434
testCompile project( ':hibernate-core' )
3535
}
3636

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.jpamodelgen.util;
8+
9+
import java.util.List;
10+
import javax.lang.model.element.Element;
11+
import javax.lang.model.element.ElementKind;
12+
import javax.lang.model.element.TypeParameterElement;
13+
import javax.lang.model.type.ArrayType;
14+
import javax.lang.model.type.DeclaredType;
15+
import javax.lang.model.type.ExecutableType;
16+
import javax.lang.model.type.IntersectionType;
17+
import javax.lang.model.type.NoType;
18+
import javax.lang.model.type.NullType;
19+
import javax.lang.model.type.PrimitiveType;
20+
import javax.lang.model.type.TypeKind;
21+
import javax.lang.model.type.TypeMirror;
22+
import javax.lang.model.type.TypeVariable;
23+
import javax.lang.model.type.UnionType;
24+
import javax.lang.model.type.WildcardType;
25+
import javax.lang.model.util.SimpleTypeVisitor8;
26+
27+
/**
28+
* @author Christian Beikov
29+
*/
30+
public final class TypeRenderingVisitor extends SimpleTypeVisitor8<Object, Object> {
31+
32+
private final StringBuilder sb = new StringBuilder();
33+
34+
private TypeRenderingVisitor() {
35+
}
36+
37+
public static String toString(TypeMirror typeMirror) {
38+
if ( typeMirror instanceof TypeVariable ) {
39+
// Top level type variables don't need to render the upper bound as `T extends Type`
40+
final Element typeVariableElement = ( (TypeVariable) typeMirror ).asElement();
41+
if ( typeVariableElement instanceof TypeParameterElement ) {
42+
final TypeParameterElement typeParameter = (TypeParameterElement) typeVariableElement;
43+
if ( typeParameter.getEnclosingElement().getKind() == ElementKind.METHOD ) {
44+
// But for method level type variable we return the upper bound
45+
// because the type variable has no meaning except for that method
46+
typeMirror = ( (TypeVariable) typeMirror ).getUpperBound();
47+
}
48+
else {
49+
return typeParameter.toString();
50+
}
51+
}
52+
else {
53+
typeMirror = typeVariableElement.asType();
54+
}
55+
}
56+
else if ( typeMirror instanceof IntersectionType ) {
57+
// For top level type only the first type is relevant
58+
typeMirror = ( (IntersectionType) typeMirror ).getBounds().get( 0 );
59+
}
60+
final TypeRenderingVisitor typeRenderingVisitor = new TypeRenderingVisitor();
61+
typeMirror.accept( typeRenderingVisitor, null );
62+
return typeRenderingVisitor.sb.toString();
63+
}
64+
65+
@Override
66+
public Object visitPrimitive(PrimitiveType t, Object o) {
67+
final String primitiveTypeName = getPrimitiveTypeName( t.getKind() );
68+
if ( primitiveTypeName != null ) {
69+
sb.append( primitiveTypeName );
70+
}
71+
return null;
72+
}
73+
74+
private static String getPrimitiveTypeName(TypeKind kind) {
75+
switch ( kind ) {
76+
case INT:
77+
return "int";
78+
case BOOLEAN:
79+
return "boolean";
80+
case BYTE:
81+
return "byte";
82+
case CHAR:
83+
return "char";
84+
case DOUBLE:
85+
return "double";
86+
case FLOAT:
87+
return "float";
88+
case LONG:
89+
return "long";
90+
case SHORT:
91+
return "short";
92+
case VOID:
93+
return "void";
94+
}
95+
return null;
96+
}
97+
98+
@Override
99+
public Object visitNull(NullType t, Object o) {
100+
return null;
101+
}
102+
103+
@Override
104+
public Object visitArray(ArrayType t, Object o) {
105+
t.getComponentType().accept( this, null );
106+
sb.append( "[]" );
107+
return t;
108+
}
109+
110+
@Override
111+
public Object visitDeclared(DeclaredType t, Object o) {
112+
sb.append( t.asElement().toString() );
113+
List<? extends TypeMirror> typeArguments = t.getTypeArguments();
114+
if ( !typeArguments.isEmpty() ) {
115+
sb.append( '<' );
116+
typeArguments.get( 0 ).accept( this, null );
117+
for ( int i = 1; i < typeArguments.size(); i++ ) {
118+
sb.append( ", " );
119+
typeArguments.get( i ).accept( this, null );
120+
}
121+
sb.append( '>' );
122+
}
123+
return null;
124+
}
125+
126+
@Override
127+
public Object visitTypeVariable(TypeVariable t, Object o) {
128+
final Element typeVariableElement = t.asElement();
129+
if ( typeVariableElement instanceof TypeParameterElement ) {
130+
final TypeParameterElement typeParameter = (TypeParameterElement) typeVariableElement;
131+
sb.append( typeParameter );
132+
if ( !"java.lang.Object".equals( t.getUpperBound().toString() ) ) {
133+
sb.append( " extends " );
134+
t.getUpperBound().accept( this, null );
135+
}
136+
}
137+
else {
138+
typeVariableElement.asType().accept( this, null );
139+
}
140+
return null;
141+
}
142+
143+
@Override
144+
public Object visitWildcard(WildcardType t, Object o) {
145+
sb.append( '?' );
146+
if ( t.getExtendsBound() != null ) {
147+
sb.append( " extends " );
148+
t.getExtendsBound().accept( this, null );
149+
}
150+
if ( t.getSuperBound() != null ) {
151+
sb.append( " super " );
152+
t.getSuperBound().accept( this, null );
153+
}
154+
return null;
155+
}
156+
157+
@Override
158+
public Object visitUnion(UnionType t, Object o) {
159+
return null;
160+
}
161+
162+
@Override
163+
public Object visitIntersection(IntersectionType t, Object o) {
164+
final List<? extends TypeMirror> bounds = t.getBounds();
165+
bounds.get( 0 ).accept( this, null );
166+
for ( int i = 0; i < bounds.size(); i++ ) {
167+
sb.append( " & " );
168+
bounds.get( i ).accept( this, null );
169+
}
170+
return null;
171+
}
172+
173+
@Override
174+
public Object visitExecutable(ExecutableType t, Object o) {
175+
return null;
176+
}
177+
178+
@Override
179+
public Object visitNoType(NoType t, Object o) {
180+
return null;
181+
}
182+
}

tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public static String toTypeString(TypeMirror type) {
7474
if ( type.getKind().isPrimitive() ) {
7575
return PRIMITIVE_WRAPPERS.get( type.getKind() );
7676
}
77-
return type.toString();
77+
return TypeRenderingVisitor.toString( type );
7878
}
7979

8080
public static String toArrayTypeString(ArrayType type, Context context) {

0 commit comments

Comments
 (0)