This is an automated email from the ASF dual-hosted git repository.

dbalek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 44de9726dd Allow for creating Micronaut Controllers based on Data 
Repository interfaces.
     new f6083fc341 Merge pull request #6702 from 
dbalek/dbalek/micronaut-controllers-from-repositories
44de9726dd is described below

commit 44de9726ddae5112921821b046b003e285766bd8
Author: Dusan Balek <dusan.ba...@oracle.com>
AuthorDate: Wed Nov 15 14:25:30 2023 +0100

    Allow for creating Micronaut Controllers based on Data Repository 
interfaces.
---
 .../modules/micronaut/db/Bundle.properties         |  24 ++-
 ...ClassesPanel.form => ClassesSelectorPanel.form} |  63 +++---
 ...ClassesPanel.java => ClassesSelectorPanel.java} | 223 ++++++++++++---------
 .../modules/micronaut/db/MicronautController.java  | 196 +++++++++++++++---
 .../modules/micronaut/db/MicronautRepository.java  |  21 +-
 .../modules/micronaut/resources/Controller.html    |   4 +-
 6 files changed, 354 insertions(+), 177 deletions(-)

diff --git 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/Bundle.properties 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/Bundle.properties
index 9363d7ff68..3fe100ed34 100644
--- 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/Bundle.properties
+++ 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/Bundle.properties
@@ -16,7 +16,7 @@
 # under the License.
 
 Templates/Micronaut=Micronaut
-Templates/Micronaut/Controller=Micronaut Controller Class
+Templates/Micronaut/Controller=Micronaut Controller Classes (from Data 
Repositories)
 Templates/Micronaut/Entity=Micronaut Data Entity Classes from Database
 Templates/Micronaut/Repository=Micronaut Data Repository Interfaces from 
Entities
 
@@ -30,19 +30,33 @@ MSG_PK_Class=Primary Key class {0} for entity class {1}\n
 
 USG_PERSISTENCE_ENTITY_DB_CREATED={0} entity classes was generated from db
 
-LBL_EntityClasses=Entity Classes
+LBL_Entities=Entity Classes
 LBL_AvailableEntities=Available &Entity Classes:
 TXT_AvailableEntities=Available Entity Classes
 ACSN_AvailableEntities=Available entity classes
 ACSD_AvailableEntities=List of all available entity classes
 LBL_SelectedEntities=S&elected Entity Classes:
 TXT_SelectedEntities=Selected Entity Classes
+ACSN_SelectedEntities=Selected entity classes
+ACSD_SelectedEntities=List of selected entity classes
+
+LBL_Repositories=Repository Interfaces
+LBL_AvailableRepositories=Available Repository &Interfaces:
+TXT_AvailableRepositories=Available Repository Interfaces
+ACSN_AvailableRepositories=Available repository interfaces
+ACSD_AvailableRepositories=List of all available repository interfaces
+LBL_SelectedRepositories=S&elected Repository Interfaces:
+TXT_SelectedRepositories=Selected Repository Interfaces
+ACSN_SelectedRepositories=Selected repository interfaces
+ACSD_SelectedRepositories=List of selected repository interfaces
+
 LBL_AddAll=Add A&ll >>
 LBL_Add=&Add >
 LBL_Remove=< &Remove
 LBL_RemoveAll=<< Re&move All
-ACSN_SelectedEntities=Selected entity classes
-ACSD_SelectedEntities=List of selected entity classes
+
 ERR_SelectEntities=Select at least one entity class
 # {0} = project name
-ERR_NoEntities=No entity class found in {0}
\ No newline at end of file
+ERR_NoEntities=No entity class found in {0}
+# {0} = project name
+ERR_NoRepositories=No repository interface found in {0}
\ No newline at end of file
diff --git 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/EntityClassesPanel.form
 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/ClassesSelectorPanel.form
similarity index 80%
rename from 
enterprise/micronaut/src/org/netbeans/modules/micronaut/db/EntityClassesPanel.form
rename to 
enterprise/micronaut/src/org/netbeans/modules/micronaut/db/ClassesSelectorPanel.form
index 0a3bcbb9cf..7ce55b6e3c 100644
--- 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/EntityClassesPanel.form
+++ 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/ClassesSelectorPanel.form
@@ -26,8 +26,8 @@
     <Property name="minimumSize" type="java.awt.Dimension" 
editor="org.netbeans.beaninfo.editors.DimensionEditor">
       <Dimension value="[200, 300]"/>
     </Property>
-    <Property name="name" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-      <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="LBL_EntityClasses" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+    <Property name="name" type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+      <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;LBL_&quot; + bundleKey)" type="code"/>
     </Property>
     <Property name="preferredSize" type="java.awt.Dimension" 
editor="org.netbeans.beaninfo.editors.DimensionEditor">
       <Dimension value="[496, 350]"/>
@@ -48,33 +48,28 @@
 
   <Layout 
class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
   <SubComponents>
-    <Container class="javax.swing.JPanel" name="entitiesPanel">
-      <Properties>
-        <Property name="preferredSize" type="java.awt.Dimension" 
editor="org.netbeans.beaninfo.editors.DimensionEditor">
-          <Dimension value="[440, 174]"/>
-        </Property>
-      </Properties>
+    <Container class="javax.swing.JPanel" name="classesPanel">
       <AuxValues>
-        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" 
type="java.lang.String" value="new EntitiesPanel();"/>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" 
type="java.lang.String" value="new ClassesPanel();"/>
       </AuxValues>
       <Constraints>
         <Constraint 
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" 
value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
-          <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" 
fill="1" ipadX="0" ipadY="80" insetsTop="6" insetsLeft="0" insetsBottom="0" 
insetsRight="0" anchor="18" weightX="0.0" weightY="2.0"/>
+          <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" 
fill="1" ipadX="0" ipadY="80" insetsTop="6" insetsLeft="0" insetsBottom="0" 
insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
         </Constraint>
       </Constraints>
 
       <Layout 
class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
       <SubComponents>
-        <Component class="javax.swing.JLabel" name="availableEntitiesLabel">
+        <Component class="javax.swing.JLabel" name="availableLabel">
           <Properties>
             <Property name="labelFor" type="java.awt.Component" 
editor="org.netbeans.modules.form.ComponentChooserEditor">
-              <ComponentRef name="availableEntitiesList"/>
+              <ComponentRef name="availableList"/>
             </Property>
-            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="LBL_AvailableEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+              <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;LBL_Available&quot; + bundleKey)" type="code"/>
             </Property>
-            <Property name="toolTipText" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="TXT_AvailableEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            <Property name="toolTipText" type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+              <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;LBL_Available&quot; + bundleKey)" type="code"/>
             </Property>
           </Properties>
           <Constraints>
@@ -83,7 +78,7 @@
             </Constraint>
           </Constraints>
         </Component>
-        <Container class="javax.swing.JScrollPane" 
name="availableEntitiesScrollPane">
+        <Container class="javax.swing.JScrollPane" name="availableScrollPane">
           <Properties>
             <Property name="preferredSize" type="java.awt.Dimension" 
editor="org.netbeans.beaninfo.editors.DimensionEditor">
               <Dimension value="[160, 130]"/>
@@ -100,18 +95,18 @@
 
           <Layout 
class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
           <SubComponents>
