HHH-18693 Changed code to allow creation of metadata for inner static non-private classes
Generaed metadate class for inner class A.B is A_.B_
This commit is contained in:
parent
d91d87c516
commit
d3a1ebd0e2
|
@ -4,11 +4,16 @@
|
|||
*/
|
||||
package org.hibernate.processor;
|
||||
|
||||
import org.hibernate.processor.annotation.InnerClassMetaAttribute;
|
||||
import org.hibernate.processor.model.MetaAttribute;
|
||||
import org.hibernate.processor.model.Metamodel;
|
||||
import org.hibernate.processor.util.StringUtil;
|
||||
|
||||
import javax.annotation.processing.FilerException;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.FileObject;
|
||||
|
@ -18,7 +23,12 @@ import java.io.PrintWriter;
|
|||
import java.io.StringWriter;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hibernate.processor.util.TypeUtils.isMemberType;
|
||||
|
||||
/**
|
||||
* Helper class to write the actual metamodel class using the {@link javax.annotation.processing.Filer} API.
|
||||
|
@ -39,7 +49,7 @@ public final class ClassWriter {
|
|||
String body = generateBody( entity, context ).toString();
|
||||
|
||||
FileObject fo = context.getProcessingEnvironment().getFiler().createSourceFile(
|
||||
getFullyQualifiedClassName( entity, metaModelPackage ),
|
||||
getFullyQualifiedClassName( entity ),
|
||||
entity.getElement()
|
||||
);
|
||||
OutputStream os = fo.openOutputStream();
|
||||
|
@ -101,6 +111,15 @@ public final class ClassWriter {
|
|||
pw.println();
|
||||
|
||||
final List<MetaAttribute> members = entity.getMembers();
|
||||
for ( MetaAttribute metaMember : members ) {
|
||||
if ( metaMember instanceof InnerClassMetaAttribute innerClass ) {
|
||||
generateBody( innerClass.getMetaEntity(), context )
|
||||
.toString().lines()
|
||||
.forEach(line -> pw.println('\t' + line));
|
||||
context.markGenerated( innerClass.getMetaEntity() );
|
||||
}
|
||||
}
|
||||
|
||||
for ( MetaAttribute metaMember : members ) {
|
||||
if ( metaMember.hasStringAttribute() ) {
|
||||
metaMember.getAttributeNameDeclarationString().lines()
|
||||
|
@ -133,16 +152,29 @@ public final class ClassWriter {
|
|||
}
|
||||
|
||||
private static void printClassDeclaration(Metamodel entity, PrintWriter pw) {
|
||||
if ( isMemberType( entity.getElement() ) ) {
|
||||
final Set<Modifier> modifiers = entity.getElement().getModifiers();
|
||||
if ( modifiers.contains( Modifier.PUBLIC ) ) {
|
||||
pw.print( "public " );
|
||||
}
|
||||
else if ( modifiers.contains( Modifier.PROTECTED ) ) {
|
||||
pw.print( "protected " );
|
||||
}
|
||||
pw.print( "static " );
|
||||
}
|
||||
else {
|
||||
pw.print( "public " );
|
||||
}
|
||||
if ( !entity.isImplementation() && !entity.isJakartaDataStyle() ) {
|
||||
pw.print( "abstract " );
|
||||
}
|
||||
pw.print( entity.isJakartaDataStyle() ? "interface " : "class " );
|
||||
pw.print( getGeneratedClassName(entity) );
|
||||
|
||||
String superClassName = entity.getSupertypeName();
|
||||
if ( superClassName != null ) {
|
||||
pw.print( " extends " + getGeneratedSuperclassName(entity, superClassName) );
|
||||
final Element superTypeElement = entity.getSuperTypeElement();
|
||||
if ( superTypeElement != null ) {
|
||||
pw.print( " extends " +
|
||||
entity.importType(getGeneratedSuperclassName( superTypeElement, entity.isJakartaDataStyle() )) );
|
||||
}
|
||||
if ( entity.isImplementation() ) {
|
||||
pw.print( entity.getElement().getKind() == ElementKind.CLASS ? " extends " : " implements " );
|
||||
|
@ -152,13 +184,21 @@ public final class ClassWriter {
|
|||
pw.println( " {" );
|
||||
}
|
||||
|
||||
private static String getFullyQualifiedClassName(Metamodel entity, String metaModelPackage) {
|
||||
String fullyQualifiedClassName = "";
|
||||
if ( !metaModelPackage.isEmpty() ) {
|
||||
fullyQualifiedClassName = fullyQualifiedClassName + metaModelPackage + ".";
|
||||
private static String getFullyQualifiedClassName(Metamodel entity) {
|
||||
final String metaModelPackage = entity.getPackageName();
|
||||
final String packageNamePrefix = !metaModelPackage.isEmpty() ? metaModelPackage + "." : "";
|
||||
final String className;
|
||||
if ( entity.getElement().getKind() == ElementKind.PACKAGE ) {
|
||||
className = getGeneratedClassName( entity );
|
||||
}
|
||||
fullyQualifiedClassName = fullyQualifiedClassName + getGeneratedClassName( entity );
|
||||
return fullyQualifiedClassName;
|
||||
else {
|
||||
className = Arrays.stream(
|
||||
entity.getQualifiedName().substring( packageNamePrefix.length() ).split( "\\." ) )
|
||||
.map( StringUtil::removeDollar )
|
||||
.map( part -> entity.isJakartaDataStyle() ? '_' + part : part + '_' )
|
||||
.collect( Collectors.joining( "." ) );
|
||||
}
|
||||
return packageNamePrefix + className;
|
||||
}
|
||||
|
||||
private static String getGeneratedClassName(Metamodel entity) {
|
||||
|
@ -166,20 +206,14 @@ public final class ClassWriter {
|
|||
return entity.isJakartaDataStyle() ? '_' + className : className + '_';
|
||||
}
|
||||
|
||||
private static String getGeneratedSuperclassName(Metamodel entity, String superClassName) {
|
||||
if ( entity.isJakartaDataStyle() ) {
|
||||
int lastDot = superClassName.lastIndexOf('.');
|
||||
if ( lastDot<0 ) {
|
||||
return '_' + superClassName;
|
||||
}
|
||||
else {
|
||||
return superClassName.substring(0,lastDot+1)
|
||||
+ '_' + superClassName.substring(lastDot+1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return superClassName + '_';
|
||||
}
|
||||
private static String getGeneratedSuperclassName(Element superClassElement, boolean jakartaDataStyle) {
|
||||
final TypeElement typeElement = (TypeElement) superClassElement;
|
||||
final String simpleName = typeElement.getSimpleName().toString();
|
||||
final Element enclosingElement = typeElement.getEnclosingElement();
|
||||
return (enclosingElement instanceof TypeElement
|
||||
? getGeneratedSuperclassName( enclosingElement, jakartaDataStyle )
|
||||
: ((PackageElement) enclosingElement).getQualifiedName().toString())
|
||||
+ "." + (jakartaDataStyle ? '_' + simpleName : simpleName + '_');
|
||||
}
|
||||
|
||||
private static String writeGeneratedAnnotation(Metamodel entity, Context context) {
|
||||
|
@ -227,6 +261,7 @@ public final class ClassWriter {
|
|||
final String annotation = entity.isJakartaDataStyle()
|
||||
? "jakarta.data.metamodel.StaticMetamodel"
|
||||
: "jakarta.persistence.metamodel.StaticMetamodel";
|
||||
return "@" + entity.importType( annotation ) + "(" + entity.getSimpleName() + ".class)";
|
||||
final String simpleName = entity.importType( entity.getQualifiedName() );
|
||||
return "@" + entity.importType( annotation ) + "(" + simpleName + ".class)";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,6 +304,15 @@ public final class Context {
|
|||
return dataMetaEmbeddables.values();
|
||||
}
|
||||
|
||||
public @Nullable Metamodel getMetamodel(String qualifiedName) {
|
||||
if ( metaEntities.containsKey( qualifiedName ) ) {
|
||||
return metaEntities.get( qualifiedName );
|
||||
}
|
||||
else {
|
||||
return metaEmbeddables.get( qualifiedName );
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable Metamodel getMetaAuxiliary(String qualifiedName) {
|
||||
return metaAuxiliaries.get( qualifiedName );
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.hibernate.processor;
|
|||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.processor.annotation.AnnotationMetaEntity;
|
||||
import org.hibernate.processor.annotation.AnnotationMetaPackage;
|
||||
import org.hibernate.processor.annotation.NonManagedMetamodel;
|
||||
import org.hibernate.processor.model.Metamodel;
|
||||
import org.hibernate.processor.util.Constants;
|
||||
import org.hibernate.processor.xml.JpaDescriptorParser;
|
||||
|
@ -22,6 +23,7 @@ import javax.lang.model.element.AnnotationValue;
|
|||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.element.QualifiedNameable;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
@ -82,6 +84,7 @@ import static org.hibernate.processor.util.TypeUtils.getAnnotationMirror;
|
|||
import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
|
||||
import static org.hibernate.processor.util.TypeUtils.hasAnnotation;
|
||||
import static org.hibernate.processor.util.TypeUtils.isClassOrRecordType;
|
||||
import static org.hibernate.processor.util.TypeUtils.isMemberType;
|
||||
|
||||
/**
|
||||
* Main annotation processor.
|
||||
|
@ -358,15 +361,22 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
}
|
||||
|
||||
for ( Element element : roundEnvironment.getRootElements() ) {
|
||||
processElement( element, null );
|
||||
}
|
||||
}
|
||||
|
||||
private void processElement(Element element, @Nullable Element parent) {
|
||||
try {
|
||||
if ( !included( element )
|
||||
|| hasAnnotation( element, Constants.EXCLUDE )
|
||||
|| hasPackageAnnotation( element, Constants.EXCLUDE ) ) {
|
||||
|| hasPackageAnnotation( element, Constants.EXCLUDE )
|
||||
|| element.getModifiers().contains( Modifier.PRIVATE ) ) {
|
||||
// skip it completely
|
||||
return;
|
||||
}
|
||||
else if ( isEntityOrEmbeddable( element ) ) {
|
||||
else if ( isEntityOrEmbeddable( element ) && !element.getModifiers().contains( Modifier.PRIVATE )) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated entity class '" + element + "'" );
|
||||
handleRootElementAnnotationMirrors( element );
|
||||
handleRootElementAnnotationMirrors( element, parent );
|
||||
}
|
||||
else if ( hasAuxiliaryAnnotations( element ) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
|
||||
|
@ -398,6 +408,42 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ( enclosesEntityOrEmbeddable( element ) ) {
|
||||
AnnotationMetaEntity parentMeta = null;
|
||||
if ( parent instanceof TypeElement parentElement ) {
|
||||
final String key = parentElement.getQualifiedName().toString();
|
||||
if ( context.getMetamodel( key ) instanceof AnnotationMetaEntity parentMetaEntity ) {
|
||||
parentMeta = parentMetaEntity;
|
||||
}
|
||||
}
|
||||
final NonManagedMetamodel metaEntity =
|
||||
NonManagedMetamodel .create(
|
||||
typeElement, context,
|
||||
false, parentMeta );
|
||||
context.addMetaEntity( metaEntity.getQualifiedName(), metaEntity );
|
||||
if ( context.generateJakartaDataStaticMetamodel()) {
|
||||
AnnotationMetaEntity parentDataMeta = null;
|
||||
if ( parent instanceof TypeElement parentElement ) {
|
||||
final String key = parentElement.getQualifiedName().toString();
|
||||
if ( context.getDataMetaEntity( key ) instanceof AnnotationMetaEntity parentMetaEntity ) {
|
||||
parentDataMeta = parentMetaEntity;
|
||||
}
|
||||
}
|
||||
final NonManagedMetamodel dataMetaEntity =
|
||||
NonManagedMetamodel .create(
|
||||
typeElement, context,
|
||||
true, parentDataMeta );
|
||||
context.addDataMetaEntity( dataMetaEntity.getQualifiedName(), dataMetaEntity );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( isClassOrRecordType( element ) ) {
|
||||
for ( final Element child : element.getEnclosedElements() ) {
|
||||
if ( isClassOrRecordType( child ) ) {
|
||||
processElement( child, element );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +457,6 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasPackageAnnotation(Element element, String annotation) {
|
||||
final PackageElement pack = context.getElementUtils().getPackageOf( element ); // null for module descriptor
|
||||
|
@ -430,7 +475,7 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
}
|
||||
|
||||
for ( Metamodel entity : context.getMetaEntities() ) {
|
||||
if ( !context.isAlreadyGenerated(entity) ) {
|
||||
if ( !context.isAlreadyGenerated( entity ) && !isMemberType( entity.getElement() ) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER,
|
||||
"Writing Jakarta Persistence metamodel for entity '" + entity + "'" );
|
||||
ClassWriter.writeFile( entity, context );
|
||||
|
@ -439,7 +484,7 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
}
|
||||
|
||||
for ( Metamodel entity : context.getDataMetaEntities() ) {
|
||||
if ( !context.isAlreadyGenerated(entity) ) {
|
||||
if ( !context.isAlreadyGenerated( entity ) && !isMemberType( entity.getElement() ) ) {
|
||||
context.logMessage( Diagnostic.Kind.OTHER,
|
||||
"Writing Jakarta Data metamodel for entity '" + entity + "'" );
|
||||
ClassWriter.writeFile( entity, context );
|
||||
|
@ -516,6 +561,18 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static boolean enclosesEntityOrEmbeddable(Element element) {
|
||||
if ( !(element instanceof TypeElement typeElement) ) {
|
||||
return false;
|
||||
}
|
||||
for ( final Element enclosedElement : typeElement.getEnclosedElements() ) {
|
||||
if ( isEntityOrEmbeddable( enclosedElement ) || enclosesEntityOrEmbeddable( enclosedElement ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isEntityOrEmbeddable(Element element) {
|
||||
return hasAnnotation(
|
||||
element,
|
||||
|
@ -547,7 +604,7 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
);
|
||||
}
|
||||
|
||||
private void handleRootElementAnnotationMirrors(final Element element) {
|
||||
private void handleRootElementAnnotationMirrors(final Element element, @Nullable Element parent) {
|
||||
if ( isClassOrRecordType( element ) ) {
|
||||
if ( isEntityOrEmbeddable( element ) ) {
|
||||
final TypeElement typeElement = (TypeElement) element;
|
||||
|
@ -564,12 +621,20 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
+ "' since XML configuration is metadata complete.");
|
||||
}
|
||||
else {
|
||||
AnnotationMetaEntity parentMetaEntity = null;
|
||||
if ( parent instanceof TypeElement parentTypeElement ) {
|
||||
if ( context.getMetamodel(
|
||||
parentTypeElement.getQualifiedName().toString() )
|
||||
instanceof AnnotationMetaEntity pme ) {
|
||||
parentMetaEntity = pme;
|
||||
}
|
||||
}
|
||||
final boolean requiresLazyMemberInitialization
|
||||
= hasAnnotation( element, EMBEDDABLE, MAPPED_SUPERCLASS );
|
||||
final AnnotationMetaEntity metaEntity =
|
||||
AnnotationMetaEntity.create( typeElement, context,
|
||||
requiresLazyMemberInitialization,
|
||||
true, false );
|
||||
true, false, parentMetaEntity );
|
||||
if ( alreadyExistingMetaEntity != null ) {
|
||||
metaEntity.mergeInMembers( alreadyExistingMetaEntity );
|
||||
}
|
||||
|
@ -583,10 +648,17 @@ public class HibernateProcessor extends AbstractProcessor {
|
|||
// let a handwritten metamodel "override" the generated one
|
||||
// (this is used in the Jakarta Data TCK)
|
||||
&& !hasHandwrittenMetamodel(element) ) {
|
||||
AnnotationMetaEntity parentDataEntity = null;
|
||||
if ( parent instanceof TypeElement parentTypeElement ) {
|
||||
if ( context.getDataMetaEntity( parentTypeElement.getQualifiedName().toString() )
|
||||
instanceof AnnotationMetaEntity pme ) {
|
||||
parentDataEntity = pme;
|
||||
}
|
||||
}
|
||||
final AnnotationMetaEntity dataMetaEntity =
|
||||
AnnotationMetaEntity.create( typeElement, context,
|
||||
requiresLazyMemberInitialization,
|
||||
true, true );
|
||||
true, true, parentDataEntity );
|
||||
// final Metamodel alreadyExistingDataMetaEntity =
|
||||
// tryGettingExistingDataEntityFromContext( mirror, '_' + qualifiedName );
|
||||
// if ( alreadyExistingDataMetaEntity != null ) {
|
||||
|
|
|
@ -80,11 +80,12 @@ import static org.hibernate.processor.annotation.QueryMethod.isOrderParam;
|
|||
import static org.hibernate.processor.annotation.QueryMethod.isPageParam;
|
||||
import static org.hibernate.processor.util.Constants.*;
|
||||
import static org.hibernate.processor.util.NullnessUtil.castNonNull;
|
||||
import static org.hibernate.processor.util.StringUtil.removeDollar;
|
||||
import static org.hibernate.processor.util.TypeUtils.containsAnnotation;
|
||||
import static org.hibernate.processor.util.TypeUtils.determineAccessTypeForHierarchy;
|
||||
import static org.hibernate.processor.util.TypeUtils.determineAnnotationSpecifiedAccessType;
|
||||
import static org.hibernate.processor.util.TypeUtils.extendsClass;
|
||||
import static org.hibernate.processor.util.TypeUtils.findMappedSuperClass;
|
||||
import static org.hibernate.processor.util.TypeUtils.findMappedSuperElement;
|
||||
import static org.hibernate.processor.util.TypeUtils.getAnnotationMirror;
|
||||
import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
|
||||
import static org.hibernate.processor.util.TypeUtils.hasAnnotation;
|
||||
|
@ -110,6 +111,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
private final ImportContext importContext;
|
||||
private final TypeElement element;
|
||||
private final Map<String, MetaAttribute> members;
|
||||
private TypeElement parentElement;
|
||||
private final Context context;
|
||||
private final boolean managed;
|
||||
private boolean jakartaDataRepository;
|
||||
|
@ -163,26 +165,32 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
|
||||
public AnnotationMetaEntity(
|
||||
TypeElement element, Context context, boolean managed,
|
||||
boolean jakartaDataStaticMetamodel) {
|
||||
boolean jakartaDataStaticMetamodel,
|
||||
@Nullable AnnotationMeta parent) {
|
||||
this.element = element;
|
||||
this.context = context;
|
||||
this.managed = managed;
|
||||
this.members = new HashMap<>();
|
||||
this.quarkusInjection = context.isQuarkusInjection();
|
||||
this.importContext = new ImportContextImpl( getPackageName( context, element ) );
|
||||
this.importContext = parent != null ? parent : new ImportContextImpl( getPackageName( context, element ) );
|
||||
jakartaDataStaticModel = jakartaDataStaticMetamodel;
|
||||
}
|
||||
|
||||
public static AnnotationMetaEntity create(TypeElement element, Context context) {
|
||||
return create( element,context, false, false, false );
|
||||
return create( element,context, false, false, false, null );
|
||||
}
|
||||
|
||||
public static AnnotationMetaEntity create(
|
||||
TypeElement element, Context context,
|
||||
boolean lazilyInitialised, boolean managed,
|
||||
boolean jakartaData) {
|
||||
boolean jakartaData,
|
||||
@Nullable AnnotationMetaEntity parent) {
|
||||
final AnnotationMetaEntity annotationMetaEntity =
|
||||
new AnnotationMetaEntity( element, context, managed, jakartaData );
|
||||
new AnnotationMetaEntity( element, context, managed, jakartaData, parent );
|
||||
if ( parent != null ) {
|
||||
annotationMetaEntity.setParentElement( parent.element );
|
||||
parent.addInnerClass( annotationMetaEntity );
|
||||
}
|
||||
if ( !lazilyInitialised ) {
|
||||
annotationMetaEntity.init();
|
||||
}
|
||||
|
@ -225,18 +233,6 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
return getSimpleName() + '_';
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is an "intermediate" class providing {@code @Query}
|
||||
* annotations for the query by magical method name crap, then
|
||||
* by convention it will be named with a trailing $ sign. Strip
|
||||
* that off, so we get the standard constructor.
|
||||
*/
|
||||
private static String removeDollar(String simpleName) {
|
||||
return simpleName.endsWith("$")
|
||||
? simpleName.substring(0, simpleName.length()-1)
|
||||
: simpleName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getQualifiedName() {
|
||||
if ( qualifiedName == null ) {
|
||||
|
@ -246,8 +242,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getSupertypeName() {
|
||||
return repository ? null : findMappedSuperClass( this, context );
|
||||
public @Nullable Element getSuperTypeElement() {
|
||||
return repository ? null : findMappedSuperElement( this, context );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -270,6 +266,14 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
return new ArrayList<>( members.values() );
|
||||
}
|
||||
|
||||
public void addInnerClass(AnnotationMetaEntity metaEntity) {
|
||||
putMember( "INNER_" + metaEntity.getQualifiedName(), new InnerClassMetaAttribute( metaEntity ) );
|
||||
}
|
||||
|
||||
public void setParentElement(TypeElement parentElement) {
|
||||
this.parentElement = parentElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMetaComplete() {
|
||||
return false;
|
||||
|
@ -363,7 +367,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
.toString();
|
||||
}
|
||||
|
||||
protected final void init() {
|
||||
protected void init() {
|
||||
getContext().logMessage( Diagnostic.Kind.OTHER, "Initializing type '" + getQualifiedName() + "'" );
|
||||
|
||||
setupSession();
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.processor.model.ImportContext;
|
|||
import org.hibernate.processor.model.MetaAttribute;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.tools.Diagnostic;
|
||||
import java.util.ArrayList;
|
||||
|
@ -69,7 +70,7 @@ public class AnnotationMetaPackage extends AnnotationMeta {
|
|||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getSupertypeName() {
|
||||
public @Nullable Element getSuperTypeElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public class DefaultConstructor implements MetaAttribute {
|
|||
final StringBuilder declaration = new StringBuilder();
|
||||
declaration
|
||||
.append('\n');
|
||||
if ( annotationMetaEntity.getSupertypeName() == null ) {
|
||||
if ( annotationMetaEntity.getSuperTypeElement() == null ) {
|
||||
declaration
|
||||
.append("@")
|
||||
.append(annotationMetaEntity.importType("jakarta.persistence.PersistenceUnit"));
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.processor.annotation;
|
||||
|
||||
import org.hibernate.processor.model.MetaAttribute;
|
||||
import org.hibernate.processor.model.Metamodel;
|
||||
|
||||
public class InnerClassMetaAttribute implements MetaAttribute {
|
||||
|
||||
private final AnnotationMeta metaEntity;
|
||||
|
||||
public InnerClassMetaAttribute(AnnotationMeta parent) {
|
||||
this.metaEntity = parent;
|
||||
}
|
||||
|
||||
public AnnotationMeta getMetaEntity() {
|
||||
return metaEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTypedAttribute() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStringAttribute() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttributeDeclarationString() {
|
||||
// final StringBuilder decl = new StringBuilder()
|
||||
// .append("\n/**\n * Static ID class for {@link ")
|
||||
// .append( parent.getQualifiedName() )
|
||||
// .append( "}\n **/\n" )
|
||||
// .append( "public record Id" );
|
||||
// String delimiter = "(";
|
||||
// for ( MetaAttribute component : components ) {
|
||||
// decl.append( delimiter ).append( parent.importType( component.getTypeDeclaration() ) )
|
||||
// .append( ' ' ).append( component.getPropertyName() );
|
||||
// delimiter = ", ";
|
||||
// }
|
||||
// return decl.append( ") {}" ).toString();
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttributeNameDeclarationString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMetaType() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPropertyName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metamodel getHostingEntity() {
|
||||
return metaEntity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* Copyright Red Hat Inc. and Hibernate Authors
|
||||
*/
|
||||
package org.hibernate.processor.annotation;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.processor.Context;
|
||||
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
public class NonManagedMetamodel extends AnnotationMetaEntity {
|
||||
|
||||
public NonManagedMetamodel(TypeElement element, Context context, boolean jakartaDataStaticMetamodel, @Nullable AnnotationMeta parent) {
|
||||
super( element, context, false, jakartaDataStaticMetamodel, parent );
|
||||
}
|
||||
|
||||
public static NonManagedMetamodel create(
|
||||
TypeElement element, Context context,
|
||||
boolean jakartaDataStaticMetamodel,
|
||||
@Nullable AnnotationMetaEntity parent) {
|
||||
final NonManagedMetamodel metamodel =
|
||||
new NonManagedMetamodel( element, context, jakartaDataStaticMetamodel, parent );
|
||||
if ( parent != null ) {
|
||||
metamodel.setParentElement( parent.getElement() );
|
||||
parent.addInnerClass( metamodel );
|
||||
}
|
||||
return metamodel;
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
// Initialization is not needed when non-managed class
|
||||
}
|
||||
|
||||
@Override
|
||||
public String javadoc() {
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -67,7 +67,7 @@ public class RepositoryConstructor implements MetaAttribute {
|
|||
final StringBuilder declaration = new StringBuilder();
|
||||
declaration
|
||||
.append('\n');
|
||||
if ( annotationMetaEntity.getSupertypeName() == null ) {
|
||||
if ( annotationMetaEntity.getSuperTypeElement() == null ) {
|
||||
declaration
|
||||
.append("protected ");
|
||||
if ( !dataRepository ) {
|
||||
|
@ -96,7 +96,7 @@ public class RepositoryConstructor implements MetaAttribute {
|
|||
.append(" ")
|
||||
.append(sessionVariableName)
|
||||
.append(") {\n");
|
||||
if ( annotationMetaEntity.getSupertypeName() != null ) {
|
||||
if ( annotationMetaEntity.getSuperTypeElement() != null ) {
|
||||
declaration
|
||||
.append("\tsuper(")
|
||||
.append(sessionVariableName)
|
||||
|
@ -112,7 +112,7 @@ public class RepositoryConstructor implements MetaAttribute {
|
|||
}
|
||||
declaration
|
||||
.append("}");
|
||||
if ( annotationMetaEntity.getSupertypeName() == null ) {
|
||||
if ( annotationMetaEntity.getSuperTypeElement() == null ) {
|
||||
declaration
|
||||
.append("\n\n");
|
||||
if (addOverrideAnnotation) {
|
||||
|
|
|
@ -19,7 +19,7 @@ public interface Metamodel extends ImportContext {
|
|||
|
||||
String getQualifiedName();
|
||||
|
||||
@Nullable String getSupertypeName();
|
||||
@Nullable Element getSuperTypeElement();
|
||||
|
||||
String getPackageName();
|
||||
|
||||
|
|
|
@ -98,6 +98,9 @@ public final class StringUtil {
|
|||
}
|
||||
|
||||
public static String getUpperUnderscoreCaseFromLowerCamelCase(String lowerCamelCaseString) {
|
||||
if ( lowerCamelCaseString.length() == 1 && isUpperCase( lowerCamelCaseString.charAt( 0 ) ) ) {
|
||||
return "_" + lowerCamelCaseString;
|
||||
}
|
||||
final StringBuilder result = new StringBuilder();
|
||||
int position = 0;
|
||||
while ( position < lowerCamelCaseString.length() ) {
|
||||
|
@ -116,4 +119,16 @@ public final class StringUtil {
|
|||
&& isUpperCase( string.charAt( 0 ) )
|
||||
&& isUpperCase( string.charAt( 1 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is an "intermediate" class providing {@code @Query}
|
||||
* annotations for the query by magical method name crap, then
|
||||
* by convention it will be named with a trailing $ sign. Strip
|
||||
* that off, so we get the standard constructor.
|
||||
*/
|
||||
public static String removeDollar(String simpleName) {
|
||||
return simpleName.endsWith("$")
|
||||
? simpleName.substring(0, simpleName.length()-1)
|
||||
: simpleName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -598,7 +598,7 @@ public final class TypeUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static @Nullable String findMappedSuperClass(Metamodel entity, Context context) {
|
||||
public static @Nullable Element findMappedSuperElement(Metamodel entity, Context context) {
|
||||
final Element element = entity.getElement();
|
||||
if ( element instanceof TypeElement typeElement ) {
|
||||
TypeMirror superClass = typeElement.getSuperclass();
|
||||
|
@ -607,7 +607,7 @@ public final class TypeUtils {
|
|||
final DeclaredType declaredType = (DeclaredType) superClass;
|
||||
final TypeElement superClassElement = (TypeElement) declaredType.asElement();
|
||||
if ( extendsSuperMetaModel( superClassElement, entity.isMetaComplete(), context ) ) {
|
||||
return superClassElement.getQualifiedName().toString();
|
||||
return superClassElement;
|
||||
}
|
||||
superClass = superClassElement.getSuperclass();
|
||||
}
|
||||
|
@ -667,6 +667,10 @@ public final class TypeUtils {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean isMemberType(Element element) {
|
||||
return element.getEnclosingElement() instanceof TypeElement;
|
||||
}
|
||||
|
||||
static class EmbeddedAttributeVisitor extends SimpleTypeVisitor8<@Nullable TypeElement, Element> {
|
||||
private final Context context;
|
||||
|
||||
|
|
|
@ -113,6 +113,8 @@ import org.hibernate.type.MapType;
|
|||
import org.hibernate.type.SetType;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
|
||||
|
@ -120,6 +122,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
|||
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -280,7 +283,7 @@ public abstract class MockSessionFactory
|
|||
|
||||
abstract boolean isEntityDefined(String entityName);
|
||||
|
||||
abstract String findEntityName(String typeName);
|
||||
abstract TypeElement findEntityClass(String entityName);
|
||||
|
||||
abstract String qualifyName(String entityName);
|
||||
|
||||
|
@ -681,6 +684,39 @@ public abstract class MockSessionFactory
|
|||
return SqlTypes.ARRAY;
|
||||
}
|
||||
|
||||
private static class MockJavaType<X> implements BasicJavaType<X> {
|
||||
private final String typeName;
|
||||
|
||||
public MockJavaType(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X1> X1 unwrap(X value, Class<X1> type, WrapperOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X1> X wrap(X1 value, WrapperOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<X> getJavaTypeClass() {
|
||||
try {
|
||||
return (Class<X>) Class.forName( typeName );
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MockMappingMetamodelImpl extends MappingMetamodelImpl {
|
||||
public MockMappingMetamodelImpl() {
|
||||
super(typeConfiguration, serviceRegistry);
|
||||
|
@ -774,21 +810,21 @@ public abstract class MockSessionFactory
|
|||
|
||||
@Override
|
||||
public EntityDomainType<?> entity(String entityName) {
|
||||
return isEntityDefined( entityName )
|
||||
? new MockEntityDomainType<>( entityName )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable EntityDomainType<?> findEntityType(@Nullable String entityName) {
|
||||
if ( isEntityDefined(entityName) ) {
|
||||
return new MockEntityDomainType<>(entityName);
|
||||
final TypeElement entityClass = findEntityClass( entityName );
|
||||
final String entityTypeName = entityClass == null ? entityName : entityClass.getQualifiedName().toString();
|
||||
return new MockEntityDomainType<>(entityName, new MockJavaType<>( entityTypeName ));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable EntityDomainType<?> findEntityType(@Nullable String entityName) {
|
||||
return entity( entityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String qualifyImportableName(String queryName) {
|
||||
if (isClassDefined(queryName)) {
|
||||
|
@ -825,9 +861,12 @@ public abstract class MockSessionFactory
|
|||
|
||||
@Override
|
||||
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
|
||||
return isEntityDefined( cls.getName() )
|
||||
? new MockEntityDomainType<X>( cls.getName() )
|
||||
: null;
|
||||
if ( isEntityDefined( cls.getName() ) ) {
|
||||
return new MockEntityDomainType<>( cls.getName(), new MockJavaType<X>( cls.getName() ));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -906,8 +945,8 @@ public abstract class MockSessionFactory
|
|||
|
||||
class MockEntityDomainType<X> extends EntityTypeImpl<X> {
|
||||
|
||||
public MockEntityDomainType(String entityName) {
|
||||
super(entityName, entityName, false, true, false, null, null,
|
||||
public MockEntityDomainType(String entityName, JavaType<X> javaType) {
|
||||
super(entityName, entityName, false, true, false, javaType, null,
|
||||
metamodel.getJpaMetamodel());
|
||||
}
|
||||
|
||||
|
@ -991,7 +1030,7 @@ public abstract class MockSessionFactory
|
|||
if (!entry.getValue().getEntityName().equals(getHibernateEntityName())
|
||||
&& isSubtype(entry.getValue().getEntityName(), getHibernateEntityName())) {
|
||||
final PersistentAttribute<? super Object, ?> subattribute
|
||||
= new MockEntityDomainType<>(entry.getValue().getEntityName()).findAttribute(name);
|
||||
= new MockEntityDomainType<>(entry.getValue().getEntityName(), new MockJavaType<>(entry.getValue().getEntityName()) ).findAttribute(name);
|
||||
if (subattribute != null) {
|
||||
return (SqmPathSource<?>) subattribute;
|
||||
}
|
||||
|
@ -1037,7 +1076,7 @@ public abstract class MockSessionFactory
|
|||
owner,
|
||||
name,
|
||||
AttributeClassification.MANY_TO_ONE,
|
||||
new MockEntityDomainType<>(type.getName()),
|
||||
new MockEntityDomainType<>(type.getName(), new MockJavaType<>(type.getName())),
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
|
@ -1095,7 +1134,9 @@ public abstract class MockSessionFactory
|
|||
private DomainType<?> getDomainType(String entityName, CollectionType collectionType, ManagedDomainType<?> owner, Type elementType) {
|
||||
if ( elementType.isEntityType() ) {
|
||||
final String associatedEntityName = collectionType.getAssociatedEntityName(MockSessionFactory.this);
|
||||
return new MockEntityDomainType<>(associatedEntityName);
|
||||
final TypeElement associatedEntityEntityClass = findEntityClass( associatedEntityName );
|
||||
final String associatedEntityTypeName = associatedEntityEntityClass == null ? associatedEntityName : associatedEntityEntityClass.getQualifiedName().toString();
|
||||
return new MockEntityDomainType<>(associatedEntityName, new MockJavaType<>(associatedEntityTypeName));
|
||||
}
|
||||
else if ( elementType.isComponentType() ) {
|
||||
final CompositeType compositeType = (CompositeType) elementType;
|
||||
|
|
|
@ -477,7 +477,8 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
|||
&& findPropertyByPath(entityClass, fieldName, getDefaultAccessType(entityClass)) != null;
|
||||
}
|
||||
|
||||
private TypeElement findEntityClass(String entityName) {
|
||||
@Override
|
||||
public TypeElement findEntityClass(String entityName) {
|
||||
if (entityName == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ import static org.hibernate.processor.util.StringUtil.determineFullyQualifiedCla
|
|||
import static org.hibernate.processor.util.StringUtil.isFullyQualified;
|
||||
import static org.hibernate.processor.util.StringUtil.packageNameFromFullyQualifiedName;
|
||||
import static org.hibernate.processor.util.TypeUtils.extractClosestRealTypeAsString;
|
||||
import static org.hibernate.processor.util.TypeUtils.findMappedSuperClass;
|
||||
import static org.hibernate.processor.util.TypeUtils.findMappedSuperElement;
|
||||
import static org.hibernate.processor.util.TypeUtils.getElementKindForAccessType;
|
||||
|
||||
/**
|
||||
|
@ -165,8 +165,8 @@ public class XmlMetaEntity implements Metamodel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getSupertypeName() {
|
||||
return findMappedSuperClass( this, context );
|
||||
public @Nullable Element getSuperTypeElement() {
|
||||
return findMappedSuperElement( this, context );
|
||||
}
|
||||
|
||||
public List<MetaAttribute> getMembers() {
|
||||
|
|
Loading…
Reference in New Issue