Skip to content

Commit 9817360

Browse files
committed
HHH-18693 Fixed code to allow creation of metadata for inner static non-private classes
1 parent 54466db commit 9817360

File tree

6 files changed

+138
-61
lines changed

6 files changed

+138
-61
lines changed

tooling/metamodel-generator/src/main/java/org/hibernate/processor/ClassWriter.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package org.hibernate.processor;
66

7+
import jakarta.annotation.Nullable;
78
import org.hibernate.processor.model.MetaAttribute;
89
import org.hibernate.processor.model.Metamodel;
910

@@ -96,7 +97,7 @@ private static StringBuffer generateBody(Metamodel entity, Context context) {
9697
}
9798
entity.inheritedAnnotations().forEach(pw::println);
9899

99-
printClassDeclaration( entity, pw );
100+
printClassDeclaration( entity, pw, context );
100101

101102
pw.println();
102103

@@ -132,7 +133,7 @@ private static StringBuffer generateBody(Metamodel entity, Context context) {
132133
}
133134
}
134135

135-
private static void printClassDeclaration(Metamodel entity, PrintWriter pw) {
136+
private static void printClassDeclaration(Metamodel entity, PrintWriter pw, Context context) {
136137
pw.print( "public " );
137138
if ( !entity.isImplementation() && !entity.isJakartaDataStyle() ) {
138139
pw.print( "abstract " );
@@ -142,7 +143,11 @@ private static void printClassDeclaration(Metamodel entity, PrintWriter pw) {
142143

143144
String superClassName = entity.getSupertypeName();
144145
if ( superClassName != null ) {
145-
pw.print( " extends " + getGeneratedSuperclassName(entity, superClassName) );
146+
Metamodel superClassEntity = context.getMetaEntity( superClassName );
147+
if (superClassEntity == null) {
148+
superClassEntity = context.getMetaEmbeddable( superClassName );
149+
}
150+
pw.print( " extends " + getGeneratedSuperclassName(entity, superClassName, superClassEntity ) );
146151
}
147152
if ( entity.isImplementation() ) {
148153
pw.print( entity.getElement().getKind() == ElementKind.CLASS ? " extends " : " implements " );
@@ -162,11 +167,11 @@ private static String getFullyQualifiedClassName(Metamodel entity, String metaMo
162167
}
163168

164169
private static String getGeneratedClassName(Metamodel entity) {
165-
final String className = entity.getSimpleName();
170+
final String className = entity.getSimpleName().replace( '.', '_' );
166171
return entity.isJakartaDataStyle() ? '_' + className : className + '_';
167172
}
168173

169-
private static String getGeneratedSuperclassName(Metamodel entity, String superClassName) {
174+
private static String getGeneratedSuperclassName(Metamodel entity, String superClassName, @Nullable Metamodel superClassEntity) {
170175
if ( entity.isJakartaDataStyle() ) {
171176
int lastDot = superClassName.lastIndexOf('.');
172177
if ( lastDot<0 ) {
@@ -178,7 +183,8 @@ private static String getGeneratedSuperclassName(Metamodel entity, String superC
178183
}
179184
}
180185
else {
181-
return superClassName + '_';
186+
return superClassEntity == null ? superClassName + '_'
187+
: getFullyQualifiedClassName( superClassEntity, superClassEntity.getPackageName() );
182188
}
183189
}
184190

tooling/metamodel-generator/src/main/java/org/hibernate/processor/HibernateProcessor.java

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@
3434
import java.io.PrintWriter;
3535
import java.io.StringWriter;
3636
import java.io.Writer;
37+
import java.net.URLEncoder;
3738
import java.util.Collection;
3839
import java.util.HashSet;
3940
import java.util.List;
4041
import java.util.Map;
4142
import java.util.Set;
4243

4344
import static java.lang.Boolean.parseBoolean;
45+
import static java.nio.charset.StandardCharsets.UTF_8;
4446
import static javax.lang.model.util.ElementFilter.fieldsIn;
4547
import static javax.lang.model.util.ElementFilter.methodsIn;
4648
import static org.hibernate.processor.HibernateProcessor.ADD_GENERATED_ANNOTATION;
@@ -362,59 +364,70 @@ private void processClasses(RoundEnvironment roundEnvironment) {
362364
}
363365

364366
for ( Element element : roundEnvironment.getRootElements() ) {
365-
try {
366-
if ( !included( element )
367-
|| hasAnnotation( element, Constants.EXCLUDE )
368-
|| hasPackageAnnotation( element, Constants.EXCLUDE ) ) {
369-
// skip it completely
370-
}
371-
else if ( isEntityOrEmbeddable( element ) ) {
372-
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated entity class '" + element + "'" );
373-
handleRootElementAnnotationMirrors( element );
374-
}
375-
else if ( hasAuxiliaryAnnotations( element ) ) {
376-
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
377-
handleRootElementAuxiliaryAnnotationMirrors( element );
367+
processElement( element );
368+
}
369+
}
370+
371+
private void processElement(Element element) {
372+
try {
373+
if ( !included( element )
374+
|| hasAnnotation( element, Constants.EXCLUDE )
375+
|| hasPackageAnnotation( element, Constants.EXCLUDE ) ) {
376+
// skip it completely
377+
}
378+
else if ( isEntityOrEmbeddable( element ) ) {
379+
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated entity class '" + element + "'" );
380+
handleRootElementAnnotationMirrors( element );
381+
}
382+
else if ( hasAuxiliaryAnnotations( element ) ) {
383+
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
384+
handleRootElementAuxiliaryAnnotationMirrors( element );
385+
}
386+
else if ( element instanceof TypeElement typeElement ) {
387+
final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY );
388+
if ( repository != null ) {
389+
final AnnotationValue provider = getAnnotationValue( repository, "provider" );
390+
if ( provider == null
391+
|| provider.getValue().toString().isEmpty()
392+
|| provider.getValue().toString().equalsIgnoreCase("hibernate") ) {
393+
context.logMessage( Diagnostic.Kind.OTHER, "Processing repository class '" + element + "'" );
394+
final AnnotationMetaEntity metaEntity =
395+
AnnotationMetaEntity.create( typeElement, context );
396+
if ( metaEntity.isInitialized() ) {
397+
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
398+
}
399+
// otherwise discard it (assume it has query by magical method name stuff)
400+
}
378401
}
379-
else if ( element instanceof TypeElement typeElement ) {
380-
final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY );
381-
if ( repository != null ) {
382-
final AnnotationValue provider = getAnnotationValue( repository, "provider" );
383-
if ( provider == null
384-
|| provider.getValue().toString().isEmpty()
385-
|| provider.getValue().toString().equalsIgnoreCase("hibernate") ) {
386-
context.logMessage( Diagnostic.Kind.OTHER, "Processing repository class '" + element + "'" );
402+
else {
403+
for ( Element member : typeElement.getEnclosedElements() ) {
404+
if ( hasAnnotation( member, HQL, SQL, FIND ) ) {
405+
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
387406
final AnnotationMetaEntity metaEntity =
388407
AnnotationMetaEntity.create( typeElement, context );
389-
if ( metaEntity.isInitialized() ) {
390-
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
391-
}
392-
// otherwise discard it (assume it has query by magical method name stuff)
393-
}
394-
}
395-
else {
396-
for ( Element member : typeElement.getEnclosedElements() ) {
397-
if ( hasAnnotation( member, HQL, SQL, FIND ) ) {
398-
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
399-
final AnnotationMetaEntity metaEntity =
400-
AnnotationMetaEntity.create( typeElement, context );
401-
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
402-
break;
403-
}
408+
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
409+
break;
404410
}
405411
}
406412
}
407413
}
408-
catch ( ProcessLaterException processLaterException ) {
409-
if ( element instanceof TypeElement ) {
410-
context.logMessage(
411-
Diagnostic.Kind.OTHER,
412-
"Could not process '" + element + "' (will redo in next round)"
413-
);
414-
context.addElementToRedo( ( (TypeElement) element).getQualifiedName() );
414+
if ( isClassOrRecordType( element ) ) {
415+
for ( final Element child : element.getEnclosedElements() ) {
416+
if ( isClassOrRecordType( child ) ) {
417+
processElement( child );
418+
}
415419
}
416420
}
417421
}
422+
catch ( ProcessLaterException processLaterException ) {
423+
if ( element instanceof TypeElement ) {
424+
context.logMessage(
425+
Diagnostic.Kind.OTHER,
426+
"Could not process '" + element + "' (will redo in next round)"
427+
);
428+
context.addElementToRedo( ( (TypeElement) element ).getQualifiedName() );
429+
}
430+
}
418431
}
419432

420433
private boolean hasPackageAnnotation(Element element, String annotation) {
@@ -714,7 +727,7 @@ private void writeIndex() {
714727
.createResource(
715728
StandardLocation.SOURCE_OUTPUT,
716729
ENTITY_INDEX,
717-
entityName,
730+
URLEncoder.encode(entityName, UTF_8),
718731
processingEnvironment.getElementUtils().getTypeElement( className )
719732
)
720733
.openWriter()) {

tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMeta.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.hibernate.query.sqm.tree.SqmStatement;
2020
import org.hibernate.query.sqm.tree.select.SqmSelectClause;
2121
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
22+
import org.hibernate.type.descriptor.java.JavaType;
2223

2324
import javax.lang.model.element.AnnotationMirror;
2425
import javax.lang.model.element.AnnotationValue;
@@ -147,7 +148,8 @@ else if (selection instanceof SqmSelectClause from) {
147148
: from.getSelectionItems().get(0).getJavaTypeName();
148149
}
149150
else if (selection instanceof JpaRoot<?> root) {
150-
return root.getModel().getTypeName();
151+
final JavaType<?> javaType = root.getModel().getExpressibleJavaType();
152+
return javaType != null ? javaType.getTypeName() : root.getModel().getTypeName();
151153
}
152154
else if (selection instanceof JpaEntityJoin<?, ?> join) {
153155
return join.getModel().getTypeName();

tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454

5555
import java.util.ArrayList;
5656
import java.util.Collection;
57+
import java.util.Collections;
5758
import java.util.HashMap;
5859
import java.util.List;
5960
import java.util.Map;
@@ -217,11 +218,24 @@ public boolean isInitialized() {
217218

218219
@Override
219220
public final String getSimpleName() {
220-
return removeDollar( element.getSimpleName().toString() );
221+
if ( element.getNestingKind().isNested() ) {
222+
final var strings = new ArrayList<String>();
223+
for ( TypeElement el = element;; el = (TypeElement) el.getEnclosingElement() ) {
224+
strings.add( removeDollar( el.getSimpleName().toString() ) );
225+
if ( !el.getNestingKind().isNested() ) {
226+
break;
227+
}
228+
}
229+
Collections.reverse( strings );
230+
return String.join( ".", strings );
231+
}
232+
else {
233+
return removeDollar( element.getSimpleName().toString() );
234+
}
221235
}
222236

223237
private String getConstructorName() {
224-
return getSimpleName() + '_';
238+
return getSimpleName().replace( '.', '_' ) + '_';
225239
}
226240

227241
/**

tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,16 @@
114114
import org.hibernate.type.SetType;
115115
import org.hibernate.type.SqlTypes;
116116
import org.hibernate.type.Type;
117+
import org.hibernate.type.descriptor.WrapperOptions;
118+
import org.hibernate.type.descriptor.java.BasicJavaType;
117119
import org.hibernate.type.descriptor.java.EnumJavaType;
118120
import org.hibernate.type.descriptor.java.JavaType;
119121
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
120122
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
121123
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
122124
import org.hibernate.type.spi.TypeConfiguration;
123125

126+
import javax.lang.model.element.TypeElement;
124127
import java.util.HashMap;
125128
import java.util.List;
126129
import java.util.Map;
@@ -287,6 +290,8 @@ static CollectionType createCollectionType(String role, String name) {
287290

288291
abstract boolean isEntityDefined(String entityName);
289292

293+
abstract TypeElement findEntityClass(String entityName);
294+
290295
abstract String findEntityName(String typeName);
291296

292297
abstract String qualifyName(String entityName);
@@ -792,7 +797,9 @@ public MockJpaMetamodelImpl() {
792797
@Override
793798
public EntityDomainType<?> entity(String entityName) {
794799
if ( isEntityDefined(entityName) ) {
795-
return new MockEntityDomainType<>(entityName);
800+
final TypeElement entityClass = findEntityClass( entityName );
801+
final String entityTypeName = entityClass == null ? entityName : entityClass.getQualifiedName().toString();
802+
return new MockEntityDomainType<>(entityName, new MockJavaType<>( entityTypeName ));
796803
}
797804
else {
798805
return null;
@@ -825,7 +832,7 @@ public <X> ManagedDomainType<X> findManagedType(Class<X> cls) {
825832
@Override
826833
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
827834
if ( isEntityDefined( cls.getName() ) ) {
828-
return new MockEntityDomainType<>( cls.getName() );
835+
return new MockEntityDomainType<>( cls.getName(), new MockJavaType<X>( cls.getName() ));
829836
}
830837
else {
831838
return null;
@@ -887,6 +894,39 @@ public <E extends Enum<E>> E enumValue(EnumJavaType<E> enumType, String enumValu
887894
public JpaCompliance getJpaCompliance() {
888895
return jpaCompliance;
889896
}
897+
898+
private static class MockJavaType<X> implements BasicJavaType<X> {
899+
private final String typeName;
900+
901+
public MockJavaType(String typeName) {
902+
this.typeName = typeName;
903+
}
904+
905+
@Override
906+
public <X1> X1 unwrap(X value, Class<X1> type, WrapperOptions options) {
907+
return null;
908+
}
909+
910+
@Override
911+
public <X1> X wrap(X1 value, WrapperOptions options) {
912+
return null;
913+
}
914+
915+
@Override
916+
public String getTypeName() {
917+
return typeName;
918+
}
919+
920+
@Override
921+
public Class<X> getJavaTypeClass() {
922+
try {
923+
return (Class<X>) Class.forName( typeName );
924+
}
925+
catch (ClassNotFoundException e) {
926+
return null;
927+
}
928+
}
929+
}
890930
}
891931

892932
@Nullable Set<String> getEnumTypesForValue(String value) {
@@ -909,8 +949,8 @@ public PersistentAttribute<X,?> findDeclaredAttribute(String name) {
909949

910950
class MockEntityDomainType<X> extends EntityTypeImpl<X> {
911951

912-
public MockEntityDomainType(String entityName) {
913-
super(entityName, entityName, false, true, false, null, null,
952+
public MockEntityDomainType(String entityName, JavaType<X> javaType) {
953+
super(entityName, entityName, false, true, false, javaType, null,
914954
metamodel.getJpaMetamodel());
915955
}
916956

@@ -994,7 +1034,7 @@ public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
9941034
if (!entry.getValue().getEntityName().equals(getHibernateEntityName())
9951035
&& isSubtype(entry.getValue().getEntityName(), getHibernateEntityName())) {
9961036
PersistentAttribute<? super Object, ?> subattribute
997-
= new MockEntityDomainType<>(entry.getValue().getEntityName()).findAttribute(name);
1037+
= new MockEntityDomainType<>(entry.getValue().getEntityName(), new MockJpaMetamodelImpl.MockJavaType<>(entry.getValue().getEntityName()) ).findAttribute(name);
9981038
if (subattribute != null) {
9991039
return (SqmPathSource<?>) subattribute;
10001040
}
@@ -1040,7 +1080,7 @@ else if ( type.isEntityType() ) {
10401080
owner,
10411081
name,
10421082
AttributeClassification.MANY_TO_ONE,
1043-
new MockEntityDomainType<>(type.getName()),
1083+
new MockEntityDomainType<>(type.getName(), new MockJpaMetamodelImpl.MockJavaType<>(type.getName())),
10441084
null,
10451085
null,
10461086
false,
@@ -1098,7 +1138,9 @@ private DomainType<?> getMapKeyDomainType(String entityName, CollectionType coll
10981138
private DomainType<?> getDomainType(String entityName, CollectionType collectionType, ManagedDomainType<?> owner, Type elementType) {
10991139
if ( elementType.isEntityType() ) {
11001140
String associatedEntityName = collectionType.getAssociatedEntityName(MockSessionFactory.this);
1101-
return new MockEntityDomainType<>(associatedEntityName);
1141+
final TypeElement associatedEntityEntityClass = findEntityClass( associatedEntityName );
1142+
final String associatedEntityTypeName = associatedEntityEntityClass == null ? associatedEntityName : associatedEntityEntityClass.getQualifiedName().toString();
1143+
return new MockEntityDomainType<>(associatedEntityName, new MockJpaMetamodelImpl.MockJavaType<>(associatedEntityTypeName));
11021144
}
11031145
else if ( elementType.isComponentType() ) {
11041146
CompositeType compositeType = (CompositeType) elementType;

tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ boolean isAttributeDefined(String entityName, String fieldName) {
495495
&& findPropertyByPath(entityClass, fieldName, getDefaultAccessType(entityClass)) != null;
496496
}
497497

498-
private TypeElement findEntityClass(String entityName) {
498+
public TypeElement findEntityClass(String entityName) {
499499
if (entityName == null) {
500500
return null;
501501
}

0 commit comments

Comments
 (0)