Skip to content

Commit

Permalink
Support ORM/HR+Panache
Browse files Browse the repository at this point in the history
- Allow `@Find`/`@*QL` methods on `native` methods
- Look at session getters to find their session types, but never make
  DAOs for Panache entities or repositories (we want generated static methods)
  • Loading branch information
FroMage authored and gavinking committed Mar 1, 2024
1 parent 36c9ce9 commit 1f3aed0
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
Expand Down Expand Up @@ -342,16 +343,7 @@ else if ( containsAnnotation( method, JD_INSERT, JD_UPDATE, JD_DELETE, JD_SAVE )
}
}

jakartaDataRepository = hasAnnotation( element, JD_REPOSITORY );
findSessionGetter( element );
if ( !repository && jakartaDataRepository) {
repository = true;
sessionType = HIB_STATELESS_SESSION;
addDaoConstructor( null );
}
if ( jakartaDataRepository && !quarkusInjection ) {
addDefaultConstructor();
}
setupSession();

if ( managed && !jakartaDataStaticModel ) {
putMember( "class", new AnnotationMetaType(this) );
Expand Down Expand Up @@ -395,31 +387,91 @@ private void addDefaultConstructor() {
}
return null;
}

private void setupSession() {
jakartaDataRepository = hasAnnotation( element, JD_REPOSITORY );
ExecutableElement getter = findSessionGetter( element );
if ( getter != null ) {
// Never make a DAO for Panache subtypes
if ( !isPanacheType( element ) ) {
repository = true;
sessionType = addDaoConstructor( getter );
}
else {
// For Panache subtypes, we look at the session type, but no DAO, we want static methods
sessionType = getter.getReturnType().toString();
}
}
if ( !repository && jakartaDataRepository ) {
repository = true;
sessionType = HIB_STATELESS_SESSION;
addDaoConstructor( null );
}
if ( jakartaDataRepository && !quarkusInjection ) {
addDefaultConstructor();
}
}

private void findSessionGetter(TypeElement type) {
if ( !hasAnnotation( type, Constants.ENTITY )
private @Nullable ExecutableElement findSessionGetter(TypeElement type) {
if ( ( !hasAnnotation( type, Constants.ENTITY )
&& !hasAnnotation( type, Constants.MAPPED_SUPERCLASS )
&& !hasAnnotation( type, Constants.EMBEDDABLE ) ) {
&& !hasAnnotation( type, Constants.EMBEDDABLE ) )
|| isPanacheType( type ) ) {
for ( ExecutableElement method : methodsIn( type.getEnclosedElements() ) ) {
if ( isSessionGetter( method ) ) {
repository = true;
sessionType = addDaoConstructor( method );
return method;
}
}
if ( !repository) {
final TypeMirror superclass = type.getSuperclass();
if ( superclass.getKind() == TypeKind.DECLARED ) {
final DeclaredType declaredType = (DeclaredType) superclass;
findSessionGetter( (TypeElement) declaredType.asElement() );
final TypeMirror superclass = type.getSuperclass();
if ( superclass.getKind() == TypeKind.DECLARED ) {
final DeclaredType declaredType = (DeclaredType) superclass;
ExecutableElement ret = findSessionGetter( (TypeElement) declaredType.asElement() );
if ( ret != null ) {
return ret;
}
for ( TypeMirror superinterface : type.getInterfaces() ) {
if ( superinterface.getKind() == TypeKind.DECLARED ) {
final DeclaredType declaredType = (DeclaredType) superinterface;
findSessionGetter( (TypeElement) declaredType.asElement() );
}
for ( TypeMirror superinterface : type.getInterfaces() ) {
if ( superinterface.getKind() == TypeKind.DECLARED ) {
final DeclaredType declaredType = (DeclaredType) superinterface;
ExecutableElement ret = findSessionGetter( (TypeElement) declaredType.asElement() );
if ( ret != null ) {
return ret;
}
}
}
}
return null;
}

private boolean isPanacheType(TypeElement type) {
return isOrmPanacheType( type ) || isReactivePanacheType( type );
}

private boolean isOrmPanacheType(TypeElement type) {
ProcessingEnvironment processingEnvironment = this.context.getProcessingEnvironment();
TypeElement panacheRepositorySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_ORM_REPOSITORY_BASE );
TypeElement panacheEntitySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_ORM_ENTITY_BASE );
if ( panacheRepositorySuperType == null || panacheEntitySuperType == null ) {
return false;
}
Types types = processingEnvironment.getTypeUtils();
// check against a raw supertype of PanacheRepositoryBase, which .asType() is not
return processingEnvironment.getTypeUtils().isSubtype( type.asType(), types.getDeclaredType( panacheRepositorySuperType ) )
|| processingEnvironment.getTypeUtils().isSubtype( type.asType(), panacheEntitySuperType.asType() );
}

private boolean isReactivePanacheType(TypeElement type) {
ProcessingEnvironment processingEnvironment = this.context.getProcessingEnvironment();
TypeElement panacheRepositorySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_REACTIVE_REPOSITORY_BASE );
TypeElement panacheEntitySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_REACTIVE_ENTITY_BASE );

if ( panacheRepositorySuperType == null || panacheEntitySuperType == null ) {
return false;
}
Types types = processingEnvironment.getTypeUtils();
// check against a raw supertype of PanacheRepositoryBase, which .asType() is not
return types.isSubtype( type.asType(), types.getDeclaredType( panacheRepositorySuperType ) )
|| types.isSubtype( type.asType(), panacheEntitySuperType.asType());
}

/**
Expand Down Expand Up @@ -557,7 +609,7 @@ private void addLifecycleMethods(List<ExecutableElement> queryMethods) {

private void addQueryMethods(List<ExecutableElement> queryMethods) {
for ( ExecutableElement method : queryMethods) {
if ( method.getModifiers().contains(Modifier.ABSTRACT) ) {
if ( method.getModifiers().contains(Modifier.ABSTRACT) || method.getModifiers().contains(Modifier.NATIVE) ) {
addQueryMethod( method );
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ public final class Constants {
public static final String OPTIONAL = "java.util.Optional";
public static final String STREAM = "java.util.stream.Stream";

public static final String PANACHE_ORM_REPOSITORY_BASE = "io.quarkus.hibernate.orm.panache.PanacheRepositoryBase";
public static final String PANACHE_ORM_ENTITY_BASE = "io.quarkus.hibernate.orm.panache.PanacheEntityBase";
public static final String PANACHE_REACTIVE_REPOSITORY_BASE = "io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase";
public static final String PANACHE_REACTIVE_ENTITY_BASE = "io.quarkus.hibernate.reactive.panache.PanacheEntityBase";

public static final Map<String, String> COLLECTIONS = Map.of(
COLLECTION, Constants.COLLECTION_ATTRIBUTE,
SET, Constants.SET_ATTRIBUTE,
Expand Down

0 comments on commit 1f3aed0

Please sign in to comment.