mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-22 11:06:08 +00:00
HHH-17772 rework processor bookkeeping
This commit is contained in:
parent
67a5590316
commit
582d736062
@ -50,6 +50,17 @@ public final class Context {
|
||||
*/
|
||||
private final Map<String, Metamodel> metaEmbeddables = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Used for keeping track of parsed entities and mapped super classes (XML + annotations).
|
||||
*/
|
||||
private final Map<String, Metamodel> dataMetaEntities = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Used for keeping track of parsed embeddable entities. These entities have to be kept separate since
|
||||
* they are lazily initialized.
|
||||
*/
|
||||
private final Map<String, Metamodel> dataMetaEmbeddables = new HashMap<>();
|
||||
|
||||
private final Map<String, Metamodel> metaAuxiliaries = new HashMap<>();
|
||||
|
||||
private final Map<String, AccessTypeInformation> accessTypeInformation = new HashMap<>();
|
||||
@ -78,7 +89,7 @@ public final class Context {
|
||||
private boolean generateJakartaDataStaticMetamodel;
|
||||
|
||||
// keep track of all classes for which model have been generated
|
||||
private final Collection<String> generatedModelClasses = new HashSet<>();
|
||||
private final Set<Metamodel> generatedModelClasses = new HashSet<>();
|
||||
|
||||
// keep track of which named queries have been checked
|
||||
private final Set<String> checkedNamedQueries = new HashSet<>();
|
||||
@ -233,6 +244,38 @@ public Collection<Metamodel> getMetaEmbeddables() {
|
||||
return metaEmbeddables.values();
|
||||
}
|
||||
|
||||
public boolean containsDataMetaEntity(String qualifiedName) {
|
||||
return dataMetaEntities.containsKey( qualifiedName );
|
||||
}
|
||||
|
||||
public @Nullable Metamodel getDataMetaEntity(String qualifiedName) {
|
||||
return dataMetaEntities.get( qualifiedName );
|
||||
}
|
||||
|
||||
public Collection<Metamodel> getDataMetaEntities() {
|
||||
return dataMetaEntities.values();
|
||||
}
|
||||
|
||||
public void addDataMetaEntity(String qualifiedName, Metamodel metaEntity) {
|
||||
dataMetaEntities.put( qualifiedName, metaEntity );
|
||||
}
|
||||
|
||||
public boolean containsDataMetaEmbeddable(String qualifiedName) {
|
||||
return dataMetaEmbeddables.containsKey( qualifiedName );
|
||||
}
|
||||
|
||||
public @Nullable Metamodel getDataMetaEmbeddable(String qualifiedName) {
|
||||
return dataMetaEmbeddables.get( qualifiedName );
|
||||
}
|
||||
|
||||
public void addDataMetaEmbeddable(String qualifiedName, Metamodel metaEntity) {
|
||||
dataMetaEmbeddables.put( qualifiedName, metaEntity );
|
||||
}
|
||||
|
||||
public Collection<Metamodel> getDataMetaEmbeddables() {
|
||||
return dataMetaEmbeddables.values();
|
||||
}
|
||||
|
||||
public @Nullable Metamodel getMetaAuxiliary(String qualifiedName) {
|
||||
return metaAuxiliaries.get( qualifiedName );
|
||||
}
|
||||
@ -258,12 +301,12 @@ public TypeElement getTypeElementForFullyQualifiedName(String qualifiedName) {
|
||||
return elementUtils.getTypeElement( qualifiedName );
|
||||
}
|
||||
|
||||
void markGenerated(String name) {
|
||||
generatedModelClasses.add( name );
|
||||
void markGenerated(Metamodel metamodel) {
|
||||
generatedModelClasses.add( metamodel );
|
||||
}
|
||||
|
||||
boolean isAlreadyGenerated(String name) {
|
||||
return generatedModelClasses.contains( name );
|
||||
boolean isAlreadyGenerated(Metamodel metamodel) {
|
||||
return generatedModelClasses.contains( metamodel );
|
||||
}
|
||||
|
||||
public Set<CharSequence> getElementsToRedo() {
|
||||
|
@ -6,11 +6,12 @@
|
||||
*/
|
||||
package org.hibernate.jpamodelgen;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
|
||||
import org.hibernate.jpamodelgen.annotation.AnnotationMetaPackage;
|
||||
import org.hibernate.jpamodelgen.model.Metamodel;
|
||||
import org.hibernate.jpamodelgen.xml.JpaDescriptorParser;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
@ -24,20 +25,29 @@
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
|
||||
import org.hibernate.jpamodelgen.annotation.AnnotationMetaPackage;
|
||||
import org.hibernate.jpamodelgen.model.Metamodel;
|
||||
import org.hibernate.jpamodelgen.xml.JpaDescriptorParser;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.lang.Boolean.parseBoolean;
|
||||
import static javax.lang.model.util.ElementFilter.fieldsIn;
|
||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ADD_GENERATED_ANNOTATION;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ADD_GENERATION_DATE;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ADD_SUPPRESS_WARNINGS_ANNOTATION;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.DEBUG_OPTION;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.LAZY_XML_PARSING;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.ORM_XML_OPTION;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION;
|
||||
import static org.hibernate.jpamodelgen.util.Constants.*;
|
||||
import static org.hibernate.jpamodelgen.util.TypeUtils.*;
|
||||
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.*;
|
||||
import static org.hibernate.jpamodelgen.util.TypeUtils.containsAnnotation;
|
||||
import static org.hibernate.jpamodelgen.util.TypeUtils.getAnnotationMirror;
|
||||
import static org.hibernate.jpamodelgen.util.TypeUtils.getAnnotationValue;
|
||||
import static org.hibernate.jpamodelgen.util.TypeUtils.hasAnnotation;
|
||||
import static org.hibernate.jpamodelgen.util.TypeUtils.isClassOrRecordType;
|
||||
|
||||
/**
|
||||
* Main annotation processor.
|
||||
@ -281,51 +291,62 @@ else if ( element instanceof TypeElement ) {
|
||||
private void createMetaModelClasses() {
|
||||
|
||||
for ( Metamodel aux : context.getMetaAuxiliaries() ) {
|
||||
final String key = aux.getQualifiedName();
|
||||
if ( !context.isAlreadyGenerated(key) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Writing metamodel for auxiliary '" + aux + "'" );
|
||||
if ( !context.isAlreadyGenerated(aux) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER,
|
||||
"Writing metamodel for auxiliary '" + aux + "'" );
|
||||
ClassWriter.writeFile( aux, context );
|
||||
context.markGenerated(key);
|
||||
context.markGenerated(aux);
|
||||
}
|
||||
}
|
||||
|
||||
for ( Metamodel entity : context.getMetaEntities() ) {
|
||||
final String key = entity.isJakartaDataStyle()
|
||||
? '_' + entity.getQualifiedName()
|
||||
: entity.getQualifiedName();
|
||||
if ( !context.isAlreadyGenerated(key) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Writing metamodel for entity '" + entity + "'" );
|
||||
if ( !context.isAlreadyGenerated(entity) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER,
|
||||
"Writing Jakarta Persistence metamodel for entity '" + entity + "'" );
|
||||
ClassWriter.writeFile( entity, context );
|
||||
context.markGenerated(key);
|
||||
context.markGenerated(entity);
|
||||
}
|
||||
}
|
||||
|
||||
// we cannot process the delayed entities in any order. There might be dependencies between them.
|
||||
// we need to process the top level entities first
|
||||
final Collection<Metamodel> toProcessEntities = context.getMetaEmbeddables();
|
||||
while ( !toProcessEntities.isEmpty() ) {
|
||||
final Set<Metamodel> processedEntities = new HashSet<>();
|
||||
int toProcessCountBeforeLoop = toProcessEntities.size();
|
||||
for ( Metamodel entity : toProcessEntities ) {
|
||||
for ( Metamodel entity : context.getDataMetaEntities() ) {
|
||||
if ( !context.isAlreadyGenerated(entity) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER,
|
||||
"Writing Jakarta Data metamodel for entity '" + entity + "'" );
|
||||
ClassWriter.writeFile( entity, context );
|
||||
context.markGenerated(entity);
|
||||
}
|
||||
}
|
||||
|
||||
processEmbeddables( context.getMetaEmbeddables() );
|
||||
processEmbeddables( context.getDataMetaEmbeddables() );
|
||||
}
|
||||
|
||||
/**
|
||||
* We cannot process the delayed classes in any order.
|
||||
* There might be dependencies between them.
|
||||
* We need to process the toplevel classes first.
|
||||
*/
|
||||
private void processEmbeddables(Collection<Metamodel> models) {
|
||||
while ( !models.isEmpty() ) {
|
||||
final Set<Metamodel> processed = new HashSet<>();
|
||||
final int toProcessCountBeforeLoop = models.size();
|
||||
for ( Metamodel metamodel : models ) {
|
||||
// see METAGEN-36
|
||||
final String key = entity.isJakartaDataStyle()
|
||||
? '_' + entity.getQualifiedName()
|
||||
: entity.getQualifiedName();
|
||||
if ( context.isAlreadyGenerated(key) ) {
|
||||
processedEntities.add( entity );
|
||||
if ( context.isAlreadyGenerated(metamodel) ) {
|
||||
processed.add( metamodel );
|
||||
}
|
||||
else if ( !modelGenerationNeedsToBeDeferred( toProcessEntities, entity ) ) {
|
||||
else if ( !modelGenerationNeedsToBeDeferred(models, metamodel ) ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.OTHER,
|
||||
"Writing meta model for embeddable/mapped superclass " + entity
|
||||
"Writing metamodel for embeddable " + metamodel
|
||||
);
|
||||
ClassWriter.writeFile( entity, context );
|
||||
context.markGenerated(key);
|
||||
processedEntities.add( entity );
|
||||
ClassWriter.writeFile( metamodel, context );
|
||||
context.markGenerated(metamodel);
|
||||
processed.add( metamodel );
|
||||
}
|
||||
}
|
||||
toProcessEntities.removeAll( processedEntities );
|
||||
if ( toProcessEntities.size() >= toProcessCountBeforeLoop ) {
|
||||
models.removeAll( processed );
|
||||
if ( models.size() >= toProcessCountBeforeLoop ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.ERROR,
|
||||
"Potential endless loop in generation of entities."
|
||||
@ -398,11 +419,11 @@ private boolean hasAuxiliaryAnnotations(Element element) {
|
||||
|
||||
private void handleRootElementAnnotationMirrors(final Element element) {
|
||||
if ( isClassOrRecordType( element ) ) {
|
||||
for ( AnnotationMirror mirror : element.getAnnotationMirrors() ) {
|
||||
if ( hasAnnotation( element, ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE ) ) {
|
||||
final TypeElement typeElement = (TypeElement) element;
|
||||
final String qualifiedName = typeElement.getQualifiedName().toString();
|
||||
final Metamodel alreadyExistingMetaEntity =
|
||||
tryGettingExistingEntityFromContext( mirror, qualifiedName );
|
||||
tryGettingExistingEntityFromContext( typeElement, qualifiedName );
|
||||
if ( alreadyExistingMetaEntity != null && alreadyExistingMetaEntity.isMetaComplete() ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.OTHER,
|
||||
@ -418,7 +439,7 @@ private void handleRootElementAnnotationMirrors(final Element element) {
|
||||
if ( alreadyExistingMetaEntity != null ) {
|
||||
metaEntity.mergeInMembers( alreadyExistingMetaEntity );
|
||||
}
|
||||
addMetaEntityToContext( mirror, metaEntity );
|
||||
addMetamodelToContext( typeElement, metaEntity );
|
||||
if ( context.generateJakartaDataStaticMetamodel()
|
||||
// Don't generate a Jakarta Data metamodel
|
||||
// if this entity was partially mapped in XML
|
||||
@ -427,11 +448,11 @@ private void handleRootElementAnnotationMirrors(final Element element) {
|
||||
AnnotationMetaEntity.create( typeElement, context,
|
||||
requiresLazyMemberInitialization, true, true );
|
||||
// final Metamodel alreadyExistingDataMetaEntity =
|
||||
// tryGettingExistingEntityFromContext( mirror, '_' + qualifiedName );
|
||||
// tryGettingExistingDataEntityFromContext( mirror, '_' + qualifiedName );
|
||||
// if ( alreadyExistingDataMetaEntity != null ) {
|
||||
// dataMetaEntity.mergeInMembers( alreadyExistingDataMetaEntity );
|
||||
// }
|
||||
addMetaEntityToContext( mirror, dataMetaEntity );
|
||||
addDataMetamodelToContext( typeElement, dataMetaEntity );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -452,29 +473,39 @@ else if ( element instanceof PackageElement ) {
|
||||
//TODO: handle PackageElement
|
||||
}
|
||||
|
||||
private @Nullable Metamodel tryGettingExistingEntityFromContext(AnnotationMirror mirror, String qualifiedName) {
|
||||
if ( isAnnotationMirrorOfType( mirror, ENTITY )
|
||||
|| isAnnotationMirrorOfType( mirror, MAPPED_SUPERCLASS ) ) {
|
||||
private @Nullable Metamodel tryGettingExistingEntityFromContext(TypeElement typeElement, String qualifiedName) {
|
||||
if ( hasAnnotation( typeElement, ENTITY, MAPPED_SUPERCLASS ) ) {
|
||||
return context.getMetaEntity( qualifiedName );
|
||||
}
|
||||
else if ( isAnnotationMirrorOfType( mirror, EMBEDDABLE ) ) {
|
||||
else if ( hasAnnotation( typeElement, EMBEDDABLE ) ) {
|
||||
return context.getMetaEmbeddable( qualifiedName );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addMetaEntityToContext(AnnotationMirror mirror, AnnotationMetaEntity metaEntity) {
|
||||
final String key = metaEntity.isJakartaDataStyle()
|
||||
? '_' + metaEntity.getQualifiedName()
|
||||
: metaEntity.getQualifiedName();
|
||||
if ( isAnnotationMirrorOfType( mirror, ENTITY ) ) {
|
||||
context.addMetaEntity( key, metaEntity );
|
||||
private void addMetamodelToContext(TypeElement typeElement, AnnotationMetaEntity entity) {
|
||||
final String key = entity.getQualifiedName();
|
||||
if ( hasAnnotation( typeElement, ENTITY ) ) {
|
||||
context.addMetaEntity( key, entity );
|
||||
}
|
||||
else if ( isAnnotationMirrorOfType( mirror, MAPPED_SUPERCLASS ) ) {
|
||||
context.addMetaEntity( key, metaEntity );
|
||||
else if ( hasAnnotation( typeElement, MAPPED_SUPERCLASS ) ) {
|
||||
context.addMetaEntity( key, entity );
|
||||
}
|
||||
else if ( isAnnotationMirrorOfType( mirror, EMBEDDABLE ) ) {
|
||||
context.addMetaEmbeddable( key, metaEntity );
|
||||
else if ( hasAnnotation( typeElement, EMBEDDABLE ) ) {
|
||||
context.addMetaEmbeddable( key, entity );
|
||||
}
|
||||
}
|
||||
|
||||
private void addDataMetamodelToContext(TypeElement typeElement, AnnotationMetaEntity entity) {
|
||||
final String key = entity.getQualifiedName();
|
||||
if ( hasAnnotation( typeElement, ENTITY ) ) {
|
||||
context.addDataMetaEntity( key, entity );
|
||||
}
|
||||
else if ( hasAnnotation( typeElement, MAPPED_SUPERCLASS ) ) {
|
||||
context.addDataMetaEntity( key, entity );
|
||||
}
|
||||
else if ( hasAnnotation( typeElement, EMBEDDABLE ) ) {
|
||||
context.addDataMetaEmbeddable( key, entity );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||
private final Map<String, MetaAttribute> members;
|
||||
private final Context context;
|
||||
private final boolean managed;
|
||||
private boolean dataRepository;
|
||||
private boolean jakartaDataRepository;
|
||||
private String qualifiedName;
|
||||
private final boolean jakartaDataStaticModel;
|
||||
|
||||
@ -306,7 +306,7 @@ public boolean isInjectable() {
|
||||
|
||||
@Override
|
||||
public String scope() {
|
||||
if (dataRepository) {
|
||||
if (jakartaDataRepository) {
|
||||
return context.addTransactionScopedAnnotation()
|
||||
? "javax.transaction.TransactionScoped"
|
||||
: "jakarta.enterprise.context.RequestScoped";
|
||||
@ -351,18 +351,18 @@ else if ( containsAnnotation( method, JD_INSERT, JD_UPDATE, JD_DELETE, JD_SAVE )
|
||||
}
|
||||
}
|
||||
|
||||
dataRepository = hasAnnotation( element, JD_REPOSITORY );
|
||||
jakartaDataRepository = hasAnnotation( element, JD_REPOSITORY );
|
||||
findSessionGetter( element );
|
||||
if ( !repository && dataRepository) {
|
||||
if ( !repository && jakartaDataRepository) {
|
||||
repository = true;
|
||||
sessionType = HIB_STATELESS_SESSION;
|
||||
addDaoConstructor( null );
|
||||
}
|
||||
if ( dataRepository ) {
|
||||
if ( jakartaDataRepository ) {
|
||||
addDefaultConstructor();
|
||||
}
|
||||
|
||||
if ( managed ) {
|
||||
if ( managed && !jakartaDataStaticModel ) {
|
||||
putMember( "class", new AnnotationMetaType(this) );
|
||||
}
|
||||
|
||||
@ -452,7 +452,7 @@ private String addDaoConstructor(@Nullable ExecutableElement method) {
|
||||
context.addInjectAnnotation(),
|
||||
context.addNonnullAnnotation(),
|
||||
method != null,
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
)
|
||||
);
|
||||
return sessionType;
|
||||
@ -822,7 +822,7 @@ else if ( !context.getTypeUtils().isSameType( typeArgument, entity.asType() ) )
|
||||
enabledFetchProfiles( method ),
|
||||
orderByList( method, entity ),
|
||||
context.addNonnullAnnotation(),
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -976,7 +976,7 @@ && matchesNaturalKey( method, entity ) ) {
|
||||
sessionType[1],
|
||||
enabledFetchProfiles( method ),
|
||||
context.addNonnullAnnotation(),
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -996,7 +996,7 @@ && matchesNaturalKey( method, entity ) ) {
|
||||
enabledFetchProfiles( method ),
|
||||
orderByList( method, entity ),
|
||||
context.addNonnullAnnotation(),
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -1029,7 +1029,7 @@ private void createSingleParameterFinder(ExecutableElement method, TypeMirror re
|
||||
sessionType[1],
|
||||
profiles,
|
||||
context.addNonnullAnnotation(),
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
)
|
||||
);
|
||||
break;
|
||||
@ -1047,7 +1047,7 @@ private void createSingleParameterFinder(ExecutableElement method, TypeMirror re
|
||||
sessionType[1],
|
||||
profiles,
|
||||
context.addNonnullAnnotation(),
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
)
|
||||
);
|
||||
break;
|
||||
@ -1067,7 +1067,7 @@ private void createSingleParameterFinder(ExecutableElement method, TypeMirror re
|
||||
profiles,
|
||||
orderByList( method, entity ),
|
||||
context.addNonnullAnnotation(),
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
)
|
||||
);
|
||||
break;
|
||||
@ -1302,7 +1302,7 @@ private void addQueryMethod(
|
||||
sessionType[0],
|
||||
sessionType[1],
|
||||
context.addNonnullAnnotation(),
|
||||
dataRepository
|
||||
jakartaDataRepository
|
||||
);
|
||||
putMember( attribute.getPropertyName() + paramTypes, attribute );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user