add a jakartaDataStyle option to processor

This commit is contained in:
Gavin King 2024-02-24 11:27:21 +01:00
parent 43905c657f
commit 9aa2f631f1
4 changed files with 89 additions and 75 deletions

View File

@ -38,7 +38,6 @@ import static org.hibernate.jpamodelgen.util.TypeUtils.containsAnnotation;
* @author Hardy Ferentschik * @author Hardy Ferentschik
*/ */
public final class ClassWriter { public final class ClassWriter {
private static final String META_MODEL_CLASS_NAME_SUFFIX = "_";
private ClassWriter() { private ClassWriter() {
} }
@ -51,7 +50,7 @@ public final class ClassWriter {
String body = generateBody( entity, context ).toString(); String body = generateBody( entity, context ).toString();
FileObject fo = context.getProcessingEnvironment().getFiler().createSourceFile( FileObject fo = context.getProcessingEnvironment().getFiler().createSourceFile(
getFullyQualifiedClassName( entity, metaModelPackage ), getFullyQualifiedClassName( entity, metaModelPackage, context ),
entity.getElement() entity.getElement()
); );
OutputStream os = fo.openOutputStream(); OutputStream os = fo.openOutputStream();
@ -96,7 +95,7 @@ public final class ClassWriter {
pw.println( writeDependentAnnotation( entity ) ); pw.println( writeDependentAnnotation( entity ) );
} }
if ( entity.getElement() instanceof TypeElement ) { if ( entity.getElement() instanceof TypeElement ) {
pw.println( writeStaticMetaModelAnnotation( entity ) ); pw.println( writeStaticMetaModelAnnotation( entity, context ) );
} }
if ( context.addGeneratedAnnotation() ) { if ( context.addGeneratedAnnotation() ) {
pw.println( writeGeneratedAnnotation( entity, context ) ); pw.println( writeGeneratedAnnotation( entity, context ) );
@ -131,11 +130,11 @@ public final class ClassWriter {
private static void printClassDeclaration(Metamodel entity, PrintWriter pw, Context context) { private static void printClassDeclaration(Metamodel entity, PrintWriter pw, Context context) {
pw.print( entity.isImplementation() ? "public class " : "public abstract class " ); pw.print( entity.isImplementation() ? "public class " : "public abstract class " );
pw.print( entity.getSimpleName() + META_MODEL_CLASS_NAME_SUFFIX ); pw.print( generatedClassName( context, entity.getSimpleName() ) );
String superClassName = findMappedSuperClass( entity, context ); String superClassName = findMappedSuperClass( entity, context );
if ( superClassName != null ) { if ( superClassName != null ) {
pw.print( " extends " + superClassName + META_MODEL_CLASS_NAME_SUFFIX ); pw.print( " extends " + generatedClassName( context, superClassName ) );
} }
if ( entity.isImplementation() ) { if ( entity.isImplementation() ) {
pw.print( entity.getElement().getKind() == ElementKind.CLASS ? " extends " : " implements " ); pw.print( entity.getElement().getKind() == ElementKind.CLASS ? " extends " : " implements " );
@ -145,13 +144,16 @@ public final class ClassWriter {
pw.println( " {" ); pw.println( " {" );
} }
private static String generatedClassName(Context context, String superClassName) {
return context.useJakartaDataStyle() ? '_' + superClassName : superClassName + '_';
}
private static @Nullable String findMappedSuperClass(Metamodel entity, Context context) { private static @Nullable String findMappedSuperClass(Metamodel entity, Context context) {
Element element = entity.getElement(); Element element = entity.getElement();
if ( element instanceof TypeElement ) { if ( element instanceof TypeElement ) {
TypeMirror superClass = ((TypeElement) element).getSuperclass(); TypeMirror superClass = ((TypeElement) element).getSuperclass();
//superclass of Object is of NoType which returns some other kind //superclass of Object is of NoType which returns some other kind
while ( superClass.getKind() == TypeKind.DECLARED ) { while ( superClass.getKind() == TypeKind.DECLARED ) {
//F..king Ch...t Have those people used their horrible APIs even once?
final Element superClassElement = ( (DeclaredType) superClass ).asElement(); final Element superClassElement = ( (DeclaredType) superClass ).asElement();
String superClassName = ( (TypeElement) superClassElement ).getQualifiedName().toString(); String superClassName = ( (TypeElement) superClassElement ).getQualifiedName().toString();
if ( extendsSuperMetaModel( superClassElement, entity.isMetaComplete(), context ) ) { if ( extendsSuperMetaModel( superClassElement, entity.isMetaComplete(), context ) ) {
@ -195,12 +197,12 @@ public final class ClassWriter {
return false; return false;
} }
private static String getFullyQualifiedClassName(Metamodel entity, String metaModelPackage) { private static String getFullyQualifiedClassName(Metamodel entity, String metaModelPackage, Context context) {
String fullyQualifiedClassName = ""; String fullyQualifiedClassName = "";
if ( !metaModelPackage.isEmpty() ) { if ( !metaModelPackage.isEmpty() ) {
fullyQualifiedClassName = fullyQualifiedClassName + metaModelPackage + "."; fullyQualifiedClassName = fullyQualifiedClassName + metaModelPackage + ".";
} }
fullyQualifiedClassName = fullyQualifiedClassName + entity.getSimpleName() + META_MODEL_CLASS_NAME_SUFFIX; fullyQualifiedClassName = fullyQualifiedClassName + generatedClassName( context, entity.getSimpleName() );
return fullyQualifiedClassName; return fullyQualifiedClassName;
} }
@ -230,15 +232,17 @@ public final class ClassWriter {
} }
private static String writeSuppressWarnings() { private static String writeSuppressWarnings() {
return "@SuppressWarnings({ \"deprecation\", \"rawtypes\" })"; return "@SuppressWarnings({\"deprecation\", \"rawtypes\"})";
} }
private static String writeDependentAnnotation(Metamodel entity) { private static String writeDependentAnnotation(Metamodel entity) {
return "@" + entity.importType( "jakarta.enterprise.context.Dependent" ); return "@" + entity.importType( "jakarta.enterprise.context.Dependent" );
} }
private static String writeStaticMetaModelAnnotation(Metamodel entity) { private static String writeStaticMetaModelAnnotation(Metamodel entity, Context context) {
return "@" + entity.importType( "jakarta.persistence.metamodel.StaticMetamodel" ) final String annotation = context.useJakartaDataStyle()
+ "(" + entity.getSimpleName() + ".class)"; ? "jakarta.data.metamodel.StaticMetamodel"
: "jakarta.persistence.metamodel.StaticMetamodel";
return "@" + entity.importType( annotation ) + "(" + entity.getSimpleName() + ".class)";
} }
} }

View File

@ -74,6 +74,7 @@ public final class Context {
private boolean addGenerationDate; private boolean addGenerationDate;
private boolean addSuppressWarningsAnnotation; private boolean addSuppressWarningsAnnotation;
private AccessType persistenceUnitDefaultAccessType; private AccessType persistenceUnitDefaultAccessType;
private boolean jakartaDataStyle;
// keep track of all classes for which model have been generated // keep track of all classes for which model have been generated
private final Collection<String> generatedModelClasses = new HashSet<>(); private final Collection<String> generatedModelClasses = new HashSet<>();
@ -119,6 +120,13 @@ public final class Context {
return processingEnvironment; return processingEnvironment;
} }
public boolean useJakartaDataStyle() {
return jakartaDataStyle;
}
public void setJakartaDataStyle(boolean jakartaDataStyle) {
this.jakartaDataStyle = jakartaDataStyle;
}
public boolean addInjectAnnotation() { public boolean addInjectAnnotation() {
return addInjectAnnotation; return addInjectAnnotation;
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.jpamodelgen;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.AbstractProcessor;
@ -31,7 +32,6 @@ import javax.tools.Diagnostic;
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity; import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
import org.hibernate.jpamodelgen.annotation.AnnotationMetaPackage; import org.hibernate.jpamodelgen.annotation.AnnotationMetaPackage;
import org.hibernate.jpamodelgen.model.Metamodel; import org.hibernate.jpamodelgen.model.Metamodel;
import org.hibernate.jpamodelgen.util.Constants;
import org.hibernate.jpamodelgen.xml.JpaDescriptorParser; import org.hibernate.jpamodelgen.xml.JpaDescriptorParser;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -39,12 +39,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import static java.lang.Boolean.parseBoolean; import static java.lang.Boolean.parseBoolean;
import static javax.lang.model.util.ElementFilter.fieldsIn; import static javax.lang.model.util.ElementFilter.fieldsIn;
import static javax.lang.model.util.ElementFilter.methodsIn; import static javax.lang.model.util.ElementFilter.methodsIn;
import static org.hibernate.jpamodelgen.util.Constants.FIND; import static org.hibernate.jpamodelgen.util.Constants.*;
import static org.hibernate.jpamodelgen.util.Constants.HQL;
import static org.hibernate.jpamodelgen.util.Constants.JD_REPOSITORY;
import static org.hibernate.jpamodelgen.util.Constants.SQL;
import static org.hibernate.jpamodelgen.util.StringUtil.isProperty; import static org.hibernate.jpamodelgen.util.StringUtil.isProperty;
import static org.hibernate.jpamodelgen.util.TypeUtils.*; import static org.hibernate.jpamodelgen.util.TypeUtils.*;
import static org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.*;
/** /**
* Main annotation processor. * Main annotation processor.
@ -52,36 +50,36 @@ import static org.hibernate.jpamodelgen.util.TypeUtils.*;
* @author Max Andersen * @author Max Andersen
* @author Hardy Ferentschik * @author Hardy Ferentschik
* @author Emmanuel Bernard * @author Emmanuel Bernard
* @author Gavin King
*/ */
@SupportedAnnotationTypes({ @SupportedAnnotationTypes({
Constants.ENTITY, // standard for JPA 2
Constants.MAPPED_SUPERCLASS, ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE,
Constants.EMBEDDABLE, // standard for JPA 3.2
Constants.HQL, NAMED_QUERY, NAMED_NATIVE_QUERY, NAMED_ENTITY_GRAPH, SQL_RESULT_SET_MAPPING,
Constants.SQL, // extra for Hibernate
Constants.FIND, HIB_FETCH_PROFILE, HIB_FILTER_DEF, HIB_NAMED_QUERY, HIB_NAMED_NATIVE_QUERY,
Constants.NAMED_QUERY, // Hibernate query methods
Constants.NAMED_NATIVE_QUERY, HQL, SQL, FIND,
Constants.NAMED_ENTITY_GRAPH, // Jakarta Data repositories
Constants.SQL_RESULT_SET_MAPPING, JD_REPOSITORY // do not need to list any other Jakarta Data annotations here
Constants.HIB_FETCH_PROFILE,
Constants.HIB_FILTER_DEF,
Constants.HIB_NAMED_QUERY,
Constants.HIB_NAMED_NATIVE_QUERY,
// do not need to list other Jakarta Data annotations here
Constants.JD_REPOSITORY
}) })
@SupportedOptions({ @SupportedOptions({
JPAMetaModelEntityProcessor.DEBUG_OPTION, DEBUG_OPTION,
JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION, PERSISTENCE_XML_OPTION,
JPAMetaModelEntityProcessor.ORM_XML_OPTION, ORM_XML_OPTION,
JPAMetaModelEntityProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION, FULLY_ANNOTATION_CONFIGURED_OPTION,
JPAMetaModelEntityProcessor.LAZY_XML_PARSING, LAZY_XML_PARSING,
JPAMetaModelEntityProcessor.ADD_GENERATION_DATE, ADD_GENERATION_DATE,
JPAMetaModelEntityProcessor.ADD_GENERATED_ANNOTATION, ADD_GENERATED_ANNOTATION,
JPAMetaModelEntityProcessor.ADD_SUPPRESS_WARNINGS_ANNOTATION ADD_SUPPRESS_WARNINGS_ANNOTATION,
JAKARTA_DATA_OPTION
}) })
public class JPAMetaModelEntityProcessor extends AbstractProcessor { public class JPAMetaModelEntityProcessor extends AbstractProcessor {
/**
* Produce Jakarta Data style static metamodel
*/
public static final String JAKARTA_DATA_OPTION = "jakartaDataStyle";
/** /**
* Debug logging from the processor * Debug logging from the processor
*/ */
@ -134,7 +132,7 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
context = new Context( processingEnvironment ); context = new Context( processingEnvironment );
context.logMessage( context.logMessage(
Diagnostic.Kind.NOTE, Diagnostic.Kind.NOTE,
"Hibernate/JPA static Metamodel Generator " + Version.getVersionString() "Hibernate compile-time tooling " + Version.getVersionString()
); );
boolean fullyAnnotationConfigured = handleSettings( processingEnvironment ); boolean fullyAnnotationConfigured = handleSettings( processingEnvironment );
@ -173,6 +171,8 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
context.setAddSuppressWarningsAnnotation( parseBoolean( options.get( ADD_SUPPRESS_WARNINGS_ANNOTATION ) ) ); context.setAddSuppressWarningsAnnotation( parseBoolean( options.get( ADD_SUPPRESS_WARNINGS_ANNOTATION ) ) );
context.setJakartaDataStyle( parseBoolean( options.get( JAKARTA_DATA_OPTION ) ) );
return parseBoolean( options.get( FULLY_ANNOTATION_CONFIGURED_OPTION ) ); return parseBoolean( options.get( FULLY_ANNOTATION_CONFIGURED_OPTION ) );
} }
@ -337,16 +337,18 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
new ContainsAttributeTypeVisitor( (TypeElement) element, context ); new ContainsAttributeTypeVisitor( (TypeElement) element, context );
for ( Metamodel entity : entities ) { for ( Metamodel entity : entities ) {
if ( !entity.equals( containedEntity ) ) { if ( !entity.equals( containedEntity ) ) {
for ( Element subElement : fieldsIn( entity.getElement().getEnclosedElements() ) ) { final List<? extends Element> enclosedElements =
TypeMirror mirror = subElement.asType(); entity.getElement().getEnclosedElements();
for ( Element subElement : fieldsIn(enclosedElements) ) {
final TypeMirror mirror = subElement.asType();
if ( TypeKind.DECLARED == mirror.getKind() ) { if ( TypeKind.DECLARED == mirror.getKind() ) {
if ( mirror.accept( visitor, subElement ) ) { if ( mirror.accept( visitor, subElement ) ) {
return true; return true;
} }
} }
} }
for ( Element subElement : methodsIn( entity.getElement().getEnclosedElements() ) ) { for ( Element subElement : methodsIn(enclosedElements) ) {
TypeMirror mirror = subElement.asType(); final TypeMirror mirror = subElement.asType();
if ( TypeKind.DECLARED == mirror.getKind() ) { if ( TypeKind.DECLARED == mirror.getKind() ) {
if ( mirror.accept( visitor, subElement ) ) { if ( mirror.accept( visitor, subElement ) ) {
return true; return true;
@ -362,31 +364,31 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
private static boolean isEntityOrEmbeddable(Element element) { private static boolean isEntityOrEmbeddable(Element element) {
return containsAnnotation( return containsAnnotation(
element, element,
Constants.ENTITY, ENTITY,
Constants.MAPPED_SUPERCLASS, MAPPED_SUPERCLASS,
Constants.EMBEDDABLE EMBEDDABLE
); );
} }
private boolean hasAuxiliaryAnnotations(Element element) { private boolean hasAuxiliaryAnnotations(Element element) {
return containsAnnotation( return containsAnnotation(
element, element,
Constants.NAMED_QUERY, NAMED_QUERY,
Constants.NAMED_QUERIES, NAMED_QUERIES,
Constants.NAMED_NATIVE_QUERY, NAMED_NATIVE_QUERY,
Constants.NAMED_NATIVE_QUERIES, NAMED_NATIVE_QUERIES,
Constants.SQL_RESULT_SET_MAPPING, SQL_RESULT_SET_MAPPING,
Constants.SQL_RESULT_SET_MAPPINGS, SQL_RESULT_SET_MAPPINGS,
Constants.NAMED_ENTITY_GRAPH, NAMED_ENTITY_GRAPH,
Constants.NAMED_ENTITY_GRAPHS, NAMED_ENTITY_GRAPHS,
Constants.HIB_NAMED_QUERY, HIB_NAMED_QUERY,
Constants.HIB_NAMED_QUERIES, HIB_NAMED_QUERIES,
Constants.HIB_NAMED_NATIVE_QUERY, HIB_NAMED_NATIVE_QUERY,
Constants.HIB_NAMED_NATIVE_QUERIES, HIB_NAMED_NATIVE_QUERIES,
Constants.HIB_FETCH_PROFILE, HIB_FETCH_PROFILE,
Constants.HIB_FETCH_PROFILES, HIB_FETCH_PROFILES,
Constants.HIB_FILTER_DEF, HIB_FILTER_DEF,
Constants.HIB_FILTER_DEFS HIB_FILTER_DEFS
); );
} }
@ -404,8 +406,8 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
} }
else { else {
boolean requiresLazyMemberInitialization boolean requiresLazyMemberInitialization
= containsAnnotation( element, Constants.EMBEDDABLE ) = containsAnnotation( element, EMBEDDABLE )
|| containsAnnotation( element, Constants.MAPPED_SUPERCLASS ); || containsAnnotation( element, MAPPED_SUPERCLASS );
final AnnotationMetaEntity metaEntity = final AnnotationMetaEntity metaEntity =
AnnotationMetaEntity.create( typeElement, context, requiresLazyMemberInitialization, true ); AnnotationMetaEntity.create( typeElement, context, requiresLazyMemberInitialization, true );
if ( alreadyExistingMetaEntity != null ) { if ( alreadyExistingMetaEntity != null ) {
@ -432,24 +434,24 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
} }
private @Nullable Metamodel tryGettingExistingEntityFromContext(AnnotationMirror mirror, String qualifiedName) { private @Nullable Metamodel tryGettingExistingEntityFromContext(AnnotationMirror mirror, String qualifiedName) {
if ( isAnnotationMirrorOfType( mirror, Constants.ENTITY ) if ( isAnnotationMirrorOfType( mirror, ENTITY )
|| isAnnotationMirrorOfType( mirror, Constants.MAPPED_SUPERCLASS ) ) { || isAnnotationMirrorOfType( mirror, MAPPED_SUPERCLASS ) ) {
return context.getMetaEntity( qualifiedName ); return context.getMetaEntity( qualifiedName );
} }
else if ( isAnnotationMirrorOfType( mirror, Constants.EMBEDDABLE ) ) { else if ( isAnnotationMirrorOfType( mirror, EMBEDDABLE ) ) {
return context.getMetaEmbeddable( qualifiedName ); return context.getMetaEmbeddable( qualifiedName );
} }
return null; return null;
} }
private void addMetaEntityToContext(AnnotationMirror mirror, AnnotationMetaEntity metaEntity) { private void addMetaEntityToContext(AnnotationMirror mirror, AnnotationMetaEntity metaEntity) {
if ( isAnnotationMirrorOfType( mirror, Constants.ENTITY ) ) { if ( isAnnotationMirrorOfType( mirror, ENTITY ) ) {
context.addMetaEntity( metaEntity.getQualifiedName(), metaEntity ); context.addMetaEntity( metaEntity.getQualifiedName(), metaEntity );
} }
else if ( isAnnotationMirrorOfType( mirror, Constants.MAPPED_SUPERCLASS ) ) { else if ( isAnnotationMirrorOfType( mirror, MAPPED_SUPERCLASS ) ) {
context.addMetaEntity( metaEntity.getQualifiedName(), metaEntity ); context.addMetaEntity( metaEntity.getQualifiedName(), metaEntity );
} }
else if ( isAnnotationMirrorOfType( mirror, Constants.EMBEDDABLE ) ) { else if ( isAnnotationMirrorOfType( mirror, EMBEDDABLE ) ) {
context.addMetaEmbeddable( metaEntity.getQualifiedName(), metaEntity ); context.addMetaEmbeddable( metaEntity.getQualifiedName(), metaEntity );
} }
} }
@ -470,7 +472,7 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
TypeElement returnedElement = (TypeElement) context.getTypeUtils().asElement( declaredType ); TypeElement returnedElement = (TypeElement) context.getTypeUtils().asElement( declaredType );
final String fqNameOfReturnType = returnedElement.getQualifiedName().toString(); final String fqNameOfReturnType = returnedElement.getQualifiedName().toString();
final String collection = Constants.COLLECTIONS.get( fqNameOfReturnType ); final String collection = COLLECTIONS.get( fqNameOfReturnType );
if ( collection != null ) { if ( collection != null ) {
final TypeMirror collectionElementType = final TypeMirror collectionElementType =
getCollectionElementType( declaredType, fqNameOfReturnType, null, context ); getCollectionElementType( declaredType, fqNameOfReturnType, null, context );

View File

@ -32,7 +32,7 @@ public class SuppressWarningsAnnotationGeneratedTest extends CompilationTest {
String metaModelSource = getMetaModelSourceAsString( TestEntity.class ); String metaModelSource = getMetaModelSourceAsString( TestEntity.class );
assertTrue( assertTrue(
"@SuppressWarnings should be added to the metamodel.", "@SuppressWarnings should be added to the metamodel.",
metaModelSource.contains( "@SuppressWarnings({ \"deprecation\", \"rawtypes\" })" ) metaModelSource.contains( "@SuppressWarnings({\"deprecation\", \"rawtypes\"})" )
); );
} }
} }