@@ -468,6 +468,10 @@ && containsAnnotation( method, HQL, SQL, FIND ) ) {
468468 addPersistentMembers ( gettersAndSettersOfClass , AccessType .PROPERTY );
469469
470470 addIdClassIfNeeded ( fieldsOfClass , gettersAndSettersOfClass );
471+
472+ if ( hasAnnotation ( element , ENTITY ) && isPanache2Type (element ) && !jakartaDataStaticModel ) {
473+ addRepositoryMembers ( element );
474+ }
471475 }
472476
473477 addAuxiliaryMembers ();
@@ -521,6 +525,41 @@ private void addIdClassIfNeeded(List<VariableElement> fields, List<ExecutableEle
521525 }
522526 }
523527
528+ private void addRepositoryMembers (TypeElement element ) {
529+ Element managedBlockingRepository = null ;
530+ Element statelessBlockingRepository = null ;
531+ Element managedReactiveRepository = null ;
532+ Element statelessReactiveRepository = null ;
533+ for ( Element enclosedElement : element .getEnclosedElements () ) {
534+ if ( enclosedElement .getKind () == ElementKind .INTERFACE ) {
535+ members .put ( enclosedElement .getSimpleName ().toString (), new CDIAccessorMetaAttribute ( this , enclosedElement ) );
536+ if ( implementsInterface ( (TypeElement ) enclosedElement , Constants .PANACHE2_MANAGED_BLOCKING_REPOSITORY_BASE ) ) {
537+ managedBlockingRepository = enclosedElement ;
538+ }
539+ else if ( implementsInterface ( (TypeElement ) enclosedElement , Constants .PANACHE2_STATELESS_BLOCKING_REPOSITORY_BASE ) ) {
540+ statelessBlockingRepository = enclosedElement ;
541+ }
542+ else if ( implementsInterface ( (TypeElement ) enclosedElement , Constants .PANACHE2_MANAGED_REACTIVE_REPOSITORY_BASE ) ) {
543+ managedReactiveRepository = enclosedElement ;
544+ }
545+ else if ( implementsInterface ( (TypeElement ) enclosedElement , Constants .PANACHE2_STATELESS_REACTIVE_REPOSITORY_BASE ) ) {
546+ statelessReactiveRepository = enclosedElement ;
547+ }
548+ }
549+ }
550+ if ( quarkusInjection ) {
551+ // FIXME: perhaps import id type?
552+ TypeMirror idType = findIdType ();
553+ addAccessors (managedBlockingRepository , idType , "managedBlocking" , PANACHE2_MANAGED_BLOCKING_REPOSITORY_BASE );
554+ addAccessors (statelessBlockingRepository , idType , "statelessBlocking" , PANACHE2_STATELESS_BLOCKING_REPOSITORY_BASE );
555+ // Only add those if HR is in the classpath, otherwise it causes a compilation issue
556+ if ( context .usesQuarkusReactiveCommon () ) {
557+ addAccessors (managedReactiveRepository , idType , "managedReactive" , PANACHE2_MANAGED_REACTIVE_REPOSITORY_BASE );
558+ addAccessors (statelessReactiveRepository , idType , "statelessReactive" , PANACHE2_STATELESS_REACTIVE_REPOSITORY_BASE );
559+ }
560+ }
561+ }
562+
524563 private List <MetaAttribute > getIdMemberNames (List <VariableElement > fields , List <ExecutableElement > methods ) {
525564 final List <MetaAttribute > components = new ArrayList <>();
526565 for ( var field : fields ) {
@@ -648,6 +687,56 @@ private boolean isEquivalentPrimitiveType(TypeMirror type, TypeMirror match) {
648687 && isSameType ( context .getTypeUtils ().boxedClass ( ((PrimitiveType ) type ) ).asType (), match );
649688 }
650689
690+ private void addAccessors (@ Nullable Element repositoryType , @ Nullable TypeMirror idType ,
691+ String repositoryAccessor , String repositorySuperType ) {
692+ TypeElement finalPrimaryEntity = primaryEntity ;
693+ if ( repositoryType != null ) {
694+ members .put ( repositoryAccessor , new CDIAccessorMetaAttribute ( this , repositoryAccessor , repositoryType .getSimpleName ().toString () ) );
695+ }
696+ else if ( idType != null && finalPrimaryEntity != null ) {
697+ String repositoryTypeName = "Panache" +repositoryAccessor .substring (0 ,1 ).toUpperCase ()+repositoryAccessor .substring (1 )+"Repository" ;
698+ members .put ( repositoryAccessor , new CDIAccessorMetaAttribute ( this , repositoryAccessor , repositoryTypeName ) );
699+ members .put ( repositoryAccessor + "Repository" , new CDITypeMetaAttribute ( this , repositoryTypeName , repositorySuperType +"<" + finalPrimaryEntity .getSimpleName ()+", " + idType .toString ()+">" ) );
700+ }
701+ }
702+
703+ private @ Nullable TypeMirror findIdType () {
704+ Element idMember = findIdMember ();
705+ TypeElement primaryEntityForTest = primaryEntity ;
706+ if ( idMember != null && primaryEntityForTest != null ) {
707+ TypeMirror typedIdMember = this .context .getTypeUtils ().asMemberOf ((DeclaredType ) primaryEntityForTest .asType (), idMember );
708+ return switch (typedIdMember .getKind ()) {
709+ case ARRAY , DECLARED , BOOLEAN , BYTE , CHAR , SHORT , INT , LONG , FLOAT , DOUBLE -> typedIdMember ;
710+ case EXECUTABLE -> ((ExecutableType ) typedIdMember ).getReturnType ();
711+ default -> {
712+ message ( element ,
713+ "Unhandled id member kind: " +typedIdMember +" for id " +idMember ,
714+ Diagnostic .Kind .ERROR );
715+ yield null ;
716+ }
717+ };
718+ }
719+ return null ;
720+ }
721+
722+ private @ Nullable Element findIdMember () {
723+ if ( primaryEntity == null ) {
724+ message ( element ,
725+ "No primary entity defined to find id member" ,
726+ Diagnostic .Kind .ERROR );
727+ return null ;
728+ }
729+ for ( Element member : context .getAllMembers ( primaryEntity ) ) {
730+ if ( hasAnnotation ( member , ID , EMBEDDED_ID ) ) {
731+ return member ;
732+ }
733+ }
734+ message ( element ,
735+ "Could not find any member annotated with @Id or @EmbeddedId" ,
736+ Diagnostic .Kind .ERROR );
737+ return null ;
738+ }
739+
651740 private boolean checkEntities (List <ExecutableElement > lifecycleMethods , boolean hibernateRepo ) {
652741 boolean foundPersistenceEntity = false ;
653742 VariableElement nonPersistenceParameter = null ;
0 commit comments