Skip to content

Commit 582d736

Browse files
committed
HHH-17772 rework processor bookkeeping
1 parent 67a5590 commit 582d736

File tree

3 files changed

+155
-81
lines changed

3 files changed

+155
-81
lines changed

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

+48-5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ public final class Context {
5050
*/
5151
private final Map<String, Metamodel> metaEmbeddables = new HashMap<>();
5252

53+
/**
54+
* Used for keeping track of parsed entities and mapped super classes (XML + annotations).
55+
*/
56+
private final Map<String, Metamodel> dataMetaEntities = new HashMap<>();
57+
58+
/**
59+
* Used for keeping track of parsed embeddable entities. These entities have to be kept separate since
60+
* they are lazily initialized.
61+
*/
62+
private final Map<String, Metamodel> dataMetaEmbeddables = new HashMap<>();
63+
5364
private final Map<String, Metamodel> metaAuxiliaries = new HashMap<>();
5465

5566
private final Map<String, AccessTypeInformation> accessTypeInformation = new HashMap<>();
@@ -78,7 +89,7 @@ public final class Context {
7889
private boolean generateJakartaDataStaticMetamodel;
7990

8091
// keep track of all classes for which model have been generated
81-
private final Collection<String> generatedModelClasses = new HashSet<>();
92+
private final Set<Metamodel> generatedModelClasses = new HashSet<>();
8293

8394
// keep track of which named queries have been checked
8495
private final Set<String> checkedNamedQueries = new HashSet<>();
@@ -233,6 +244,38 @@ public Collection<Metamodel> getMetaEmbeddables() {
233244
return metaEmbeddables.values();
234245
}
235246

247+
public boolean containsDataMetaEntity(String qualifiedName) {
248+
return dataMetaEntities.containsKey( qualifiedName );
249+
}
250+
251+
public @Nullable Metamodel getDataMetaEntity(String qualifiedName) {
252+
return dataMetaEntities.get( qualifiedName );
253+
}
254+
255+
public Collection<Metamodel> getDataMetaEntities() {
256+
return dataMetaEntities.values();
257+
}
258+
259+
public void addDataMetaEntity(String qualifiedName, Metamodel metaEntity) {
260+
dataMetaEntities.put( qualifiedName, metaEntity );
261+
}
262+
263+
public boolean containsDataMetaEmbeddable(String qualifiedName) {
264+
return dataMetaEmbeddables.containsKey( qualifiedName );
265+
}
266+
267+
public @Nullable Metamodel getDataMetaEmbeddable(String qualifiedName) {
268+
return dataMetaEmbeddables.get( qualifiedName );
269+
}
270+
271+
public void addDataMetaEmbeddable(String qualifiedName, Metamodel metaEntity) {
272+
dataMetaEmbeddables.put( qualifiedName, metaEntity );
273+
}
274+
275+
public Collection<Metamodel> getDataMetaEmbeddables() {
276+
return dataMetaEmbeddables.values();
277+
}
278+
236279
public @Nullable Metamodel getMetaAuxiliary(String qualifiedName) {
237280
return metaAuxiliaries.get( qualifiedName );
238281
}
@@ -258,12 +301,12 @@ public TypeElement getTypeElementForFullyQualifiedName(String qualifiedName) {
258301
return elementUtils.getTypeElement( qualifiedName );
259302
}
260303

261-
void markGenerated(String name) {
262-
generatedModelClasses.add( name );
304+
void markGenerated(Metamodel metamodel) {
305+
generatedModelClasses.add( metamodel );
263306
}
264307

265-
boolean isAlreadyGenerated(String name) {
266-
return generatedModelClasses.contains( name );
308+
boolean isAlreadyGenerated(Metamodel metamodel) {
309+
return generatedModelClasses.contains( metamodel );
267310
}
268311

269312
public Set<CharSequence> getElementsToRedo() {

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

+93-62
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
*/
77
package org.hibernate.jpamodelgen;
88

9-
import java.util.Collection;
10-
import java.util.HashSet;
11-
import java.util.List;
12-
import java.util.Map;
13-
import java.util.Set;
9+
import org.checkerframework.checker.nullness.qual.Nullable;
10+
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
11+
import org.hibernate.jpamodelgen.annotation.AnnotationMetaPackage;
12+
import org.hibernate.jpamodelgen.model.Metamodel;
13+
import org.hibernate.jpamodelgen.xml.JpaDescriptorParser;
14+
1415
import javax.annotation.processing.AbstractProcessor;
1516
import javax.annotation.processing.ProcessingEnvironment;
1617
import javax.annotation.processing.RoundEnvironment;
@@ -24,20 +25,29 @@
2425
import javax.lang.model.type.TypeKind;
2526
import javax.lang.model.type.TypeMirror;
2627
import javax.tools.Diagnostic;
27-
28-
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
29-
import org.hibernate.jpamodelgen.annotation.AnnotationMetaPackage;
30-
import org.hibernate.jpamodelgen.model.Metamodel;
31-
import org.hibernate.jpamodelgen.xml.JpaDescriptorParser;
32-
33-
import org.checkerframework.checker.nullness.qual.Nullable;
28+
import java.util.Collection;
29+
import java.util.HashSet;
30+
import java.util.List;
31+
import java.util.Map;
32+
import java.util.Set;
3433

3534
import static java.lang.Boolean.parseBoolean;
3635
import static javax.lang.model.util.ElementFilter.fieldsIn;
3736
import static javax.lang.model.util.ElementFilter.methodsIn;
37+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ADD_GENERATED_ANNOTATION;
38+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ADD_GENERATION_DATE;
39+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ADD_SUPPRESS_WARNINGS_ANNOTATION;
40+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.DEBUG_OPTION;
41+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION;
42+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.LAZY_XML_PARSING;
43+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ORM_XML_OPTION;
44+
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION;
3845
import static org.hibernate.jpamodelgen.util.Constants.*;
39-
import static org.hibernate.jpamodelgen.util.TypeUtils.*;
40-
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.*;
46+
import static org.hibernate.jpamodelgen.util.TypeUtils.containsAnnotation;
47+
import static org.hibernate.jpamodelgen.util.TypeUtils.getAnnotationMirror;
48+
import static org.hibernate.jpamodelgen.util.TypeUtils.getAnnotationValue;
49+
import static org.hibernate.jpamodelgen.util.TypeUtils.hasAnnotation;
50+
import static org.hibernate.jpamodelgen.util.TypeUtils.isClassOrRecordType;
4151

4252
/**
4353
* Main annotation processor.
@@ -281,51 +291,62 @@ else if ( element instanceof TypeElement ) {
281291
private void createMetaModelClasses() {
282292

283293
for ( Metamodel aux : context.getMetaAuxiliaries() ) {
284-
final String key = aux.getQualifiedName();
285-
if ( !context.isAlreadyGenerated(key) ) {
286-
context.logMessage( Diagnostic.Kind.OTHER, "Writing metamodel for auxiliary '" + aux + "'" );
294+
if ( !context.isAlreadyGenerated(aux) ) {
295+
context.logMessage( Diagnostic.Kind.OTHER,
296+
"Writing metamodel for auxiliary '" + aux + "'" );
287297
ClassWriter.writeFile( aux, context );
288-
context.markGenerated(key);
298+
context.markGenerated(aux);
289299
}
290300
}
291301

292302
for ( Metamodel entity : context.getMetaEntities() ) {
293-
final String key = entity.isJakartaDataStyle()
294-
? '_' + entity.getQualifiedName()
295-
: entity.getQualifiedName();
296-
if ( !context.isAlreadyGenerated(key) ) {
297-
context.logMessage( Diagnostic.Kind.OTHER, "Writing metamodel for entity '" + entity + "'" );
303+
if ( !context.isAlreadyGenerated(entity) ) {
304+
context.logMessage( Diagnostic.Kind.OTHER,
305+
"Writing Jakarta Persistence metamodel for entity '" + entity + "'" );
306+
ClassWriter.writeFile( entity, context );
307+
context.markGenerated(entity);
308+
}
309+
}
310+
311+
for ( Metamodel entity : context.getDataMetaEntities() ) {
312+
if ( !context.isAlreadyGenerated(entity) ) {
313+
context.logMessage( Diagnostic.Kind.OTHER,
314+
"Writing Jakarta Data metamodel for entity '" + entity + "'" );
298315
ClassWriter.writeFile( entity, context );
299-
context.markGenerated(key);
316+
context.markGenerated(entity);
300317
}
301318
}
302319

303-
// we cannot process the delayed entities in any order. There might be dependencies between them.
304-
// we need to process the top level entities first
305-
final Collection<Metamodel> toProcessEntities = context.getMetaEmbeddables();
306-
while ( !toProcessEntities.isEmpty() ) {
307-
final Set<Metamodel> processedEntities = new HashSet<>();
308-
int toProcessCountBeforeLoop = toProcessEntities.size();
309-
for ( Metamodel entity : toProcessEntities ) {
320+
processEmbeddables( context.getMetaEmbeddables() );
321+
processEmbeddables( context.getDataMetaEmbeddables() );
322+
}
323+
324+
/**
325+
* We cannot process the delayed classes in any order.
326+
* There might be dependencies between them.
327+
* We need to process the toplevel classes first.
328+
*/
329+
private void processEmbeddables(Collection<Metamodel> models) {
330+
while ( !models.isEmpty() ) {
331+
final Set<Metamodel> processed = new HashSet<>();
332+
final int toProcessCountBeforeLoop = models.size();
333+
for ( Metamodel metamodel : models ) {
310334
// see METAGEN-36
311-
final String key = entity.isJakartaDataStyle()
312-
? '_' + entity.getQualifiedName()
313-
: entity.getQualifiedName();
314-
if ( context.isAlreadyGenerated(key) ) {
315-
processedEntities.add( entity );
335+
if ( context.isAlreadyGenerated(metamodel) ) {
336+
processed.add( metamodel );
316337
}
317-
else if ( !modelGenerationNeedsToBeDeferred( toProcessEntities, entity ) ) {
338+
else if ( !modelGenerationNeedsToBeDeferred(models, metamodel ) ) {
318339
context.logMessage(
319340
Diagnostic.Kind.OTHER,
320-
"Writing meta model for embeddable/mapped superclass " + entity
341+
"Writing metamodel for embeddable " + metamodel
321342
);
322-
ClassWriter.writeFile( entity, context );
323-
context.markGenerated(key);
324-
processedEntities.add( entity );
343+
ClassWriter.writeFile( metamodel, context );
344+
context.markGenerated(metamodel);
345+
processed.add( metamodel );
325346
}
326347
}
327-
toProcessEntities.removeAll( processedEntities );
328-
if ( toProcessEntities.size() >= toProcessCountBeforeLoop ) {
348+
models.removeAll( processed );
349+
if ( models.size() >= toProcessCountBeforeLoop ) {
329350
context.logMessage(
330351
Diagnostic.Kind.ERROR,
331352
"Potential endless loop in generation of entities."
@@ -398,11 +419,11 @@ private boolean hasAuxiliaryAnnotations(Element element) {
398419

399420
private void handleRootElementAnnotationMirrors(final Element element) {
400421
if ( isClassOrRecordType( element ) ) {
401-
for ( AnnotationMirror mirror : element.getAnnotationMirrors() ) {
422+
if ( hasAnnotation( element, ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE ) ) {
402423
final TypeElement typeElement = (TypeElement) element;
403424
final String qualifiedName = typeElement.getQualifiedName().toString();
404425
final Metamodel alreadyExistingMetaEntity =
405-
tryGettingExistingEntityFromContext( mirror, qualifiedName );
426+
tryGettingExistingEntityFromContext( typeElement, qualifiedName );
406427
if ( alreadyExistingMetaEntity != null && alreadyExistingMetaEntity.isMetaComplete() ) {
407428
context.logMessage(
408429
Diagnostic.Kind.OTHER,
@@ -418,7 +439,7 @@ private void handleRootElementAnnotationMirrors(final Element element) {
418439
if ( alreadyExistingMetaEntity != null ) {
419440
metaEntity.mergeInMembers( alreadyExistingMetaEntity );
420441
}
421-
addMetaEntityToContext( mirror, metaEntity );
442+
addMetamodelToContext( typeElement, metaEntity );
422443
if ( context.generateJakartaDataStaticMetamodel()
423444
// Don't generate a Jakarta Data metamodel
424445
// if this entity was partially mapped in XML
@@ -427,11 +448,11 @@ private void handleRootElementAnnotationMirrors(final Element element) {
427448
AnnotationMetaEntity.create( typeElement, context,
428449
requiresLazyMemberInitialization, true, true );
429450
// final Metamodel alreadyExistingDataMetaEntity =
430-
// tryGettingExistingEntityFromContext( mirror, '_' + qualifiedName );
451+
// tryGettingExistingDataEntityFromContext( mirror, '_' + qualifiedName );
431452
// if ( alreadyExistingDataMetaEntity != null ) {
432453
// dataMetaEntity.mergeInMembers( alreadyExistingDataMetaEntity );
433454
// }
434-
addMetaEntityToContext( mirror, dataMetaEntity );
455+
addDataMetamodelToContext( typeElement, dataMetaEntity );
435456
}
436457
}
437458
}
@@ -452,29 +473,39 @@ else if ( element instanceof PackageElement ) {
452473
//TODO: handle PackageElement
453474
}
454475

455-
private @Nullable Metamodel tryGettingExistingEntityFromContext(AnnotationMirror mirror, String qualifiedName) {
456-
if ( isAnnotationMirrorOfType( mirror, ENTITY )
457-
|| isAnnotationMirrorOfType( mirror, MAPPED_SUPERCLASS ) ) {
476+
private @Nullable Metamodel tryGettingExistingEntityFromContext(TypeElement typeElement, String qualifiedName) {
477+
if ( hasAnnotation( typeElement, ENTITY, MAPPED_SUPERCLASS ) ) {
458478
return context.getMetaEntity( qualifiedName );
459479
}
460-
else if ( isAnnotationMirrorOfType( mirror, EMBEDDABLE ) ) {
480+
else if ( hasAnnotation( typeElement, EMBEDDABLE ) ) {
461481
return context.getMetaEmbeddable( qualifiedName );
462482
}
463483
return null;
464484
}
465485

466-
private void addMetaEntityToContext(AnnotationMirror mirror, AnnotationMetaEntity metaEntity) {
467-
final String key = metaEntity.isJakartaDataStyle()
468-
? '_' + metaEntity.getQualifiedName()
469-
: metaEntity.getQualifiedName();
470-
if ( isAnnotationMirrorOfType( mirror, ENTITY ) ) {
471-
context.addMetaEntity( key, metaEntity );
486+
private void addMetamodelToContext(TypeElement typeElement, AnnotationMetaEntity entity) {
487+
final String key = entity.getQualifiedName();
488+
if ( hasAnnotation( typeElement, ENTITY ) ) {
489+
context.addMetaEntity( key, entity );
490+
}
491+
else if ( hasAnnotation( typeElement, MAPPED_SUPERCLASS ) ) {
492+
context.addMetaEntity( key, entity );
493+
}
494+
else if ( hasAnnotation( typeElement, EMBEDDABLE ) ) {
495+
context.addMetaEmbeddable( key, entity );
496+
}
497+
}
498+
499+
private void addDataMetamodelToContext(TypeElement typeElement, AnnotationMetaEntity entity) {
500+
final String key = entity.getQualifiedName();
501+
if ( hasAnnotation( typeElement, ENTITY ) ) {
502+
context.addDataMetaEntity( key, entity );
472503
}
473-
else if ( isAnnotationMirrorOfType( mirror, MAPPED_SUPERCLASS ) ) {
474-
context.addMetaEntity( key, metaEntity );
504+
else if ( hasAnnotation( typeElement, MAPPED_SUPERCLASS ) ) {
505+
context.addDataMetaEntity( key, entity );
475506
}
476-
else if ( isAnnotationMirrorOfType( mirror, EMBEDDABLE ) ) {
477-
context.addMetaEmbeddable( key, metaEntity );
507+
else if ( hasAnnotation( typeElement, EMBEDDABLE ) ) {
508+
context.addDataMetaEmbeddable( key, entity );
478509
}
479510
}
480511

0 commit comments

Comments
 (0)