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;
|
package org.hibernate.processor;
|
||||||
|
|
||||||
|
import org.hibernate.processor.annotation.InnerClassMetaAttribute;
|
||||||
import org.hibernate.processor.model.MetaAttribute;
|
import org.hibernate.processor.model.MetaAttribute;
|
||||||
import org.hibernate.processor.model.Metamodel;
|
import org.hibernate.processor.model.Metamodel;
|
||||||
|
import org.hibernate.processor.util.StringUtil;
|
||||||
|
|
||||||
import javax.annotation.processing.FilerException;
|
import javax.annotation.processing.FilerException;
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
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.lang.model.element.TypeElement;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
import javax.tools.FileObject;
|
import javax.tools.FileObject;
|
||||||
|
@ -18,7 +23,12 @@ import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
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.
|
* 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();
|
String body = generateBody( entity, context ).toString();
|
||||||
|
|
||||||
FileObject fo = context.getProcessingEnvironment().getFiler().createSourceFile(
|
FileObject fo = context.getProcessingEnvironment().getFiler().createSourceFile(
|
||||||
getFullyQualifiedClassName( entity, metaModelPackage ),
|
getFullyQualifiedClassName( entity ),
|
||||||
entity.getElement()
|
entity.getElement()
|
||||||
);
|
);
|
||||||
OutputStream os = fo.openOutputStream();
|
OutputStream os = fo.openOutputStream();
|
||||||
|
@ -101,6 +111,15 @@ public final class ClassWriter {
|
||||||
pw.println();
|
pw.println();
|
||||||
|
|
||||||
final List<MetaAttribute> members = entity.getMembers();
|
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 ) {
|
for ( MetaAttribute metaMember : members ) {
|
||||||
if ( metaMember.hasStringAttribute() ) {
|
if ( metaMember.hasStringAttribute() ) {
|
||||||
metaMember.getAttributeNameDeclarationString().lines()
|
metaMember.getAttributeNameDeclarationString().lines()
|
||||||
|
@ -133,16 +152,29 @@ public final class ClassWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printClassDeclaration(Metamodel entity, PrintWriter pw) {
|
private static void printClassDeclaration(Metamodel entity, PrintWriter pw) {
|
||||||
pw.print( "public " );
|
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() ) {
|
if ( !entity.isImplementation() && !entity.isJakartaDataStyle() ) {
|
||||||
pw.print( "abstract " );
|
pw.print( "abstract " );
|
||||||
}
|
}
|
||||||
pw.print( entity.isJakartaDataStyle() ? "interface " : "class " );
|
pw.print( entity.isJakartaDataStyle() ? "interface " : "class " );
|
||||||
pw.print( getGeneratedClassName(entity) );
|
pw.print( getGeneratedClassName(entity) );
|
||||||
|
|
||||||
String superClassName = entity.getSupertypeName();
|
final Element superTypeElement = entity.getSuperTypeElement();
|
||||||
if ( superClassName != null ) {
|
if ( superTypeElement != null ) {
|
||||||
pw.print( " extends " + getGeneratedSuperclassName(entity, superClassName) );
|
pw.print( " extends " +
|
||||||
|
entity.importType(getGeneratedSuperclassName( superTypeElement, entity.isJakartaDataStyle() )) );
|
||||||
}
|
}
|
||||||
if ( entity.isImplementation() ) {
|
if ( entity.isImplementation() ) {
|
||||||
pw.print( entity.getElement().getKind() == ElementKind.CLASS ? " extends " : " implements " );
|
pw.print( entity.getElement().getKind() == ElementKind.CLASS ? " extends " : " implements " );
|
||||||
|
@ -152,13 +184,21 @@ public final class ClassWriter {
|
||||||
pw.println( " {" );
|
pw.println( " {" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getFullyQualifiedClassName(Metamodel entity, String metaModelPackage) {
|
private static String getFullyQualifiedClassName(Metamodel entity) {
|
||||||
String fullyQualifiedClassName = "";
|
final String metaModelPackage = entity.getPackageName();
|
||||||
if ( !metaModelPackage.isEmpty() ) {
|
final String packageNamePrefix = !metaModelPackage.isEmpty() ? metaModelPackage + "." : "";
|
||||||
fullyQualifiedClassName = fullyQualifiedClassName + metaModelPackage + ".";
|
final String className;
|
||||||
|
if ( entity.getElement().getKind() == ElementKind.PACKAGE ) {
|
||||||
|
className = getGeneratedClassName( entity );
|
||||||
}
|
}
|
||||||
fullyQualifiedClassName = fullyQualifiedClassName + getGeneratedClassName( entity );
|
else {
|
||||||
return fullyQualifiedClassName;
|
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) {
|
private static String getGeneratedClassName(Metamodel entity) {
|
||||||
|
@ -166,20 +206,14 @@ public final class ClassWriter {
|
||||||
return entity.isJakartaDataStyle() ? '_' + className : className + '_';
|
return entity.isJakartaDataStyle() ? '_' + className : className + '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getGeneratedSuperclassName(Metamodel entity, String superClassName) {
|
private static String getGeneratedSuperclassName(Element superClassElement, boolean jakartaDataStyle) {
|
||||||
if ( entity.isJakartaDataStyle() ) {
|
final TypeElement typeElement = (TypeElement) superClassElement;
|
||||||
int lastDot = superClassName.lastIndexOf('.');
|
final String simpleName = typeElement.getSimpleName().toString();
|
||||||
if ( lastDot<0 ) {
|
final Element enclosingElement = typeElement.getEnclosingElement();
|
||||||
return '_' + superClassName;
|
return (enclosingElement instanceof TypeElement
|
||||||
}
|
? getGeneratedSuperclassName( enclosingElement, jakartaDataStyle )
|
||||||
else {
|
: ((PackageElement) enclosingElement).getQualifiedName().toString())
|
||||||
return superClassName.substring(0,lastDot+1)
|
+ "." + (jakartaDataStyle ? '_' + simpleName : simpleName + '_');
|
||||||
+ '_' + superClassName.substring(lastDot+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return superClassName + '_';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String writeGeneratedAnnotation(Metamodel entity, Context context) {
|
private static String writeGeneratedAnnotation(Metamodel entity, Context context) {
|
||||||
|
@ -227,6 +261,7 @@ public final class ClassWriter {
|
||||||
final String annotation = entity.isJakartaDataStyle()
|
final String annotation = entity.isJakartaDataStyle()
|
||||||
? "jakarta.data.metamodel.StaticMetamodel"
|
? "jakarta.data.metamodel.StaticMetamodel"
|
||||||
: "jakarta.persistence.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();
|
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) {
|
public @Nullable Metamodel getMetaAuxiliary(String qualifiedName) {
|
||||||
return metaAuxiliaries.get( qualifiedName );
|
return metaAuxiliaries.get( qualifiedName );
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.hibernate.processor;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.processor.annotation.AnnotationMetaEntity;
|
import org.hibernate.processor.annotation.AnnotationMetaEntity;
|
||||||
import org.hibernate.processor.annotation.AnnotationMetaPackage;
|
import org.hibernate.processor.annotation.AnnotationMetaPackage;
|
||||||
|
import org.hibernate.processor.annotation.NonManagedMetamodel;
|
||||||
import org.hibernate.processor.model.Metamodel;
|
import org.hibernate.processor.model.Metamodel;
|
||||||
import org.hibernate.processor.util.Constants;
|
import org.hibernate.processor.util.Constants;
|
||||||
import org.hibernate.processor.xml.JpaDescriptorParser;
|
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.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.PackageElement;
|
import javax.lang.model.element.PackageElement;
|
||||||
import javax.lang.model.element.QualifiedNameable;
|
import javax.lang.model.element.QualifiedNameable;
|
||||||
import javax.lang.model.element.TypeElement;
|
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.getAnnotationValue;
|
||||||
import static org.hibernate.processor.util.TypeUtils.hasAnnotation;
|
import static org.hibernate.processor.util.TypeUtils.hasAnnotation;
|
||||||
import static org.hibernate.processor.util.TypeUtils.isClassOrRecordType;
|
import static org.hibernate.processor.util.TypeUtils.isClassOrRecordType;
|
||||||
|
import static org.hibernate.processor.util.TypeUtils.isMemberType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main annotation processor.
|
* Main annotation processor.
|
||||||
|
@ -358,59 +361,101 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( Element element : roundEnvironment.getRootElements() ) {
|
for ( Element element : roundEnvironment.getRootElements() ) {
|
||||||
try {
|
processElement( element, null );
|
||||||
if ( !included( element )
|
}
|
||||||
|| hasAnnotation( element, Constants.EXCLUDE )
|
}
|
||||||
|| hasPackageAnnotation( element, Constants.EXCLUDE ) ) {
|
|
||||||
// skip it completely
|
private void processElement(Element element, @Nullable Element parent) {
|
||||||
|
try {
|
||||||
|
if ( !included( element )
|
||||||
|
|| hasAnnotation( element, Constants.EXCLUDE )
|
||||||
|
|| hasPackageAnnotation( element, Constants.EXCLUDE )
|
||||||
|
|| element.getModifiers().contains( Modifier.PRIVATE ) ) {
|
||||||
|
// skip it completely
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ( isEntityOrEmbeddable( element ) && !element.getModifiers().contains( Modifier.PRIVATE )) {
|
||||||
|
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated entity class '" + element + "'" );
|
||||||
|
handleRootElementAnnotationMirrors( element, parent );
|
||||||
|
}
|
||||||
|
else if ( hasAuxiliaryAnnotations( element ) ) {
|
||||||
|
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
|
||||||
|
handleRootElementAuxiliaryAnnotationMirrors( element );
|
||||||
|
}
|
||||||
|
else if ( element instanceof TypeElement typeElement ) {
|
||||||
|
final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY );
|
||||||
|
if ( repository != null ) {
|
||||||
|
final AnnotationValue provider = getAnnotationValue( repository, "provider" );
|
||||||
|
if ( provider == null
|
||||||
|
|| provider.getValue().toString().isEmpty()
|
||||||
|
|| provider.getValue().toString().equalsIgnoreCase("hibernate") ) {
|
||||||
|
context.logMessage( Diagnostic.Kind.OTHER, "Processing repository class '" + element + "'" );
|
||||||
|
final AnnotationMetaEntity metaEntity =
|
||||||
|
AnnotationMetaEntity.create( typeElement, context );
|
||||||
|
if ( metaEntity.isInitialized() ) {
|
||||||
|
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
|
||||||
|
}
|
||||||
|
// otherwise discard it (assume it has query by magical method name stuff)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( isEntityOrEmbeddable( element ) ) {
|
else {
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated entity class '" + element + "'" );
|
for ( Element member : typeElement.getEnclosedElements() ) {
|
||||||
handleRootElementAnnotationMirrors( element );
|
if ( hasAnnotation( member, HQL, SQL, FIND ) ) {
|
||||||
}
|
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
|
||||||
else if ( hasAuxiliaryAnnotations( element ) ) {
|
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
|
|
||||||
handleRootElementAuxiliaryAnnotationMirrors( element );
|
|
||||||
}
|
|
||||||
else if ( element instanceof TypeElement typeElement ) {
|
|
||||||
final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY );
|
|
||||||
if ( repository != null ) {
|
|
||||||
final AnnotationValue provider = getAnnotationValue( repository, "provider" );
|
|
||||||
if ( provider == null
|
|
||||||
|| provider.getValue().toString().isEmpty()
|
|
||||||
|| provider.getValue().toString().equalsIgnoreCase("hibernate") ) {
|
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Processing repository class '" + element + "'" );
|
|
||||||
final AnnotationMetaEntity metaEntity =
|
final AnnotationMetaEntity metaEntity =
|
||||||
AnnotationMetaEntity.create( typeElement, context );
|
AnnotationMetaEntity.create( typeElement, context );
|
||||||
if ( metaEntity.isInitialized() ) {
|
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
|
||||||
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
|
break;
|
||||||
}
|
|
||||||
// otherwise discard it (assume it has query by magical method name stuff)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
if ( enclosesEntityOrEmbeddable( element ) ) {
|
||||||
for ( Element member : typeElement.getEnclosedElements() ) {
|
AnnotationMetaEntity parentMeta = null;
|
||||||
if ( hasAnnotation( member, HQL, SQL, FIND ) ) {
|
if ( parent instanceof TypeElement parentElement ) {
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
|
final String key = parentElement.getQualifiedName().toString();
|
||||||
final AnnotationMetaEntity metaEntity =
|
if ( context.getMetamodel( key ) instanceof AnnotationMetaEntity parentMetaEntity ) {
|
||||||
AnnotationMetaEntity.create( typeElement, context );
|
parentMeta = parentMetaEntity;
|
||||||
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( ProcessLaterException processLaterException ) {
|
if ( isClassOrRecordType( element ) ) {
|
||||||
if ( element instanceof TypeElement ) {
|
for ( final Element child : element.getEnclosedElements() ) {
|
||||||
context.logMessage(
|
if ( isClassOrRecordType( child ) ) {
|
||||||
Diagnostic.Kind.OTHER,
|
processElement( child, element );
|
||||||
"Could not process '" + element + "' (will redo in next round)"
|
}
|
||||||
);
|
|
||||||
context.addElementToRedo( ( (TypeElement) element).getQualifiedName() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch ( ProcessLaterException processLaterException ) {
|
||||||
|
if ( element instanceof TypeElement ) {
|
||||||
|
context.logMessage(
|
||||||
|
Diagnostic.Kind.OTHER,
|
||||||
|
"Could not process '" + element + "' (will redo in next round)"
|
||||||
|
);
|
||||||
|
context.addElementToRedo( ( (TypeElement) element ).getQualifiedName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasPackageAnnotation(Element element, String annotation) {
|
private boolean hasPackageAnnotation(Element element, String annotation) {
|
||||||
|
@ -430,7 +475,7 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( Metamodel entity : context.getMetaEntities() ) {
|
for ( Metamodel entity : context.getMetaEntities() ) {
|
||||||
if ( !context.isAlreadyGenerated(entity) ) {
|
if ( !context.isAlreadyGenerated( entity ) && !isMemberType( entity.getElement() ) ) {
|
||||||
context.logMessage( Diagnostic.Kind.OTHER,
|
context.logMessage( Diagnostic.Kind.OTHER,
|
||||||
"Writing Jakarta Persistence metamodel for entity '" + entity + "'" );
|
"Writing Jakarta Persistence metamodel for entity '" + entity + "'" );
|
||||||
ClassWriter.writeFile( entity, context );
|
ClassWriter.writeFile( entity, context );
|
||||||
|
@ -439,7 +484,7 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( Metamodel entity : context.getDataMetaEntities() ) {
|
for ( Metamodel entity : context.getDataMetaEntities() ) {
|
||||||
if ( !context.isAlreadyGenerated(entity) ) {
|
if ( !context.isAlreadyGenerated( entity ) && !isMemberType( entity.getElement() ) ) {
|
||||||
context.logMessage( Diagnostic.Kind.OTHER,
|
context.logMessage( Diagnostic.Kind.OTHER,
|
||||||
"Writing Jakarta Data metamodel for entity '" + entity + "'" );
|
"Writing Jakarta Data metamodel for entity '" + entity + "'" );
|
||||||
ClassWriter.writeFile( entity, context );
|
ClassWriter.writeFile( entity, context );
|
||||||
|
@ -516,6 +561,18 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
return false;
|
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) {
|
private static boolean isEntityOrEmbeddable(Element element) {
|
||||||
return hasAnnotation(
|
return hasAnnotation(
|
||||||
element,
|
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 ( isClassOrRecordType( element ) ) {
|
||||||
if ( isEntityOrEmbeddable( element ) ) {
|
if ( isEntityOrEmbeddable( element ) ) {
|
||||||
final TypeElement typeElement = (TypeElement) element;
|
final TypeElement typeElement = (TypeElement) element;
|
||||||
|
@ -564,12 +621,20 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
+ "' since XML configuration is metadata complete.");
|
+ "' since XML configuration is metadata complete.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
AnnotationMetaEntity parentMetaEntity = null;
|
||||||
|
if ( parent instanceof TypeElement parentTypeElement ) {
|
||||||
|
if ( context.getMetamodel(
|
||||||
|
parentTypeElement.getQualifiedName().toString() )
|
||||||
|
instanceof AnnotationMetaEntity pme ) {
|
||||||
|
parentMetaEntity = pme;
|
||||||
|
}
|
||||||
|
}
|
||||||
final boolean requiresLazyMemberInitialization
|
final boolean requiresLazyMemberInitialization
|
||||||
= hasAnnotation( element, EMBEDDABLE, MAPPED_SUPERCLASS );
|
= hasAnnotation( element, EMBEDDABLE, MAPPED_SUPERCLASS );
|
||||||
final AnnotationMetaEntity metaEntity =
|
final AnnotationMetaEntity metaEntity =
|
||||||
AnnotationMetaEntity.create( typeElement, context,
|
AnnotationMetaEntity.create( typeElement, context,
|
||||||
requiresLazyMemberInitialization,
|
requiresLazyMemberInitialization,
|
||||||
true, false );
|
true, false, parentMetaEntity );
|
||||||
if ( alreadyExistingMetaEntity != null ) {
|
if ( alreadyExistingMetaEntity != null ) {
|
||||||
metaEntity.mergeInMembers( alreadyExistingMetaEntity );
|
metaEntity.mergeInMembers( alreadyExistingMetaEntity );
|
||||||
}
|
}
|
||||||
|
@ -583,10 +648,17 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
// let a handwritten metamodel "override" the generated one
|
// let a handwritten metamodel "override" the generated one
|
||||||
// (this is used in the Jakarta Data TCK)
|
// (this is used in the Jakarta Data TCK)
|
||||||
&& !hasHandwrittenMetamodel(element) ) {
|
&& !hasHandwrittenMetamodel(element) ) {
|
||||||
|
AnnotationMetaEntity parentDataEntity = null;
|
||||||
|
if ( parent instanceof TypeElement parentTypeElement ) {
|
||||||
|
if ( context.getDataMetaEntity( parentTypeElement.getQualifiedName().toString() )
|
||||||
|
instanceof AnnotationMetaEntity pme ) {
|
||||||
|
parentDataEntity = pme;
|
||||||
|
}
|
||||||
|
}
|
||||||
final AnnotationMetaEntity dataMetaEntity =
|
final AnnotationMetaEntity dataMetaEntity =
|
||||||
AnnotationMetaEntity.create( typeElement, context,
|
AnnotationMetaEntity.create( typeElement, context,
|
||||||
requiresLazyMemberInitialization,
|
requiresLazyMemberInitialization,
|
||||||
true, true );
|
true, true, parentDataEntity );
|
||||||
// final Metamodel alreadyExistingDataMetaEntity =
|
// final Metamodel alreadyExistingDataMetaEntity =
|
||||||
// tryGettingExistingDataEntityFromContext( mirror, '_' + qualifiedName );
|
// tryGettingExistingDataEntityFromContext( mirror, '_' + qualifiedName );
|
||||||
// if ( alreadyExistingDataMetaEntity != null ) {
|
// 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.annotation.QueryMethod.isPageParam;
|
||||||
import static org.hibernate.processor.util.Constants.*;
|
import static org.hibernate.processor.util.Constants.*;
|
||||||
import static org.hibernate.processor.util.NullnessUtil.castNonNull;
|
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.containsAnnotation;
|
||||||
import static org.hibernate.processor.util.TypeUtils.determineAccessTypeForHierarchy;
|
import static org.hibernate.processor.util.TypeUtils.determineAccessTypeForHierarchy;
|
||||||
import static org.hibernate.processor.util.TypeUtils.determineAnnotationSpecifiedAccessType;
|
import static org.hibernate.processor.util.TypeUtils.determineAnnotationSpecifiedAccessType;
|
||||||
import static org.hibernate.processor.util.TypeUtils.extendsClass;
|
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.getAnnotationMirror;
|
||||||
import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
|
import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
|
||||||
import static org.hibernate.processor.util.TypeUtils.hasAnnotation;
|
import static org.hibernate.processor.util.TypeUtils.hasAnnotation;
|
||||||
|
@ -110,6 +111,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
private final ImportContext importContext;
|
private final ImportContext importContext;
|
||||||
private final TypeElement element;
|
private final TypeElement element;
|
||||||
private final Map<String, MetaAttribute> members;
|
private final Map<String, MetaAttribute> members;
|
||||||
|
private TypeElement parentElement;
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final boolean managed;
|
private final boolean managed;
|
||||||
private boolean jakartaDataRepository;
|
private boolean jakartaDataRepository;
|
||||||
|
@ -163,26 +165,32 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
|
|
||||||
public AnnotationMetaEntity(
|
public AnnotationMetaEntity(
|
||||||
TypeElement element, Context context, boolean managed,
|
TypeElement element, Context context, boolean managed,
|
||||||
boolean jakartaDataStaticMetamodel) {
|
boolean jakartaDataStaticMetamodel,
|
||||||
|
@Nullable AnnotationMeta parent) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.managed = managed;
|
this.managed = managed;
|
||||||
this.members = new HashMap<>();
|
this.members = new HashMap<>();
|
||||||
this.quarkusInjection = context.isQuarkusInjection();
|
this.quarkusInjection = context.isQuarkusInjection();
|
||||||
this.importContext = new ImportContextImpl( getPackageName( context, element ) );
|
this.importContext = parent != null ? parent : new ImportContextImpl( getPackageName( context, element ) );
|
||||||
jakartaDataStaticModel = jakartaDataStaticMetamodel;
|
jakartaDataStaticModel = jakartaDataStaticMetamodel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnnotationMetaEntity create(TypeElement element, Context context) {
|
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(
|
public static AnnotationMetaEntity create(
|
||||||
TypeElement element, Context context,
|
TypeElement element, Context context,
|
||||||
boolean lazilyInitialised, boolean managed,
|
boolean lazilyInitialised, boolean managed,
|
||||||
boolean jakartaData) {
|
boolean jakartaData,
|
||||||
|
@Nullable AnnotationMetaEntity parent) {
|
||||||
final AnnotationMetaEntity annotationMetaEntity =
|
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 ) {
|
if ( !lazilyInitialised ) {
|
||||||
annotationMetaEntity.init();
|
annotationMetaEntity.init();
|
||||||
}
|
}
|
||||||
|
@ -225,18 +233,6 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
return getSimpleName() + '_';
|
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
|
@Override
|
||||||
public final String getQualifiedName() {
|
public final String getQualifiedName() {
|
||||||
if ( qualifiedName == null ) {
|
if ( qualifiedName == null ) {
|
||||||
|
@ -246,8 +242,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable String getSupertypeName() {
|
public @Nullable Element getSuperTypeElement() {
|
||||||
return repository ? null : findMappedSuperClass( this, context );
|
return repository ? null : findMappedSuperElement( this, context );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -270,6 +266,14 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
return new ArrayList<>( members.values() );
|
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
|
@Override
|
||||||
public boolean isMetaComplete() {
|
public boolean isMetaComplete() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -363,7 +367,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void init() {
|
protected void init() {
|
||||||
getContext().logMessage( Diagnostic.Kind.OTHER, "Initializing type '" + getQualifiedName() + "'" );
|
getContext().logMessage( Diagnostic.Kind.OTHER, "Initializing type '" + getQualifiedName() + "'" );
|
||||||
|
|
||||||
setupSession();
|
setupSession();
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.processor.model.ImportContext;
|
||||||
import org.hibernate.processor.model.MetaAttribute;
|
import org.hibernate.processor.model.MetaAttribute;
|
||||||
|
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.PackageElement;
|
import javax.lang.model.element.PackageElement;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -69,7 +70,7 @@ public class AnnotationMetaPackage extends AnnotationMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable String getSupertypeName() {
|
public @Nullable Element getSuperTypeElement() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class DefaultConstructor implements MetaAttribute {
|
||||||
final StringBuilder declaration = new StringBuilder();
|
final StringBuilder declaration = new StringBuilder();
|
||||||
declaration
|
declaration
|
||||||
.append('\n');
|
.append('\n');
|
||||||
if ( annotationMetaEntity.getSupertypeName() == null ) {
|
if ( annotationMetaEntity.getSuperTypeElement() == null ) {
|
||||||
declaration
|
declaration
|
||||||
.append("@")
|
.append("@")
|
||||||
.append(annotationMetaEntity.importType("jakarta.persistence.PersistenceUnit"));
|
.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();
|
final StringBuilder declaration = new StringBuilder();
|
||||||
declaration
|
declaration
|
||||||
.append('\n');
|
.append('\n');
|
||||||
if ( annotationMetaEntity.getSupertypeName() == null ) {
|
if ( annotationMetaEntity.getSuperTypeElement() == null ) {
|
||||||
declaration
|
declaration
|
||||||
.append("protected ");
|
.append("protected ");
|
||||||
if ( !dataRepository ) {
|
if ( !dataRepository ) {
|
||||||
|
@ -96,7 +96,7 @@ public class RepositoryConstructor implements MetaAttribute {
|
||||||
.append(" ")
|
.append(" ")
|
||||||
.append(sessionVariableName)
|
.append(sessionVariableName)
|
||||||
.append(") {\n");
|
.append(") {\n");
|
||||||
if ( annotationMetaEntity.getSupertypeName() != null ) {
|
if ( annotationMetaEntity.getSuperTypeElement() != null ) {
|
||||||
declaration
|
declaration
|
||||||
.append("\tsuper(")
|
.append("\tsuper(")
|
||||||
.append(sessionVariableName)
|
.append(sessionVariableName)
|
||||||
|
@ -112,7 +112,7 @@ public class RepositoryConstructor implements MetaAttribute {
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
.append("}");
|
.append("}");
|
||||||
if ( annotationMetaEntity.getSupertypeName() == null ) {
|
if ( annotationMetaEntity.getSuperTypeElement() == null ) {
|
||||||
declaration
|
declaration
|
||||||
.append("\n\n");
|
.append("\n\n");
|
||||||
if (addOverrideAnnotation) {
|
if (addOverrideAnnotation) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ public interface Metamodel extends ImportContext {
|
||||||
|
|
||||||
String getQualifiedName();
|
String getQualifiedName();
|
||||||
|
|
||||||
@Nullable String getSupertypeName();
|
@Nullable Element getSuperTypeElement();
|
||||||
|
|
||||||
String getPackageName();
|
String getPackageName();
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,9 @@ public final class StringUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUpperUnderscoreCaseFromLowerCamelCase(String lowerCamelCaseString) {
|
public static String getUpperUnderscoreCaseFromLowerCamelCase(String lowerCamelCaseString) {
|
||||||
|
if ( lowerCamelCaseString.length() == 1 && isUpperCase( lowerCamelCaseString.charAt( 0 ) ) ) {
|
||||||
|
return "_" + lowerCamelCaseString;
|
||||||
|
}
|
||||||
final StringBuilder result = new StringBuilder();
|
final StringBuilder result = new StringBuilder();
|
||||||
int position = 0;
|
int position = 0;
|
||||||
while ( position < lowerCamelCaseString.length() ) {
|
while ( position < lowerCamelCaseString.length() ) {
|
||||||
|
@ -116,4 +119,16 @@ public final class StringUtil {
|
||||||
&& isUpperCase( string.charAt( 0 ) )
|
&& isUpperCase( string.charAt( 0 ) )
|
||||||
&& isUpperCase( string.charAt( 1 ) );
|
&& 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();
|
final Element element = entity.getElement();
|
||||||
if ( element instanceof TypeElement typeElement ) {
|
if ( element instanceof TypeElement typeElement ) {
|
||||||
TypeMirror superClass = typeElement.getSuperclass();
|
TypeMirror superClass = typeElement.getSuperclass();
|
||||||
|
@ -607,7 +607,7 @@ public final class TypeUtils {
|
||||||
final DeclaredType declaredType = (DeclaredType) superClass;
|
final DeclaredType declaredType = (DeclaredType) superClass;
|
||||||
final TypeElement superClassElement = (TypeElement) declaredType.asElement();
|
final TypeElement superClassElement = (TypeElement) declaredType.asElement();
|
||||||
if ( extendsSuperMetaModel( superClassElement, entity.isMetaComplete(), context ) ) {
|
if ( extendsSuperMetaModel( superClassElement, entity.isMetaComplete(), context ) ) {
|
||||||
return superClassElement.getQualifiedName().toString();
|
return superClassElement;
|
||||||
}
|
}
|
||||||
superClass = superClassElement.getSuperclass();
|
superClass = superClassElement.getSuperclass();
|
||||||
}
|
}
|
||||||
|
@ -667,6 +667,10 @@ public final class TypeUtils {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isMemberType(Element element) {
|
||||||
|
return element.getEnclosingElement() instanceof TypeElement;
|
||||||
|
}
|
||||||
|
|
||||||
static class EmbeddedAttributeVisitor extends SimpleTypeVisitor8<@Nullable TypeElement, Element> {
|
static class EmbeddedAttributeVisitor extends SimpleTypeVisitor8<@Nullable TypeElement, Element> {
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,8 @@ import org.hibernate.type.MapType;
|
||||||
import org.hibernate.type.SetType;
|
import org.hibernate.type.SetType;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.Type;
|
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.EnumJavaType;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
|
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.descriptor.jdbc.ObjectJdbcType;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -280,7 +283,7 @@ public abstract class MockSessionFactory
|
||||||
|
|
||||||
abstract boolean isEntityDefined(String entityName);
|
abstract boolean isEntityDefined(String entityName);
|
||||||
|
|
||||||
abstract String findEntityName(String typeName);
|
abstract TypeElement findEntityClass(String entityName);
|
||||||
|
|
||||||
abstract String qualifyName(String entityName);
|
abstract String qualifyName(String entityName);
|
||||||
|
|
||||||
|
@ -681,6 +684,39 @@ public abstract class MockSessionFactory
|
||||||
return SqlTypes.ARRAY;
|
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 {
|
private class MockMappingMetamodelImpl extends MappingMetamodelImpl {
|
||||||
public MockMappingMetamodelImpl() {
|
public MockMappingMetamodelImpl() {
|
||||||
super(typeConfiguration, serviceRegistry);
|
super(typeConfiguration, serviceRegistry);
|
||||||
|
@ -774,21 +810,21 @@ public abstract class MockSessionFactory
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<?> entity(String entityName) {
|
public EntityDomainType<?> entity(String entityName) {
|
||||||
return isEntityDefined( entityName )
|
|
||||||
? new MockEntityDomainType<>( entityName )
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable EntityDomainType<?> findEntityType(@Nullable String entityName) {
|
|
||||||
if ( isEntityDefined(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 {
|
else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable EntityDomainType<?> findEntityType(@Nullable String entityName) {
|
||||||
|
return entity( entityName );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String qualifyImportableName(String queryName) {
|
public String qualifyImportableName(String queryName) {
|
||||||
if (isClassDefined(queryName)) {
|
if (isClassDefined(queryName)) {
|
||||||
|
@ -825,9 +861,12 @@ public abstract class MockSessionFactory
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
|
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
|
||||||
return isEntityDefined( cls.getName() )
|
if ( isEntityDefined( cls.getName() ) ) {
|
||||||
? new MockEntityDomainType<X>( cls.getName() )
|
return new MockEntityDomainType<>( cls.getName(), new MockJavaType<X>( cls.getName() ));
|
||||||
: null;
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -906,8 +945,8 @@ public abstract class MockSessionFactory
|
||||||
|
|
||||||
class MockEntityDomainType<X> extends EntityTypeImpl<X> {
|
class MockEntityDomainType<X> extends EntityTypeImpl<X> {
|
||||||
|
|
||||||
public MockEntityDomainType(String entityName) {
|
public MockEntityDomainType(String entityName, JavaType<X> javaType) {
|
||||||
super(entityName, entityName, false, true, false, null, null,
|
super(entityName, entityName, false, true, false, javaType, null,
|
||||||
metamodel.getJpaMetamodel());
|
metamodel.getJpaMetamodel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,7 +1030,7 @@ public abstract class MockSessionFactory
|
||||||
if (!entry.getValue().getEntityName().equals(getHibernateEntityName())
|
if (!entry.getValue().getEntityName().equals(getHibernateEntityName())
|
||||||
&& isSubtype(entry.getValue().getEntityName(), getHibernateEntityName())) {
|
&& isSubtype(entry.getValue().getEntityName(), getHibernateEntityName())) {
|
||||||
final PersistentAttribute<? super Object, ?> subattribute
|
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) {
|
if (subattribute != null) {
|
||||||
return (SqmPathSource<?>) subattribute;
|
return (SqmPathSource<?>) subattribute;
|
||||||
}
|
}
|
||||||
|
@ -1037,7 +1076,7 @@ public abstract class MockSessionFactory
|
||||||
owner,
|
owner,
|
||||||
name,
|
name,
|
||||||
AttributeClassification.MANY_TO_ONE,
|
AttributeClassification.MANY_TO_ONE,
|
||||||
new MockEntityDomainType<>(type.getName()),
|
new MockEntityDomainType<>(type.getName(), new MockJavaType<>(type.getName())),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
|
@ -1095,7 +1134,9 @@ public abstract class MockSessionFactory
|
||||||
private DomainType<?> getDomainType(String entityName, CollectionType collectionType, ManagedDomainType<?> owner, Type elementType) {
|
private DomainType<?> getDomainType(String entityName, CollectionType collectionType, ManagedDomainType<?> owner, Type elementType) {
|
||||||
if ( elementType.isEntityType() ) {
|
if ( elementType.isEntityType() ) {
|
||||||
final String associatedEntityName = collectionType.getAssociatedEntityName(MockSessionFactory.this);
|
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() ) {
|
else if ( elementType.isComponentType() ) {
|
||||||
final CompositeType compositeType = (CompositeType) elementType;
|
final CompositeType compositeType = (CompositeType) elementType;
|
||||||
|
|
|
@ -477,7 +477,8 @@ public abstract class ProcessorSessionFactory extends MockSessionFactory {
|
||||||
&& findPropertyByPath(entityClass, fieldName, getDefaultAccessType(entityClass)) != null;
|
&& findPropertyByPath(entityClass, fieldName, getDefaultAccessType(entityClass)) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeElement findEntityClass(String entityName) {
|
@Override
|
||||||
|
public TypeElement findEntityClass(String entityName) {
|
||||||
if (entityName == null) {
|
if (entityName == null) {
|
||||||
return 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.isFullyQualified;
|
||||||
import static org.hibernate.processor.util.StringUtil.packageNameFromFullyQualifiedName;
|
import static org.hibernate.processor.util.StringUtil.packageNameFromFullyQualifiedName;
|
||||||
import static org.hibernate.processor.util.TypeUtils.extractClosestRealTypeAsString;
|
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;
|
import static org.hibernate.processor.util.TypeUtils.getElementKindForAccessType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,8 +165,8 @@ public class XmlMetaEntity implements Metamodel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable String getSupertypeName() {
|
public @Nullable Element getSuperTypeElement() {
|
||||||
return findMappedSuperClass( this, context );
|
return findMappedSuperElement( this, context );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MetaAttribute> getMembers() {
|
public List<MetaAttribute> getMembers() {
|
||||||
|
|
Loading…
Reference in New Issue