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