-            <Component class="javax.swing.JList" name="availableEntitiesList">
+            <Component class="javax.swing.JList" name="availableList">
               <Properties>
                 <Property name="nextFocusableComponent" 
type="java.awt.Component" 
editor="org.netbeans.modules.form.ComponentChooserEditor">
                   <ComponentRef name="addButton"/>
                 </Property>
               </Properties>
               <AccessibilityProperties>
-                <Property name="AccessibleContext.accessibleName" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="ACSN_AvailableEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+                <Property name="AccessibleContext.accessibleName" 
type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+                  <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;ACSN_Available&quot; + bundleKey)" type="code"/>
                 </Property>
-                <Property name="AccessibleContext.accessibleDescription" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="ACSD_AvailableEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+                <Property name="AccessibleContext.accessibleDescription" 
type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+                  <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;ACSD_Available&quot; + bundleKey)" type="code"/>
                 </Property>
               </AccessibilityProperties>
               <AuxValues>
@@ -120,16 +115,16 @@
             </Component>
           </SubComponents>
         </Container>
-        <Component class="javax.swing.JLabel" name="selectedEntitiesLabel">
+        <Component class="javax.swing.JLabel" name="selectedLabel">
           <Properties>
             <Property name="labelFor" type="java.awt.Component" 
editor="org.netbeans.modules.form.ComponentChooserEditor">
-              <ComponentRef name="selectedEntitiesList"/>
+              <ComponentRef name="selectedList"/>
             </Property>
-            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="LBL_SelectedEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+              <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;LBL_Selected&quot; + bundleKey)" type="code"/>
             </Property>
-            <Property name="toolTipText" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="TXT_SelectedEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            <Property name="toolTipText" type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+              <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;LBL_Selected&quot; + bundleKey)" type="code"/>
             </Property>
           </Properties>
           <Constraints>
@@ -138,7 +133,7 @@
             </Constraint>
           </Constraints>
         </Component>
-        <Container class="javax.swing.JScrollPane" 
name="selectedEntitiesScrollPane">
+        <Container class="javax.swing.JScrollPane" name="selectedScrollPane">
           <Properties>
             <Property name="preferredSize" type="java.awt.Dimension" 
editor="org.netbeans.beaninfo.editors.DimensionEditor">
               <Dimension value="[160, 130]"/>
@@ -155,13 +150,13 @@
 
           <Layout 
class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
           <SubComponents>
-            <Component class="javax.swing.JList" name="selectedEntitiesList">
+            <Component class="javax.swing.JList" name="selectedList">
               <AccessibilityProperties>
-                <Property name="AccessibleContext.accessibleName" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="ACSN_SelectedEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+                <Property name="AccessibleContext.accessibleName" 
type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+                  <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;ACSN_Selected&quot; + bundleKey)" type="code"/>
                 </Property>
-                <Property name="AccessibleContext.accessibleDescription" 
type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString 
bundle="org/netbeans/modules/micronaut/db/Bundle.properties" 
key="ACSD_SelectedEntities" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+                <Property name="AccessibleContext.accessibleDescription" 
type="java.lang.String" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+                  <Connection 
code="org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
&quot;ACSD_Selected&quot; + bundleKey)" type="code"/>
                 </Property>
               </AccessibilityProperties>
               <AuxValues>
diff --git 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/EntityClassesPanel.java
 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/ClassesSelectorPanel.java
similarity index 58%
rename from 
enterprise/micronaut/src/org/netbeans/modules/micronaut/db/EntityClassesPanel.java
rename to 
enterprise/micronaut/src/org/netbeans/modules/micronaut/db/ClassesSelectorPanel.java
index ef4515ea98..215c76451a 100644
--- 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/EntityClassesPanel.java
+++ 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/ClassesSelectorPanel.java
@@ -22,9 +22,11 @@ package org.netbeans.modules.micronaut.db;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Rectangle;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import javax.swing.JPanel;
 import javax.swing.event.ChangeEvent;
@@ -42,13 +44,18 @@ import org.openide.util.NbBundle;
  *
  * @author Dusan Balek
  */
