Skip to content

Commit 268e4a6

Browse files
committed
HHH-18693 Fixed code to allow creation of metadata for inner static non-private classes
1 parent 55b30bb commit 268e4a6

File tree

5 files changed

+136
-60
lines changed

5 files changed

+136
-60
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;
@@ -358,59 +360,70 @@ private void processClasses(RoundEnvironment roundEnvironment) {
358360
}
359361

360362
for ( Element element : roundEnvironment.getRootElements() ) {
361-
try {
362-
if ( !included( element )
363-
|| hasAnnotation( element, Constants.EXCLUDE )
364-
|| hasPackageAnnotation( element, Constants.EXCLUDE ) ) {
365-
// skip it completely
366-
}
367-
else if ( isEntityOrEmbeddable( element ) ) {
368-
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated entity class '" + element + "'" );
369-
handleRootElementAnnotationMirrors( element );
370-
}
371-
else if ( hasAuxiliaryAnnotations( element ) ) {
372-
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
373-
handleRootElementAuxiliaryAnnotationMirrors( element );
363+
processElement( element );
364+
}
365+
}
366+
367+
private void processElement(Element element) {
368+
try {
369+
if ( !included( element )
370+
|| hasAnnotation( element, Constants.EXCLUDE )
371+
|| hasPackageAnnotation( element, Constants.EXCLUDE ) ) {
372+
// skip it completely
373+
}
374+
else if ( isEntityOrEmbeddable( element ) ) {
375+
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated entity class '" + element + "'" );
376+
handleRootElementAnnotationMirrors( element );
377+
}
378+
else if ( hasAuxiliaryAnnotations( element ) ) {
379+
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
380+
handleRootElementAuxiliaryAnnotationMirrors( element );
381+
}
382+
else if ( element instanceof TypeElement typeElement ) {
383+
final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY );
384+
if ( repository != null ) {
385+
final AnnotationValue provider = getAnnotationValue( repository, "provider" );
386+
if ( provider == null
387+
|| provider.getValue().toString().isEmpty()
388+
|| provider.getValue().toString().equalsIgnoreCase("hibernate") ) {
389+
context.logMessage( Diagnostic.Kind.OTHER, "Processing repository class '" + element + "'" );
390+
final AnnotationMetaEntity metaEntity =
391+
AnnotationMetaEntity.create( typeElement, context );
392+
if ( metaEntity.isInitialized() ) {
393+
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
394+
}
395+
// otherwise discard it (assume it has query by magical method name stuff)
396+
}
374397
}
375-
else if ( element instanceof TypeElement typeElement ) {
376-
final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY );
377-
if ( repository != null ) {
378-
final AnnotationValue provider = getAnnotationValue( repository, "provider" );
379-
if ( provider == null
380-
|| provider.getValue().toString().isEmpty()
381-
|| provider.getValue().toString().equalsIgnoreCase("hibernate") ) {
382-
context.logMessage( Diagnostic.Kind.OTHER, "Processing repository class '" + element + "'" );
398+
else {
399+
for ( Element member : typeElement.getEnclosedElements() ) {
400+
if ( hasAnnotation( member, HQL, SQL, FIND ) ) {
401+
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
383402
final AnnotationMetaEntity metaEntity =
384403
AnnotationMetaEntity.create( typeElement, context );
385-
if ( metaEntity.isInitialized() ) {
386-
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
387-
}
388-
// otherwise discard it (assume it has query by magical method name stuff)
389-
}
390-
}
391-
else {
392-
for ( Element member : typeElement.getEnclosedElements() ) {
393-
if ( hasAnnotation( member, HQL, SQL, FIND ) ) {
394-
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
395-
final AnnotationMetaEntity metaEntity =
396-
AnnotationMetaEntity.create( typeElement, context );
397-
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
398-
break;
399-
}
404+
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
405+
break;
400406
}
401407
}
402408
}
403409
}
404-
catch ( ProcessLaterException processLaterException ) {
405-
if ( element instanceof TypeElement ) {
406-
context.logMessage(
407-
Diagnostic.Kind.OTHER,
408-
"Could not process '" + element + "' (will redo in next round)"
409-
);
410-
context.addElementToRedo( ( (TypeElement) element).getQualifiedName() );
410+
if ( isClassOrRecordType( element ) ) {
411+
for ( final Element child : element.getEnclosedElements() ) {
412+
if ( isClassOrRecordType( child ) ) {
413+
processElement( child );
414+
}
411415
}
412416
}
413417
}
418+
catch ( ProcessLaterException processLaterException ) {
419+
if ( element instanceof TypeElement ) {
420+
context.logMessage(
421+
Diagnostic.Kind.OTHER,
422+
"Could not process '" + element + "' (will redo in next round)"
423+
);
424+
context.addElementToRedo( ( (TypeElement) element ).getQualifiedName() );
425+
}
426+
}
414427
}
415428

416429
private boolean hasPackageAnnotation(Element element, String annotation) {
@@ -716,7 +729,7 @@ private void writeIndex() {
716729
.createResource(
717730
StandardLocation.SOURCE_OUTPUT,
718731
ENTITY_INDEX,
719-
entityName,
732+
URLEncoder.encode(entityName, UTF_8),
720733
processingEnvironment.getElementUtils().getTypeElement( className )
721734
)
722735
.openWriter()) {

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
@@ -52,6 +52,7 @@
5252

5353
import java.util.ArrayList;
5454
import java.util.Collection;
55+
import java.util.Collections;
5556
import java.util.HashMap;
5657
import java.util.List;
5758
import java.util.Map;
@@ -218,11 +219,24 @@ public boolean isInitialized() {
218219

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

224238
private String getConstructorName() {
225-
return getSimpleName() + '_';
239+
return getSimpleName().replace( '.', '_' ) + '_';
226240
}
227241

228242
/**

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
@@ -113,13 +113,16 @@
113113
import org.hibernate.type.SetType;
114114
import org.hibernate.type.SqlTypes;
115115
import org.hibernate.type.Type;
116+
import org.hibernate.type.descriptor.WrapperOptions;
117+
import org.hibernate.type.descriptor.java.BasicJavaType;
116118
import org.hibernate.type.descriptor.java.EnumJavaType;
117119
import org.hibernate.type.descriptor.java.JavaType;
118120
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
119121
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
120122
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
121123
import org.hibernate.type.spi.TypeConfiguration;
122124

125+
import javax.lang.model.element.TypeElement;
123126
import java.util.HashMap;
124127
import java.util.List;
125128
import java.util.Map;
@@ -286,6 +289,8 @@ static CollectionType createCollectionType(String role, String name) {
286289

287290
abstract boolean isEntityDefined(String entityName);
288291

292+
abstract TypeElement findEntityClass(String entityName);
293+
289294
abstract String findEntityName(String typeName);
290295

291296
abstract String qualifyName(String entityName);
@@ -790,7 +795,9 @@ public MockJpaMetamodelImpl() {
790795
@Override
791796
public EntityDomainType<?> entity(String entityName) {
792797
if ( isEntityDefined(entityName) ) {
793-
return new MockEntityDomainType<>(entityName);
798+
final TypeElement entityClass = findEntityClass( entityName );
799+
final String entityTypeName = entityClass == null ? entityName : entityClass.getQualifiedName().toString();
800+
return new MockEntityDomainType<>(entityName, new MockJavaType<>( entityTypeName ));
794801
}
795802
else {
796803
return null;
@@ -823,7 +830,7 @@ public <X> ManagedDomainType<X> findManagedType(Class<X> cls) {
823830
@Override
824831
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
825832
if ( isEntityDefined( cls.getName() ) ) {
826-
return new MockEntityDomainType<>( cls.getName() );
833+
return new MockEntityDomainType<>( cls.getName(), new MockJavaType<X>( cls.getName() ));
827834
}
828835
else {
829836
return null;
@@ -885,6 +892,39 @@ public <E extends Enum<E>> E enumValue(EnumJavaType<E> enumType, String enumValu
885892
public JpaCompliance getJpaCompliance() {
886893
return jpaCompliance;
887894
}
895+
896+
private static class MockJavaType<X> implements BasicJavaType<X> {
897+
private final String typeName;
898+
899+
public MockJavaType(String typeName) {
900+
this.typeName = typeName;
901+
}
902+
903+
@Override
904+
public <X1> X1 unwrap(X value, Class<X1> type, WrapperOptions options) {
905+
return null;
906+
}
907+
908+
@Override
909+
public <X1> X wrap(X1 value, WrapperOptions options) {
910+
return null;
911+
}
912+
913+
@Override
914+
public String getTypeName() {
915+
return typeName;
916+
}
917+
918+
@Override
919+
public Class<X> getJavaTypeClass() {
920+
try {
921+
return (Class<X>) Class.forName( typeName );
922+
}
923+
catch (ClassNotFoundException e) {
924+
return null;
925+
}
926+
}
927+
}
888928
}
889929

890930
@Nullable Set<String> getEnumTypesForValue(String value) {
@@ -907,8 +947,8 @@ public PersistentAttribute<X,?> findDeclaredAttribute(String name) {
907947

908948
class MockEntityDomainType<X> extends EntityTypeImpl<X> {
909949

910-
public MockEntityDomainType(String entityName) {
911-
super(entityName, entityName, false, true, false, null, null,
950+
public MockEntityDomainType(String entityName, JavaType<X> javaType) {
951+
super(entityName, entityName, false, true, false, javaType, null,
912952
metamodel.getJpaMetamodel());
913953
}
914954

@@ -992,7 +1032,7 @@ public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes)
9921032
if (!entry.getValue().getEntityName().equals(getHibernateEntityName())
9931033
&& isSubtype(entry.getValue().getEntityName(), getHibernateEntityName())) {
9941034
PersistentAttribute<? super Object, ?> subattribute
995-
= new MockEntityDomainType<>(entry.getValue().getEntityName()).findAttribute(name);
1035+
= new MockEntityDomainType<>(entry.getValue().getEntityName(), new MockJpaMetamodelImpl.MockJavaType<>(entry.getValue().getEntityName()) ).findAttribute(name);
9961036
if (subattribute != null) {
9971037
return (SqmPathSource<?>) subattribute;
9981038
}
@@ -1038,7 +1078,7 @@ else if ( type.isEntityType() ) {
10381078
owner,
10391079
name,
10401080
AttributeClassification.MANY_TO_ONE,
1041-
new MockEntityDomainType<>(type.getName()),
1081+
new MockEntityDomainType<>(type.getName(), new MockJpaMetamodelImpl.MockJavaType<>(type.getName())),
10421082
null,
10431083
null,
10441084
false,
@@ -1096,7 +1136,9 @@ private DomainType<?> getMapKeyDomainType(String entityName, CollectionType coll
10961136
private DomainType<?> getDomainType(String entityName, CollectionType collectionType, ManagedDomainType<?> owner, Type elementType) {
10971137
if ( elementType.isEntityType() ) {
10981138
String associatedEntityName = collectionType.getAssociatedEntityName(MockSessionFactory.this);
1099-
return new MockEntityDomainType<>(associatedEntityName);
1139+
final TypeElement associatedEntityEntityClass = findEntityClass( associatedEntityName );
1140+
final String associatedEntityTypeName = associatedEntityEntityClass == null ? associatedEntityName : associatedEntityEntityClass.getQualifiedName().toString();
1141+
return new MockEntityDomainType<>(associatedEntityName, new MockJpaMetamodelImpl.MockJavaType<>(associatedEntityTypeName));
11001142
}
11011143
else if ( elementType.isComponentType() ) {
11021144
CompositeType compositeType = (CompositeType) elementType;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,8 @@ boolean isAttributeDefined(String entityName, String fieldName) {
477477
&& findPropertyByPath(entityClass, fieldName, getDefaultAccessType(entityClass)) != null;
478478
}
479479

480-
private TypeElement findEntityClass(String entityName) {
480+
@Override
481+
public TypeElement findEntityClass(String entityName) {
481482
if (entityName == null) {
482483
return null;
483484
}

0 commit comments

Comments
 (0)