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
*/
public final class ClassWriter {
private static final String META_MODEL_CLASS_NAME_SUFFIX = "_";
private ClassWriter() {
}
@ -51,7 +50,7 @@ public final class ClassWriter {
String body = generateBody( entity, context ).toString();
FileObject fo = context.getProcessingEnvironment().getFiler().createSourceFile(
getFullyQualifiedClassName( entity, metaModelPackage ),
getFullyQualifiedClassName( entity, metaModelPackage, context ),
entity.getElement()
);
OutputStream os = fo.openOutputStream();
@ -96,7 +95,7 @@ public final class ClassWriter {
pw.println( writeDependentAnnotation( entity ) );
}
if ( entity.getElement() instanceof TypeElement ) {
pw.println( writeStaticMetaModelAnnotation( entity ) );
pw.println( writeStaticMetaModelAnnotation( entity, context ) );
}
if ( context.addGeneratedAnnotation() ) {
pw.println( writeGeneratedAnnotation( entity, context ) );
@ -131,11 +130,11 @@ public final class ClassWriter {
private static void printClassDeclaration(Metamodel entity, PrintWriter pw, Context context) {
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 );
if ( superClassName != null ) {
pw.print( " extends " + superClassName + META_MODEL_CLASS_NAME_SUFFIX );
pw.print( " extends " + generatedClassName( context, superClassName ) );
}
if ( entity.isImplementation() ) {
pw.print( entity.getElement().getKind() == ElementKind.CLASS ? " extends " : " implements " );
@ -145,13 +144,16 @@ public final class ClassWriter {
pw.println( " {" );
}
private static String generatedClassName(Context context, String superClassName) {
return context.useJakartaDataStyle() ? '_' + superClassName : superClassName + '_';
}
private static @Nullable String findMappedSuperClass(Metamodel entity, Context context) {
Element element = entity.getElement();
if ( element instanceof TypeElement ) {
TypeMirror superClass = ((TypeElement) element).getSuperclass();
//superclass of Object is of NoType which returns some other kind
while ( superClass.getKind() == TypeKind.DECLARED ) {
//F..king Ch...t Have those people used their horrible APIs even once?
final Element superClassElement = ( (DeclaredType) superClass ).asElement();
String superClassName = ( (TypeElement) superClassElement ).getQualifiedName().toString();
if ( extendsSuperMetaModel( superClassElement, entity.isMetaComplete(), context ) ) {
@ -195,12 +197,12 @@ public final class ClassWriter {
return false;
}
private static String getFullyQualifiedClassName(Metamodel entity, String metaModelPackage) {
private static String getFullyQualifiedClassName(Metamodel entity, String metaModelPackage, Context context) {
String fullyQualifiedClassName = "";
if ( !metaModelPackage.isEmpty() ) {
fullyQualifiedClassName = fullyQualifiedClassName + metaModelPackage + ".";
}
fullyQualifiedClassName = fullyQualifiedClassName + entity.getSimpleName() + META_MODEL_CLASS_NAME_SUFFIX;
fullyQualifiedClassName = fullyQualifiedClassName + generatedClassName( context, entity.getSimpleName() );
return fullyQualifiedClassName;
}
@ -230,15 +232,17 @@ public final class ClassWriter {
}
private static String writeSuppressWarnings() {
return "@SuppressWarnings({ \"deprecation\", \"rawtypes\" })";
return "@SuppressWarnings({\"deprecation\", \"rawtypes\"})";
}
private static String writeDependentAnnotation(Metamodel entity) {
return "@" + entity.importType( "jakarta.enterprise.context.Dependent" );
}
private static String writeStaticMetaModelAnnotation(Metamodel entity) {
return "@" + entity.importType( "jakarta.persistence.metamodel.StaticMetamodel" )
+ "(" + entity.getSimpleName() + ".class)";
private static String writeStaticMetaModelAnnotation(Metamodel entity, Context context) {
final String annotation = context.useJakartaDataStyle()
? "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 addSuppressWarningsAnnotation;
private AccessType persistenceUnitDefaultAccessType;
private boolean jakartaDataStyle;
// keep track of all classes for which model have been generated
private final Collection<String> generatedModelClasses = new HashSet<>();
@ -119,6 +120,13 @@ public final class Context {
return processingEnvironment;
}
public boolean useJakartaDataStyle() {
return jakartaDataStyle;
}
public void setJakartaDataStyle(boolean jakartaDataStyle) {
this.jakartaDataStyle = jakartaDataStyle;
}
public boolean addInjectAnnotation() {
return addInjectAnnotation;
}

View File

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

View File

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