-public class EntityClassesPanel extends javax.swing.JPanel {
+public class ClassesSelectorPanel extends javax.swing.JPanel {
+
+    static final String PROP_CLASSES = "wizard-classes"; //NOI18N
+    static final String PROP_SELECTED_CLASSES = "wizard-selected-classes"; 
//NOI18N
 
     private final ChangeSupport changeSupport = new ChangeSupport(this);
-    private final Set<String> availableEntities = new HashSet<>();
-    private final Set<String> selectedEntities = new HashSet<>();
+    private final Set<String> available = new HashSet<>();
+    private final Set<String> selected = new HashSet<>();
+    private final String bundleKey;
 
-    public EntityClassesPanel() {
+    public ClassesSelectorPanel(String key) {
+        bundleKey = key;
         initComponents();
         ListSelectionListener selectionListener = new ListSelectionListener() {
             @Override
@@ -56,8 +63,8 @@ public class EntityClassesPanel extends javax.swing.JPanel {
                 updateButtons();
             }
         };
-        
availableEntitiesList.getSelectionModel().addListSelectionListener(selectionListener);
-        
selectedEntitiesList.getSelectionModel().addListSelectionListener(selectionListener);
+        
availableList.getSelectionModel().addListSelectionListener(selectionListener);
+        
selectedList.getSelectionModel().addListSelectionListener(selectionListener);
     }
 
     public void addChangeListener(ChangeListener listener) {
@@ -65,21 +72,29 @@ public class EntityClassesPanel extends javax.swing.JPanel {
     }
 
     public void initialize(Set<String> entities) {
-        availableEntities.addAll(entities);
-        availableEntitiesList.setListData(availableEntities.toArray(new 
String[availableEntities.size()]));
-        selectedEntitiesList.setListData(selectedEntities.toArray(new 
String[selectedEntities.size()]));
+        available.addAll(entities.stream().map(fqn -> {
+            int idx = fqn.lastIndexOf('.');
+            return idx < 0 ? fqn : fqn.substring(idx + 1) + " (" + 
fqn.substring(0, idx) + ')';
+        }).collect(Collectors.toSet()));
+        String[] availableArray = available.toArray(new String[0]);
+        Arrays.sort(availableArray);
+        availableList.setListData(availableArray);
+        selectedList.setListData(selected.toArray(new String[0]));
         updateButtons();
     }
 
-    public Set<String> getSelectedEntities() {
-        return selectedEntities;
+    public Set<String> getSelectedClasses() {
+        return selected.stream().map(item -> {
+            int idx = item.indexOf(" (");
+            return idx < 0 ? item : item.substring(idx + 2, item.length() - 1) 
+ '.' + item.substring(0, idx);
+        }).collect(Collectors.toSet());
     }
 
     private void updateButtons() {
-        addButton.setEnabled(availableEntitiesList.getSelectedIndices().length 
> 0);
-        addAllButton.setEnabled(!availableEntities.isEmpty());
-        
removeButton.setEnabled(selectedEntitiesList.getSelectedIndices().length > 0);
-        removeAllButton.setEnabled(!selectedEntities.isEmpty());
+        addButton.setEnabled(availableList.getSelectedIndices().length > 0);
+        addAllButton.setEnabled(!available.isEmpty());
+        removeButton.setEnabled(selectedList.getSelectedIndices().length > 0);
+        removeAllButton.setEnabled(!selected.isEmpty());
     }
 
     /** This method is called from within the constructor to
@@ -91,13 +106,13 @@ public class EntityClassesPanel extends javax.swing.JPanel 
{
     private void initComponents() {
         java.awt.GridBagConstraints gridBagConstraints;
 
-        entitiesPanel = new EntitiesPanel();
-        availableEntitiesLabel = new javax.swing.JLabel();
-        availableEntitiesScrollPane = new javax.swing.JScrollPane();
-        availableEntitiesList = new javax.swing.JList<>();
-        selectedEntitiesLabel = new javax.swing.JLabel();
-        selectedEntitiesScrollPane = new javax.swing.JScrollPane();
-        selectedEntitiesList = new javax.swing.JList<>();
+        classesPanel = new ClassesPanel();
+        availableLabel = new javax.swing.JLabel();
+        availableScrollPane = new javax.swing.JScrollPane();
+        availableList = new javax.swing.JList<>();
+        selectedLabel = new javax.swing.JLabel();
+        selectedScrollPane = new javax.swing.JScrollPane();
+        selectedList = new javax.swing.JList<>();
         buttonPanel = new javax.swing.JPanel();
         addButton = new javax.swing.JButton();
         removeButton = new javax.swing.JButton();
@@ -105,27 +120,26 @@ public class EntityClassesPanel extends 
javax.swing.JPanel {
         removeAllButton = new javax.swing.JButton();
 
         setMinimumSize(new java.awt.Dimension(200, 300));
-        setName(org.openide.util.NbBundle.getMessage(EntityClassesPanel.class, 
"LBL_EntityClasses")); // NOI18N
+        
setName(org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, "LBL_" 
+ bundleKey));
         setPreferredSize(new java.awt.Dimension(496, 350));
         setLayout(new java.awt.GridBagLayout());
 
-        entitiesPanel.setPreferredSize(new java.awt.Dimension(440, 174));
-        entitiesPanel.setLayout(new java.awt.GridBagLayout());
+        classesPanel.setLayout(new java.awt.GridBagLayout());
 
-        availableEntitiesLabel.setLabelFor(availableEntitiesList);
-        org.openide.awt.Mnemonics.setLocalizedText(availableEntitiesLabel, 
org.openide.util.NbBundle.getMessage(EntityClassesPanel.class, 
"LBL_AvailableEntities")); // NOI18N
-        
availableEntitiesLabel.setToolTipText(org.openide.util.NbBundle.getMessage(EntityClassesPanel.class,
 "TXT_AvailableEntities")); // NOI18N
+        availableLabel.setLabelFor(availableList);
+        org.openide.awt.Mnemonics.setLocalizedText(availableLabel, 
org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
"LBL_Available" + bundleKey));
+        
availableLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class,
 "LBL_Available" + bundleKey));
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
         gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
-        entitiesPanel.add(availableEntitiesLabel, gridBagConstraints);
+        classesPanel.add(availableLabel, gridBagConstraints);
 
-        availableEntitiesScrollPane.setPreferredSize(new 
java.awt.Dimension(160, 130));
+        availableScrollPane.setPreferredSize(new java.awt.Dimension(160, 130));
 
-        availableEntitiesList.setNextFocusableComponent(addButton);
-        availableEntitiesScrollPane.setViewportView(availableEntitiesList);
-        
availableEntitiesList.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(EntityClassesPanel.class,
 "ACSN_AvailableEntities")); // NOI18N
-        
availableEntitiesList.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(EntityClassesPanel.class,
 "ACSD_AvailableEntities")); // NOI18N
+        availableList.setNextFocusableComponent(addButton);
+        availableScrollPane.setViewportView(availableList);
+        
availableList.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class,
 "ACSN_Available" + bundleKey));
+        
availableList.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class,
 "ACSD_Available" + bundleKey));
 
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.gridx = 0;
@@ -134,22 +148,22 @@ public class EntityClassesPanel extends 
javax.swing.JPanel {
         gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
         gridBagConstraints.weightx = 1.0;
         gridBagConstraints.weighty = 1.0;
-        entitiesPanel.add(availableEntitiesScrollPane, gridBagConstraints);
+        classesPanel.add(availableScrollPane, gridBagConstraints);
 
-        selectedEntitiesLabel.setLabelFor(selectedEntitiesList);
-        org.openide.awt.Mnemonics.setLocalizedText(selectedEntitiesLabel, 
org.openide.util.NbBundle.getMessage(EntityClassesPanel.class, 
"LBL_SelectedEntities")); // NOI18N
-        
selectedEntitiesLabel.setToolTipText(org.openide.util.NbBundle.getMessage(EntityClassesPanel.class,
 "TXT_SelectedEntities")); // NOI18N
+        selectedLabel.setLabelFor(selectedList);
+        org.openide.awt.Mnemonics.setLocalizedText(selectedLabel, 
org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, "LBL_Selected" 
+ bundleKey));
+        
selectedLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class,
 "LBL_Selected" + bundleKey));
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.gridx = 2;
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
         gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
-        entitiesPanel.add(selectedEntitiesLabel, gridBagConstraints);
+        classesPanel.add(selectedLabel, gridBagConstraints);
 
-        selectedEntitiesScrollPane.setPreferredSize(new 
java.awt.Dimension(160, 130));
-        selectedEntitiesScrollPane.setViewportView(selectedEntitiesList);
-        
selectedEntitiesList.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(EntityClassesPanel.class,
 "ACSN_SelectedEntities")); // NOI18N
-        
selectedEntitiesList.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(EntityClassesPanel.class,
 "ACSD_SelectedEntities")); // NOI18N
+        selectedScrollPane.setPreferredSize(new java.awt.Dimension(160, 130));
+        selectedScrollPane.setViewportView(selectedList);
+        
selectedList.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class,
 "ACSN_Selected" + bundleKey));
+        
selectedList.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class,
 "ACSD_Selected" + bundleKey));
 
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.gridx = 2;
@@ -158,11 +172,11 @@ public class EntityClassesPanel extends 
javax.swing.JPanel {
         gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
         gridBagConstraints.weightx = 1.0;
         gridBagConstraints.weighty = 1.0;
-        entitiesPanel.add(selectedEntitiesScrollPane, gridBagConstraints);
+        classesPanel.add(selectedScrollPane, gridBagConstraints);
 
         buttonPanel.setLayout(new java.awt.GridBagLayout());
 
-        org.openide.awt.Mnemonics.setLocalizedText(addButton, 
org.openide.util.NbBundle.getMessage(EntityClassesPanel.class, "LBL_Add")); // 
NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(addButton, 
org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, "LBL_Add")); 
// NOI18N
         addButton.addActionListener(new java.awt.event.ActionListener() {
             public void actionPerformed(java.awt.event.ActionEvent evt) {
                 addButtonActionPerformed(evt);
@@ -172,7 +186,7 @@ public class EntityClassesPanel extends javax.swing.JPanel {
         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
         buttonPanel.add(addButton, gridBagConstraints);
 
-        org.openide.awt.Mnemonics.setLocalizedText(removeButton, 
org.openide.util.NbBundle.getMessage(EntityClassesPanel.class, "LBL_Remove")); 
// NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(removeButton, 
org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
"LBL_Remove")); // NOI18N
         removeButton.addActionListener(new java.awt.event.ActionListener() {
             public void actionPerformed(java.awt.event.ActionEvent evt) {
                 removeButtonActionPerformed(evt);
@@ -185,7 +199,7 @@ public class EntityClassesPanel extends javax.swing.JPanel {
         gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
         buttonPanel.add(removeButton, gridBagConstraints);
 
-        org.openide.awt.Mnemonics.setLocalizedText(addAllButton, 
org.openide.util.NbBundle.getMessage(EntityClassesPanel.class, "LBL_AddAll")); 
// NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(addAllButton, 
org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
"LBL_AddAll")); // NOI18N
         addAllButton.addActionListener(new java.awt.event.ActionListener() {
             public void actionPerformed(java.awt.event.ActionEvent evt) {
                 addAllButtonActionPerformed(evt);
@@ -198,7 +212,7 @@ public class EntityClassesPanel extends javax.swing.JPanel {
         gridBagConstraints.insets = new java.awt.Insets(17, 0, 0, 0);
         buttonPanel.add(addAllButton, gridBagConstraints);
 
-        org.openide.awt.Mnemonics.setLocalizedText(removeAllButton, 
org.openide.util.NbBundle.getMessage(EntityClassesPanel.class, 
"LBL_RemoveAll")); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(removeAllButton, 
org.openide.util.NbBundle.getMessage(ClassesSelectorPanel.class, 
"LBL_RemoveAll")); // NOI18N
         removeAllButton.addActionListener(new java.awt.event.ActionListener() {
             public void actionPerformed(java.awt.event.ActionEvent evt) {
                 removeAllButtonActionPerformed(evt);
@@ -217,51 +231,52 @@ public class EntityClassesPanel extends 
javax.swing.JPanel {
         gridBagConstraints.gridheight = 2;
         gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
         gridBagConstraints.insets = new java.awt.Insets(0, 11, 0, 11);
-        entitiesPanel.add(buttonPanel, gridBagConstraints);
+        classesPanel.add(buttonPanel, gridBagConstraints);
 
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.gridx = 0;
-        gridBagConstraints.gridy = 1;
+        gridBagConstraints.gridy = 0;
         gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
         gridBagConstraints.ipady = 80;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.weighty = 2.0;
+        gridBagConstraints.weightx = 1.0;
+        gridBagConstraints.weighty = 1.0;
         gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
-        add(entitiesPanel, gridBagConstraints);
+        add(classesPanel, gridBagConstraints);
     }// </editor-fold>//GEN-END:initComponents
 
     private void removeAllButtonActionPerformed(java.awt.event.ActionEvent 
evt) {//GEN-FIRST:event_removeAllButtonActionPerformed
-        availableEntities.addAll(selectedEntities);
-        selectedEntities.clear();
-        availableEntitiesList.setListData(availableEntities.toArray(new 
String[availableEntities.size()]));
-        selectedEntitiesList.setListData(selectedEntities.toArray(new 
String[selectedEntities.size()]));
+        available.addAll(selected);
+        selected.clear();
+        availableList.setListData(available.toArray(new 
String[available.size()]));
+        selectedList.setListData(selected.toArray(new 
String[selected.size()]));
         updateButtons();
         changeSupport.fireChange();
     }//GEN-LAST:event_removeAllButtonActionPerformed
 
     private void addAllButtonActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_addAllButtonActionPerformed
-        selectedEntities.addAll(availableEntities);
-        availableEntities.clear();
-        availableEntitiesList.setListData(availableEntities.toArray(new 
String[availableEntities.size()]));
-        selectedEntitiesList.setListData(selectedEntities.toArray(new 
String[selectedEntities.size()]));
+        selected.addAll(available);
+        available.clear();
+        availableList.setListData(available.toArray(new 
String[available.size()]));
+        selectedList.setListData(selected.toArray(new 
String[selected.size()]));
         updateButtons();
         changeSupport.fireChange();
     }//GEN-LAST:event_addAllButtonActionPerformed
 
     private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_removeButtonActionPerformed
-        availableEntities.addAll(selectedEntitiesList.getSelectedValuesList());
-        
selectedEntities.removeAll(selectedEntitiesList.getSelectedValuesList());
-        availableEntitiesList.setListData(availableEntities.toArray(new 
String[availableEntities.size()]));
-        selectedEntitiesList.setListData(selectedEntities.toArray(new 
String[selectedEntities.size()]));
+        available.addAll(selectedList.getSelectedValuesList());
+        selected.removeAll(selectedList.getSelectedValuesList());
+        availableList.setListData(available.toArray(new 
String[available.size()]));
+        selectedList.setListData(selected.toArray(new 
String[selected.size()]));
         updateButtons();
         changeSupport.fireChange();
     }//GEN-LAST:event_removeButtonActionPerformed
 
     private void addButtonActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_addButtonActionPerformed
-        selectedEntities.addAll(availableEntitiesList.getSelectedValuesList());
-        
availableEntities.removeAll(availableEntitiesList.getSelectedValuesList());
-        availableEntitiesList.setListData(availableEntities.toArray(new 
String[availableEntities.size()]));
-        selectedEntitiesList.setListData(selectedEntities.toArray(new 
String[selectedEntities.size()]));
+        selected.addAll(availableList.getSelectedValuesList());
+        available.removeAll(availableList.getSelectedValuesList());
+        availableList.setListData(available.toArray(new 
String[available.size()]));
+        selectedList.setListData(selected.toArray(new 
String[selected.size()]));
         updateButtons();
         changeSupport.fireChange();
     }//GEN-LAST:event_addButtonActionPerformed
@@ -270,26 +285,26 @@ public class EntityClassesPanel extends 
javax.swing.JPanel {
     // Variables declaration - do not modify//GEN-BEGIN:variables
     private javax.swing.JButton addAllButton;
     private javax.swing.JButton addButton;
-    private javax.swing.JLabel availableEntitiesLabel;
-    private javax.swing.JList<String> availableEntitiesList;
-    private javax.swing.JScrollPane availableEntitiesScrollPane;
+    private javax.swing.JLabel availableLabel;
+    private javax.swing.JList<String> availableList;
+    private javax.swing.JScrollPane availableScrollPane;
     private javax.swing.JPanel buttonPanel;
-    private javax.swing.JPanel entitiesPanel;
+    private javax.swing.JPanel classesPanel;
     private javax.swing.JButton removeAllButton;
     private javax.swing.JButton removeButton;
-    private javax.swing.JLabel selectedEntitiesLabel;
-    private javax.swing.JList<String> selectedEntitiesList;
-    private javax.swing.JScrollPane selectedEntitiesScrollPane;
+    private javax.swing.JLabel selectedLabel;
+    private javax.swing.JList<String> selectedList;
+    private javax.swing.JScrollPane selectedScrollPane;
     // End of variables declaration//GEN-END:variables
 
-    private final class EntitiesPanel extends JPanel {
+    private final class ClassesPanel extends JPanel {
 
         @Override
         public void doLayout() {
             super.doLayout();
 
-            Rectangle availableBounds = 
availableEntitiesScrollPane.getBounds();
-            Rectangle selectedBounds = selectedEntitiesScrollPane.getBounds();
+            Rectangle availableBounds = availableScrollPane.getBounds();
+            Rectangle selectedBounds = selectedScrollPane.getBounds();
 
             if (Math.abs(availableBounds.width - selectedBounds.width) > 1) {
                 GridBagConstraints buttonPanelConstraints = 
((GridBagLayout)getLayout()).getConstraints(buttonPanel);
@@ -298,40 +313,44 @@ public class EntityClassesPanel extends 
javax.swing.JPanel {
                 int xOffset = equalWidth - availableBounds.width;
 
                 availableBounds.width = equalWidth;
-                availableEntitiesScrollPane.setBounds(availableBounds);
+                availableScrollPane.setBounds(availableBounds);
 
                 Rectangle buttonBounds = buttonPanel.getBounds();
                 buttonBounds.x += xOffset;
                 buttonPanel.setBounds(buttonBounds);
 
-                Rectangle labelBounds = selectedEntitiesLabel.getBounds();
+                Rectangle labelBounds = selectedLabel.getBounds();
                 labelBounds.x += xOffset;
-                selectedEntitiesLabel.setBounds(labelBounds);
+                selectedLabel.setBounds(labelBounds);
 
                 selectedBounds.x += xOffset;
                 selectedBounds.width = totalWidth - equalWidth;
-                selectedEntitiesScrollPane.setBounds(selectedBounds);
+                selectedScrollPane.setBounds(selectedBounds);
             }
         }
     }
 
-    public static final class WizardPanel implements 
WizardDescriptor.Panel<WizardDescriptor>, ChangeListener {
+    public static final class WizardPanel implements 
WizardDescriptor.FinishablePanel<WizardDescriptor>, ChangeListener {
 
         private final ChangeSupport changeSupport = new ChangeSupport(this);
         private final String title;
-        private EntityClassesPanel component;
+        private final String key;
+        private final Function<Set<String>, String> validator;
+        private ClassesSelectorPanel component;
         private boolean componentInitialized;
         private WizardDescriptor wizardDescriptor;
-        private Map<String, String> entities;
+        private Map<String, Object> classes;
 
-        public WizardPanel(String wizardTitle) {
-            title = wizardTitle;
+        public WizardPanel(String title, String key, Function<Set<String>, 
String> validator) {
+            this.title = title;
+            this.key = key;
+            this.validator = validator;
         }
 
         @Override
-        public EntityClassesPanel getComponent() {
+        public ClassesSelectorPanel getComponent() {
             if (component == null) {
-                component = new EntityClassesPanel();
+                component = new ClassesSelectorPanel(key);
                 component.addChangeListener(this);
             }
             return component;
@@ -339,7 +358,7 @@ public class EntityClassesPanel extends javax.swing.JPanel {
 
         @Override
         public HelpCtx getHelp() {
-                return new HelpCtx(EntityClassesPanel.class);
+                return new HelpCtx(ClassesSelectorPanel.class);
         }
 
         @Override
@@ -360,30 +379,36 @@ public class EntityClassesPanel extends 
javax.swing.JPanel {
             }
             if (!componentInitialized) {
                 componentInitialized = true;
-                entities = (Map<String, String>) 
settings.getProperty(MicronautRepository.PROP_ENTITIES);
-                getComponent().initialize(entities.keySet());
+                classes = (Map<String, Object>) 
settings.getProperty(PROP_CLASSES);
+                getComponent().initialize(classes.keySet());
             }
         }
 
         @Override
         public boolean isValid() {
-            if (entities.isEmpty()) {
-                setErrorMessage(NbBundle.getMessage(EntityClassesPanel.class, 
"ERR_NoEntities", 
ProjectUtils.getInformation(Templates.getProject(wizardDescriptor)).getDisplayName()));
+            if (classes.isEmpty()) {
+                
setErrorMessage(NbBundle.getMessage(ClassesSelectorPanel.class, "ERR_No" + key, 
ProjectUtils.getInformation(Templates.getProject(wizardDescriptor)).getDisplayName()));
                 return false;
             }
-            if (getComponent().getSelectedEntities().isEmpty()) {
-                setErrorMessage(NbBundle.getMessage(EntityClassesPanel.class, 
"ERR_SelectEntities"));
+            String err = validator.apply(getComponent().getSelectedClasses());
+            if (err != null) {
+                setErrorMessage(err);
                 return false;
             }
             setErrorMessage(" "); // NOI18N
             return true;
         }
 
+        @Override
+        public boolean isFinishPanel() {
+            return !getComponent().getSelectedClasses().isEmpty();
+        }
+
         @Override
         public void storeSettings(WizardDescriptor settings) {
-            Set<String> selected = getComponent().getSelectedEntities();
-            Map<String, String> selEntities = 
entities.entrySet().stream().filter(entry -> 
selected.contains(entry.getKey())).collect(Collectors.toMap(entry -> 
entry.getKey(), entry -> entry.getValue()));
-            
wizardDescriptor.putProperty(MicronautRepository.PROP_SELECTED_ENTITIES, 
selEntities);
+            Set<String> selected = getComponent().getSelectedClasses();
+            Map<String, Object> selEntities = 
classes.entrySet().stream().filter(entry -> 
selected.contains(entry.getKey())).collect(Collectors.toMap(entry -> 
entry.getKey(), entry -> entry.getValue()));
+            wizardDescriptor.putProperty(PROP_SELECTED_CLASSES, selEntities);
         }
 
         @Override
diff --git 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautController.java
 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautController.java
index 80b2c25b3b..f8fb06ac09 100644
--- 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautController.java
+++ 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautController.java
@@ -29,21 +29,41 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
 import javax.swing.event.ChangeListener;
 import org.netbeans.api.java.project.JavaProjectConstants;
+import org.netbeans.api.java.source.ClassIndex;
+import org.netbeans.api.java.source.ClasspathInfo;
+import org.netbeans.api.java.source.ElementHandle;
 import org.netbeans.api.java.source.JavaSource;
 import org.netbeans.api.java.source.TreeMaker;
+import org.netbeans.api.project.FileOwnerQuery;
 import org.netbeans.api.project.Project;
 import org.netbeans.api.project.ProjectUtils;
 import org.netbeans.api.project.SourceGroup;
 import org.netbeans.api.project.Sources;
 import org.netbeans.api.templates.CreateDescriptor;
 import org.netbeans.api.templates.CreateFromTemplateHandler;
+import org.netbeans.modules.j2ee.core.api.support.SourceGroups;
 import org.netbeans.modules.j2ee.core.api.support.java.GenerationUtils;
 import org.netbeans.modules.j2ee.core.api.support.wizard.Wizards;
 import org.netbeans.spi.java.project.support.ui.templates.JavaTemplates;
@@ -69,6 +89,8 @@ public class MicronautController implements 
TemplateWizard.Iterator {
     }
 
     @NbBundle.Messages({
+        "MSG_SelectRepository=Select Data Repository Classes",
+        "MSG_SelectRepository_Prompt=Repositories to be called from 
Controllers",
         "MSG_SelectControllerName=Controller Name"
     })
     public static CreateFromTemplateHandler handler() {
@@ -81,13 +103,52 @@ public class MicronautController implements 
TemplateWizard.Iterator {
             @Override
             protected List<FileObject> createFromTemplate(CreateDescriptor 
desc) throws IOException {
                 try {
+                    final FileObject folder = desc.getTarget();
+                    final Project project = FileOwnerQuery.getOwner(folder);
+                    if (project == null) {
+                        DialogDisplayer.getDefault().notifyLater(new 
NotifyDescriptor.Message(Bundle.MSG_NoProject(folder.getPath()), 
NotifyDescriptor.ERROR_MESSAGE));
+                        return Collections.emptyList();
+                    }
+                    final SourceGroup sourceGroup = 
SourceGroups.getFolderSourceGroup(ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA),
 folder);
+                    if (sourceGroup != null) {
+                        Set<ElementHandle<TypeElement>> repositoryClasses = 
getRepositoryClasses(sourceGroup);
+                        if (!repositoryClasses.isEmpty()) {
+                            List<NotifyDescriptor.QuickPick.Item> items = 
repositoryClasses.stream().map(handle -> {
+                                String fqn = handle.getQualifiedName();
+                                int idx = fqn.lastIndexOf('.');
+                                return idx < 0 ? new 
NotifyDescriptor.QuickPick.Item(fqn, null) : new 
NotifyDescriptor.QuickPick.Item(fqn.substring(idx + 1), fqn.substring(0, idx));
+                            }).collect(Collectors.toList());
+                            NotifyDescriptor.QuickPick qpt = new 
NotifyDescriptor.QuickPick(Bundle.MSG_SelectRepository(), 
Bundle.MSG_SelectRepository_Prompt(), items, true);
+                            if (DialogDescriptor.OK_OPTION != 
DialogDisplayer.getDefault().notify(qpt)) {
+                                return Collections.emptyList();
+                            }
+                            List<FileObject> generated = new ArrayList<>();
+                            for (NotifyDescriptor.QuickPick.Item item : 
qpt.getItems()) {
+                                if (item.isSelected()) {
+                                    String label = item.getLabel();
+                                    if 
(label.toLowerCase().endsWith(("repository"))) { //NOI18N
+                                        label = label.substring(0, 
label.length() - 10);
+                                    }
+                                    FileObject fo = generate(folder, label, 
item.getDescription() != null ? item.getDescription() + '.' + item.getLabel() : 
item.getLabel());
+                                    if (fo != null) {
+                                        generated.add(fo);
+                                    }
+                                }
+                            }
+                            if (!generated.isEmpty()) {
+                                return generated;
+                            }
+                        }
+                    }
                     NotifyDescriptor.InputLine inputLine = new 
NotifyDescriptor.InputLine(Bundle.MSG_SelectControllerName(), 
Bundle.MSG_SelectControllerName());
                     if (DialogDescriptor.OK_OPTION == 
DialogDisplayer.getDefault().notify(inputLine)) {
                         List<FileObject> generated = new ArrayList<>();
                         String name = inputLine.getInputText();
                         if (!name.isEmpty()) {
-                            String controllerName = name.substring(0, 
1).toUpperCase() + name.substring(1) + "Controller"; // NOI18N
-                            FileObject fo = generate(desc.getTarget(), 
controllerName);
+                            if (name.toLowerCase().endsWith(("controller"))) { 
//NOI18N
+                                name = name.substring(0, name.length() - 10);
+                            }
+                            FileObject fo = generate(desc.getTarget(), name, 
null);
                             if (fo != null) {
                                 generated.add(fo);
                             }
@@ -102,20 +163,35 @@ public class MicronautController implements 
TemplateWizard.Iterator {
         };
     }
 
-    private WizardDescriptor.Panel panel;
+    private WizardDescriptor.Panel[] panels;
+    private int index;
     private WizardDescriptor wizardDescriptor;
+    private FileObject targetFolder;
 
     @Override
     public Set<DataObject> instantiate(TemplateWizard wiz) throws IOException {
         Set<DataObject> generated = new HashSet<>();
-        FileObject targetFolder = Templates.getTargetFolder(wiz);
-        String targetName = Templates.getTargetName(wiz);
-        if (targetFolder != null && targetName != null && 
!targetName.isEmpty()) {
-            FileObject fo = generate(targetFolder, targetName);
+        Map<String, ElementHandle<TypeElement>> selectedRepositories = 
(Map<String, ElementHandle<TypeElement>>) 
wiz.getProperty(ClassesSelectorPanel.PROP_SELECTED_CLASSES);
+        for (String fqn : selectedRepositories.keySet()) {
+            int idx = fqn.lastIndexOf('.');
+            String label = idx < 0 ? fqn : fqn.substring(idx + 1);
+            if (label.toLowerCase().endsWith(("repository"))) { //NOI18N
+                label = label.substring(0, label.length() - 10);
+            }
+            FileObject fo = generate(targetFolder, label, fqn);
             if (fo != null) {
                 generated.add(DataObject.find(fo));
             }
         }
+        if (generated.isEmpty()) {
+            String targetName = Templates.getTargetName(wiz);
+            if (targetName != null && !targetName.isEmpty()) {
+                FileObject fo = generate(targetFolder, targetName, null);
+                if (fo != null) {
+                    generated.add(DataObject.find(fo));
+                }
+            }
+        }
         return generated;
     }
 
@@ -123,18 +199,35 @@ public class MicronautController implements 
TemplateWizard.Iterator {
     public void initialize(TemplateWizard wiz) {
         wizardDescriptor = wiz;
 
+        targetFolder = Templates.getTargetFolder(wizardDescriptor);
         Project project = Templates.getProject(wizardDescriptor);
         Sources sources = ProjectUtils.getSources(project);
         SourceGroup[] sourceGroups = 
sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
 
         if(sourceGroups.length == 0) {
             sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC);
-            panel = Templates.buildSimpleTargetChooser(project, 
sourceGroups).create();
+            panels = new WizardDescriptor.Panel[] {
+                Templates.buildSimpleTargetChooser(project, 
sourceGroups).create()
+            };
         } else {
-            panel = JavaTemplates.createPackageChooser(project, sourceGroups);
+            List<WizardDescriptor.Panel> p = new ArrayList<>();
+            SourceGroup sourceGroup = 
SourceGroups.getFolderSourceGroup(sourceGroups, targetFolder);
+            if (sourceGroup != null) {
+                Set<ElementHandle<TypeElement>> repositoryClasses = 
getRepositoryClasses(sourceGroup);
+                if (!repositoryClasses.isEmpty()) {
+                    Map<String, ElementHandle<TypeElement>> repositories = new 
HashMap<>();
+                    for (ElementHandle<TypeElement> handle : 
repositoryClasses) {
+                        repositories.put(handle.getQualifiedName(), handle);
+                    }
+                    wiz.putProperty(ClassesSelectorPanel.PROP_CLASSES, 
repositories);
+                    p.add(new 
ClassesSelectorPanel.WizardPanel(NbBundle.getMessage(MicronautController.class, 
"Templates/Micronaut/Controller"), "Repositories", s -> null)); //NOI18N
+                }
+            }
+            p.add(JavaTemplates.createPackageChooser(project, sourceGroups));
+            panels = p.toArray(new WizardDescriptor.Panel[0]);
         }
 
-        Wizards.mergeSteps(wiz, new WizardDescriptor.Panel[] {panel}, null);
+        Wizards.mergeSteps(wiz, panels, null);
     }
 
     @Override
@@ -143,7 +236,7 @@ public class MicronautController implements 
TemplateWizard.Iterator {
 
     @Override
     public WizardDescriptor.Panel<WizardDescriptor> current() {
-        return panel;
+        return panels[index];
     }
 
     @Override
@@ -153,22 +246,28 @@ public class MicronautController implements 
TemplateWizard.Iterator {
 
     @Override
     public boolean hasNext() {
-        return false;
+        return index < (panels.length - 1) && !(current() instanceof 
WizardDescriptor.FinishablePanel && ((WizardDescriptor.FinishablePanel) 
current()).isFinishPanel());
     }
 
     @Override
     public boolean hasPrevious() {
-        return false;
+        return index > 0;
     }
 
     @Override
     public void nextPanel() {
-        throw new NoSuchElementException();
+        if ((index + 1) == panels.length) {
+            throw new NoSuchElementException();
+        }
+        index++;
     }
 
     @Override
     public void previousPanel() {
-        throw new NoSuchElementException();
+        if (index == 0) {
+            throw new NoSuchElementException();
+        }
+        index--;
     }
 
     @Override
@@ -179,11 +278,27 @@ public class MicronautController implements 
TemplateWizard.Iterator {
     public void removeChangeListener(ChangeListener l) {
     }
 
+    private static Set<ElementHandle<TypeElement>> getRepositoryClasses(final 
SourceGroup sourceGroup) throws IllegalArgumentException {
+        ClasspathInfo cpInfo = 
ClasspathInfo.create(sourceGroup.getRootFolder());
+        Set<ElementHandle<TypeElement>> repositoryClasses = new HashSet<>();
+        LinkedList<ElementHandle<TypeElement>> bases = new LinkedList<>();
+        bases.add(ElementHandle.createTypeElementHandle(ElementKind.INTERFACE, 
"io.micronaut.data.repository.CrudRepository")); //NOI18N
+        while (!bases.isEmpty()) {
+            ElementHandle<TypeElement> base = bases.removeFirst();
+            bases.addAll(cpInfo.getClassIndex().getElements(base, 
EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS), 
EnumSet.of(ClassIndex.SearchScope.DEPENDENCIES)));
+            Set<ElementHandle<TypeElement>> srcElements = 
cpInfo.getClassIndex().getElements(base, 
EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS), 
EnumSet.of(ClassIndex.SearchScope.SOURCE));
+            bases.addAll(srcElements);
+            repositoryClasses.addAll(srcElements);
+        }
+        return repositoryClasses;
+    }
+
     @NbBundle.Messages({
         "MSG_ControllerClass=Controller class {0}\n"
     })
-    private static FileObject generate(FileObject folder, String 
controllerName) {
+    private static FileObject generate(FileObject folder, String name, String 
repositoryFQN) {
         try {
+            String controllerName = name.substring(0, 1).toUpperCase() + 
name.substring(1) + "Controller"; // NOI18N
             FileObject fo = GenerationUtils.createClass(folder, 
controllerName, Bundle.MSG_ControllerClass(controllerName));
             if (fo != null) {
                 JavaSource js = JavaSource.forFileObject(fo);
@@ -194,16 +309,47 @@ public class MicronautController implements 
TemplateWizard.Iterator {
                         if (origTree.getKind() == Tree.Kind.CLASS) {
                             GenerationUtils gu = 
GenerationUtils.newInstance(copy);
                             TreeMaker tm = copy.getTreeMaker();
-                            String name = controllerName.toLowerCase();
-                            if (name.endsWith("controller")) {
-                                name = name.substring(0, name.length() - 10);
-                            }
                             List<ExpressionTree> annArgs = 
Collections.singletonList(gu.createAnnotationArgument(null, "/" + 
name.toLowerCase())); //NOI18N
-                            ClassTree cls = gu.addAnnotation((ClassTree) 
origTree, gu.createAnnotation("io.micronaut.http.annotation.Controller", 
annArgs));
-                            List<ExpressionTree> getAnnArgs = 
Arrays.asList(gu.createAnnotationArgument("uri", "/"), 
gu.createAnnotationArgument("produces", "text/plain")); //NOI18N
-                            ModifiersTree mods = 
tm.Modifiers(Collections.singleton(Modifier.PUBLIC), 
Collections.singletonList(gu.createAnnotation("io.micronaut.http.annotation.Get",
 getAnnArgs))); //NOI18N
-                            MethodTree indexMethod = tm.Method(mods, "index", 
tm.QualIdent("java.lang.String"), Collections.<TypeParameterTree>emptyList(), 
Collections.<VariableTree>emptyList(), Collections.<ExpressionTree>emptyList(), 
"{return \"Example Response\";}", null); //NOI18N
-                            cls = tm.addClassMember(cls, indexMethod);
+                            ClassTree cls = gu.addAnnotation((ClassTree) 
origTree, gu.createAnnotation("io.micronaut.http.annotation.Controller", 
annArgs)); //NOI18N
+                            if (repositoryFQN != null) {
+                                String repositoryFieldName = name.substring(0, 
1).toLowerCase() + name.substring(1) + "Repository"; //NOI18N
+                                VariableTree repositoryField = 
tm.Variable(tm.Modifiers(EnumSet.of(Modifier.PRIVATE, Modifier.FINAL)), 
repositoryFieldName, tm.QualIdent(repositoryFQN), null);
+                                cls = tm.addClassMember(cls, repositoryField);
+                                VariableTree repositoryParam = 
tm.Variable(tm.Modifiers(Collections.emptySet()), repositoryFieldName, 
tm.QualIdent(repositoryFQN), null);
+                                MethodTree ctor = 
tm.Constructor(tm.Modifiers(Collections.singleton(Modifier.PUBLIC)), 
Collections.<TypeParameterTree>emptyList(), 
Collections.singletonList(repositoryParam), 
Collections.<ExpressionTree>emptyList(), "{this." + repositoryFieldName + "=" + 
repositoryFieldName + ";}"); //NOI18N
+                                cls = tm.addClassMember(cls, ctor);
+                                TypeElement te = 
copy.getElements().getTypeElement(repositoryFQN);
+                                if (te != null) {
+                                    ModifiersTree mods = 
tm.Modifiers(Collections.singleton(Modifier.PUBLIC), 
Collections.singletonList(gu.createAnnotation("io.micronaut.http.annotation.Get")));
 //NOI18N
+                                    List<? extends ExecutableElement> 
findAllMethods = 
ElementFilter.methodsIn(copy.getElements().getAllMembers(te)).stream().filter(el
 -> "findAll".contentEquals(el.getSimpleName())).collect(Collectors.toList()); 
//NOI18N
+                                    Optional<? extends ExecutableElement> 
findAll = findAllMethods.stream().filter(el -> 
el.getParameters().isEmpty()).findAny();
+                                    if (findAll.isPresent()) {
+                                        TypeMirror returnType = 
((ExecutableType) copy.getTypes().asMemberOf((DeclaredType) te.asType(), 
findAll.get())).getReturnType();
+                                        Optional<? extends ExecutableElement> 
findAllPageable = findAllMethods.stream().filter(el -> {
+                                            if (el.getParameters().size() != 
1) {
+                                                return false;
+                                            }
+                                            TypeMirror paramType = 
el.getParameters().get(0).asType();
+                                            return paramType.getKind() == 
TypeKind.DECLARED && 
"io.micronaut.data.model.Pageable".contentEquals(((TypeElement) ((DeclaredType) 
paramType).asElement()).getQualifiedName()); //NOI18N
+                                        }).findFirst();
+                                        if (findAllPageable.isPresent()) {
+                                            ExecutableElement el = 
findAllPageable.get();
+                                            ExecutableType type = 
(ExecutableType) copy.getTypes().asMemberOf((DeclaredType) te.asType(), el);
+                                            VariableTree param = 
tm.Variable(tm.Modifiers(0, 
Collections.singletonList(gu.createAnnotation("jakarta.validation.Valid"))), 
"pageable", tm.Type(type.getParameterTypes().get(0)), null); //NOI18N
+                                            MethodTree indexMethod = 
tm.Method(mods, "list", tm.Type(returnType), 
Collections.<TypeParameterTree>emptyList(), Collections.singletonList(param), 
Collections.<ExpressionTree>emptyList(), "{return " + repositoryFieldName + 
".findAll(pageable).getContent();}", null); //NOI18N
+                                            cls = tm.addClassMember(cls, 
indexMethod);
+                                        } else {
+                                            MethodTree indexMethod = 
tm.Method(mods, "list", tm.Type(returnType), 
Collections.<TypeParameterTree>emptyList(), 
Collections.<VariableTree>emptyList(), Collections.<ExpressionTree>emptyList(), 
"{return " + repositoryFieldName + ".findAll();}", null); //NOI18N
+                                            cls = tm.addClassMember(cls, 
indexMethod);
+                                        }
+                                    }
+                                }
+                            } else {
+                                List<ExpressionTree> getAnnArgs = 
Arrays.asList(gu.createAnnotationArgument("uri", "/"), 
gu.createAnnotationArgument("produces", "text/plain")); //NOI18N
+                                ModifiersTree mods = 
tm.Modifiers(Collections.singleton(Modifier.PUBLIC), 
Collections.singletonList(gu.createAnnotation("io.micronaut.http.annotation.Get",
 getAnnArgs))); //NOI18N
+                                MethodTree indexMethod = tm.Method(mods, 
"index", tm.QualIdent("java.lang.String"), 
Collections.<TypeParameterTree>emptyList(), 
Collections.<VariableTree>emptyList(), Collections.<ExpressionTree>emptyList(), 
"{return \"Example Response\";}", null); //NOI18N
+                                cls = tm.addClassMember(cls, indexMethod);
+                            }
                             copy.rewrite(origTree, cls);
                         }
                     }).commit();
diff --git 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautRepository.java
 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautRepository.java
index 82999146bd..ebbed0d11b 100644
--- 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautRepository.java
+++ 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/db/MicronautRepository.java
@@ -18,15 +18,10 @@
  */
 package org.netbeans.modules.micronaut.db;
 
-import com.sun.source.tree.BlockTree;
 import com.sun.source.tree.ClassTree;
 import com.sun.source.tree.ExpressionTree;
-import com.sun.source.tree.MethodTree;
-import com.sun.source.tree.ModifiersTree;
 import com.sun.source.tree.ParameterizedTypeTree;
 import com.sun.source.tree.Tree;
-import com.sun.source.tree.TypeParameterTree;
-import com.sun.source.tree.VariableTree;
 import com.sun.source.util.TreePath;
 import java.io.IOException;
 import java.sql.Connection;
@@ -176,8 +171,6 @@ public class MicronautRepository implements 
TemplateWizard.Iterator {
         };
     }
 
-    static final String PROP_ENTITIES = "wizard-entities"; //NOI18N
-    static final String PROP_SELECTED_ENTITIES = "wizard-selected-entities"; 
//NOI18N
     private WizardDescriptor.Panel panel;
     private WizardDescriptor wizardDescriptor;
     private FileObject targetFolder;
@@ -187,7 +180,7 @@ public class MicronautRepository implements 
TemplateWizard.Iterator {
     public Set<DataObject> instantiate(TemplateWizard wiz) throws IOException {
         String dialect = getDialect(jpaSupported);
         Set<DataObject> generated = new HashSet<>();
-        Map<String, String> selectedEntities = (Map<String, String>) 
wiz.getProperty(PROP_SELECTED_ENTITIES);
+        Map<String, String> selectedEntities = (Map<String, String>) 
wiz.getProperty(ClassesSelectorPanel.PROP_SELECTED_CLASSES);
         for (Map.Entry<String, String> entry : selectedEntities.entrySet()) {
             String fqn = entry.getKey();
             int idx = fqn.lastIndexOf('.');
@@ -204,11 +197,13 @@ public class MicronautRepository implements 
TemplateWizard.Iterator {
     public void initialize(TemplateWizard wiz) {
         wizardDescriptor = wiz;
 
-        panel = new 
EntityClassesPanel.WizardPanel(NbBundle.getMessage(MicronautRepository.class, 
"Templates/Micronaut/Repository"));
+        panel = new 
ClassesSelectorPanel.WizardPanel(NbBundle.getMessage(MicronautRepository.class, 
"Templates/Micronaut/Repository"), "Entities", selectedEntities -> {
+            return selectedEntities.isEmpty() ? 
NbBundle.getMessage(MicronautRepository.class, "ERR_SelectEntities") : null;
+        });
         Wizards.mergeSteps(wizardDescriptor, new WizardDescriptor.Panel[] {
             panel
         }, new String[] {
-            NbBundle.getMessage(MicronautRepository.class, "LBL_EntityClasses")
+            NbBundle.getMessage(MicronautRepository.class, "LBL_Entities")
         });
 
         targetFolder = Templates.getTargetFolder(wizardDescriptor);
@@ -216,8 +211,8 @@ public class MicronautRepository implements 
TemplateWizard.Iterator {
         SourceGroup sourceGroup = 
SourceGroups.getFolderSourceGroup(ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA),
 targetFolder);
         if (sourceGroup != null) {
             jpaSupported = Utils.isJPASupported(sourceGroup);
-            Map<String, String> entities = 
MicronautRepository.getEntityClasses(sourceGroup, jpaSupported);
-            wiz.putProperty(PROP_ENTITIES, entities);
+            Map<String, String> entities = getEntityClasses(sourceGroup, 
jpaSupported);
+            wiz.putProperty(ClassesSelectorPanel.PROP_CLASSES, entities);
         }
     }
 
@@ -263,7 +258,7 @@ public class MicronautRepository implements 
TemplateWizard.Iterator {
     public void removeChangeListener(ChangeListener l) {
     }
 
-    static Map<String, String> getEntityClasses(SourceGroup sg, boolean 
jpaSupported) {
+    private static Map<String, String> getEntityClasses(SourceGroup sg, 
boolean jpaSupported) {
         final Map<String, String> entities = new HashMap<>();
         JavaSource js = 
JavaSource.create(ClasspathInfo.create(sg.getRootFolder()));
         if (js != null) {
diff --git 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/Controller.html
 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/Controller.html
index 71db5d378c..07df97765d 100644
--- 
a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/Controller.html
+++ 
b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/Controller.html
@@ -24,5 +24,7 @@
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 </head>
 <BODY>
-Creates a Micronaut Controller class with a default GET endpoint.
+Creates Micronaut Controller classes with default GET endpoints based on
+existing data repository interfaces or plain. This template creates a 
controller
+class for each selected repository interface.
 </BODY></HTML>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to