diff --git a/.gitignore b/.gitignore
index 8cad2206..88a81245 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
/target/
/infra/target/
-/jakartaee/target/
/mvc/target/
/rest/target/
/runtime/target/
-/jakarta-ee/target/
\ No newline at end of file
+/jakarta-ee/target/
+/jsf/target/
\ No newline at end of file
diff --git a/jsf/nbactions.xml b/jsf/nbactions.xml
new file mode 100644
index 00000000..8d97cd1d
--- /dev/null
+++ b/jsf/nbactions.xml
@@ -0,0 +1,19 @@
+
+
+
+ run
+
+ nbm:run-ide
+
+
+
+ debug
+
+ nbm:run-ide
+
+
+ true
+ -J-agentlib:jdwp=transport=dt_socket,suspend=n,server=n,address=${jpda.address}
+
+
+
diff --git a/jsf/pom.xml b/jsf/pom.xml
new file mode 100644
index 00000000..85fa3183
--- /dev/null
+++ b/jsf/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+ io.github.jeddict
+ jeddict-extensions
+ 5.2
+
+ jsf
+ JSF
+ nbm
+
+
+ ${basedir}/../
+
+
+
+
+
+ org.codehaus.mojo
+ nbm-maven-plugin
+ true
+
+
+
+ org.netbeans.modules:org-netbeans-modules-maven-embedder
+ impl
+
+
+
+
+
+
+
+
+ ${project.groupId}
+ infra
+ ${project.version}
+
+
+ ${project.groupId}
+ jakarta-ee
+ ${project.version}
+
+
+ org.netbeans.api
+ org-netbeans-modules-projectapi
+ ${netbeans.version}
+
+
+ org.netbeans.api
+ org-openide-loaders
+ ${netbeans.version}
+
+
+ org.netbeans.modules
+ org-netbeans-modules-maven-embedder
+ ${netbeans.version}
+
+
+
\ No newline at end of file
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/controller/Bundle.properties b/jsf/src/main/java/io/github/jeddict/jsf/controller/Bundle.properties
new file mode 100644
index 00000000..169bce30
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/controller/Bundle.properties
@@ -0,0 +1,19 @@
+MSG_Progress_Now_Generating= Generating CDI repository :
+TITLE_Maven_Project_Not_Found= Maven Project
+MSG_Maven_Project_Not_Found= Maven(pom.xml) Project not found
+JsfControllerPanel.invalidPackage.message= The\u00a0Package\u00a0Name\u00a0is\u00a0not\u00a0valid
+JsfControllerPanel.invalidSuffix.message= The\u00a0Suffix\u00a0Name\u00a0is\u00a0not\u00a0valid
+JsfControllerPanel.reservedSuffix.message= 'Service' is reserved suffix, please choose another suffix
+JsfControllerPanel.invalidPrefix.message= The\u00a0Prefix\u00a0Name\u00a0is\u00a0not\u00a0valid
+JsfControllerPanel.invalidAppPackage.message= The\u00a0Application Package\u00a0Name\u00a0is\u00a0not\u00a0valid
+
+JsfControllerPanel.entityLabel.text=
+JsfControllerPanel.prefixField.toolTipText=Prefix
+JsfControllerPanel.prefixField.text=
+JsfControllerPanel.packageTextField.text=
+JsfControllerPanel.packagePrefixLabel.text= +
+JsfControllerPanel.packageLabel.text=Package :
+JsfControllerPanel.warningLabel.text=
+JsfControllerPanel.nameLabel.text=File Pattern :
+JsfControllerPanel.suffixField.toolTipText=Suffix
+JsfControllerPanel.suffixField.text=Repository
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerData.java b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerData.java
new file mode 100644
index 00000000..12e896ff
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerData.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2013-2018 the original author or authors from the Jeddict project (https://jeddict.github.io/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.github.jeddict.jsf.controller;
+
+import io.github.jeddict.jcode.LayerConfigData;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ *
+ * @author Shiwani Gupta
+ */
+public class JsfControllerData extends LayerConfigData {
+
+ private String prefixName;
+ private String suffixName;
+ private String _package;
+ private boolean isNamed;
+ private boolean cdi = true;
+
+ /**
+ * @return the _package
+ */
+ public String getPackage() {
+ return _package;
+ }
+
+ /**
+ * @param _package the _package to set
+ */
+ public void setPackage(String _package) {
+ this._package = _package;
+ }
+
+ /**
+ * @return the suffixName
+ */
+ public String getSuffixName() {
+ if(StringUtils.isBlank(suffixName)){
+ suffixName = "Controller";
+ }
+ return suffixName;
+ }
+
+ /**
+ * @param suffixName the suffixName to set
+ */
+ public void setSuffixName(String suffixName) {
+ this.suffixName = suffixName;
+ }
+
+ /**
+ * @return the prefixName
+ */
+ public String getPrefixName() {
+ return prefixName;
+ }
+
+ /**
+ * @param prefixName the prefixName to set
+ */
+ public void setPrefixName(String prefixName) {
+ this.prefixName = prefixName;
+ }
+
+ /**
+ * @return the isNamed
+ */
+ public boolean isNamed() {
+ return isNamed;
+ }
+
+ /**
+ * @param isNamed the isNamed to set
+ */
+ public void setNamed(boolean isNamed) {
+ this.isNamed = isNamed;
+ }
+
+ /**
+ * @return the isCDI
+ */
+ public boolean isCDI() {
+ return cdi;
+ }
+
+ /**
+ * @param cdi the cdi to set
+ */
+ public void setCDI(boolean cdi) {
+ this.cdi = cdi;
+ }
+
+ @Override
+ public List getUsageDetails() {
+ return Collections.emptyList();
+ }
+}
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerGenerator.java b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerGenerator.java
new file mode 100644
index 00000000..5a372d10
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerGenerator.java
@@ -0,0 +1,159 @@
+/**
+ * Copyright 2013-2018 the original author or authors from the Jeddict project (https://jeddict.github.io/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.github.jeddict.jsf.controller;
+
+import io.github.jeddict.jcode.ApplicationConfigData;
+import io.github.jeddict.jcode.Generator;
+import io.github.jeddict.jcode.annotation.ConfigData;
+import io.github.jeddict.jcode.annotation.Technology;
+import static io.github.jeddict.jcode.annotation.Technology.Type.CONTROLLER;
+import io.github.jeddict.jcode.task.progress.ProgressHandler;
+import static io.github.jeddict.jcode.util.Constants.JAVA_EXT;
+import static io.github.jeddict.jcode.util.ProjectHelper.getFolderForPackage;
+import static io.github.jeddict.jcode.util.StringHelper.firstLower;
+import static io.github.jeddict.jcode.util.StringHelper.firstUpper;
+import io.github.jeddict.jpa.spec.Entity;
+import io.github.jeddict.jpa.spec.EntityMappings;
+import io.github.jeddict.repository.RepositoryData;
+import io.github.jeddict.repository.RepositoryGenerator;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import static java.util.stream.Collectors.toList;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.openide.filesystems.FileObject;
+import org.openide.util.lookup.ServiceProvider;
+import io.github.jeddict.jcode.util.FileUtil;
+
+/**
+ * Generates repository for entity classes.
+ *
+ * @author Shiwani Gupta
+ */
+@ServiceProvider(service = Generator.class)
+@Technology(type = CONTROLLER,
+ label = "JSF Controller",
+ panel = JsfControllerPanel.class,
+ parents = RepositoryGenerator.class
+)
+public final class JsfControllerGenerator implements Generator {
+
+ private static final String TEMPLATE = "io/github/jeddict/template/";
+ public static final String REPOSITORY_ABSTRACT = "Abstract";
+
+ @ConfigData
+ private JsfControllerData controllerData;
+
+ @ConfigData
+ private RepositoryData repositoryData;
+
+ @ConfigData
+ private EntityMappings entityMapping;
+
+ @ConfigData
+ private ApplicationConfigData appConfigData;
+
+ @ConfigData
+ private ProgressHandler handler;
+
+ private Project targetProject;
+
+ private SourceGroup targetSource;
+
+ private String targetPackage;
+
+ private Project gatewayProject;
+
+ private SourceGroup gatewaySource;
+
+ @Override
+ public void execute() throws IOException {
+ targetProject = appConfigData.getTargetProject();
+ targetSource = appConfigData.getTargetSourceGroup();
+ gatewayProject = appConfigData.getGatewayProject();
+ gatewaySource = appConfigData.getGatewaySourceGroup();
+ targetPackage = appConfigData.getTargetPackage();
+ generate();
+ generatePagination();
+ generateJsfUtil();
+
+ }
+
+ private Set generate() throws IOException {
+
+ final Set createdFiles = new HashSet<>();
+ for (Entity entity : entityMapping.getGeneratedEntity().collect(toList())) {
+ handler.progress(controllerData.getPrefixName() + entity.getClazz() + controllerData.getSuffixName());
+ createdFiles.add(generateController(entity, true));
+
+ }
+ return createdFiles;
+ }
+
+ private void generatePagination() throws IOException {
+ String _package = targetPackage + ".util";
+ FileObject targetFolder = getFolderForPackage(targetSource, _package, true);
+ String fileName = "PaginationHelper";
+ Map param = new HashMap<>();
+ param.put("package", _package);
+ handler.progress(fileName);
+ FileUtil.expandTemplate(TEMPLATE + "util/PaginationHelper.java.ftl", targetFolder, fileName + '.' + JAVA_EXT, param);
+ }
+
+ private void generateJsfUtil() throws IOException {
+ String _package = targetPackage + ".util";
+ FileObject targetFolder = getFolderForPackage(targetSource, _package, true);
+ String fileName = "JsfUtil";
+ Map param = new HashMap<>();
+ param.put("package", _package);
+ handler.progress(fileName);
+ FileUtil.expandTemplate(TEMPLATE + "util/JsfUtil.java.ftl", targetFolder, fileName + '.' + JAVA_EXT, param);
+ }
+
+ private FileObject generateController(final Entity entity, boolean overrideExisting) throws IOException {
+ FileObject targetFolder = getFolderForPackage(targetSource,
+ entity.getAbsolutePackage(targetPackage + '.' + controllerData.getPackage()),
+ true);
+
+ final String entitySimpleName = entity.getClazz();
+ String controllerName = controllerData.getPrefixName() + entitySimpleName + controllerData.getSuffixName();
+ String entityClass = firstUpper(entitySimpleName);
+ String entityInstance = firstLower(entitySimpleName);
+ String entityFQN = entity.getFQN();
+
+ String repositoryName = repositoryData.getRepositoryPrefixName() + entitySimpleName + repositoryData.getRepositorySuffixName();
+ String repositoryInstance = firstLower(repositoryName);
+ String repositoryFQN = entity.getAbsolutePackage(repositoryData.getRepositoryPackage()) + '.' + repositoryName;;
+
+ Map params = new HashMap<>();
+ params.put("entityInstance", entityInstance);
+ params.put("Entity", entityClass);
+ params.put("EntityController", controllerName);
+ params.put("named", controllerData.isNamed());
+ params.put("EntityRepository", repositoryName);
+ params.put("RepositoryInstance", repositoryInstance);
+ params.put("EntityClass_FQN", entityFQN);
+ params.put("RepositoryClass_FQN", targetPackage + '.' + repositoryFQN);
+ params.put("JsfUtil_FQN", targetPackage + ".util.JsfUtil");
+ params.put("PaginationHelper_FQN", targetPackage + ".util.PaginationHelper");
+ params.put("package", targetPackage + '.' + entity.getAbsolutePackage(controllerData.getPackage()));
+
+ return FileUtil.expandTemplate(TEMPLATE + "controller/EntityController.java.ftl", targetFolder, controllerName + '.' + JAVA_EXT, params);
+ }
+}
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerPanel.form b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerPanel.form
new file mode 100644
index 00000000..f05c1b04
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerPanel.form
@@ -0,0 +1,238 @@
+
+
+
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerPanel.java b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerPanel.java
new file mode 100644
index 00000000..e5d1ae22
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/controller/JsfControllerPanel.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright 2013-2018 the original author or authors from the Jeddict project (https://jeddict.github.io/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.github.jeddict.jsf.controller;
+
+import io.github.jeddict.jcode.LayerConfigPanel;
+import static io.github.jeddict.jcode.util.JavaIdentifiers.isValidPackageName;
+import javax.lang.model.SourceVersion;
+import org.apache.commons.lang.StringUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author Shiwani Gupta
+ */
+public class JsfControllerPanel extends LayerConfigPanel {
+
+ private static final String DEFAULT_PACKAGE = "repository";
+
+ public JsfControllerPanel() {
+ initComponents();
+ }
+
+ @Override
+ public boolean hasError() {
+ warningLabel.setText("");
+ if (!isValidPackageName(getPackage())) {
+ warningLabel.setText(NbBundle.getMessage(JsfControllerPanel.class, "RepositoryPanel.invalidPackage.message"));
+ return true;
+ }
+ String prefix = getPrefix();
+ String suffix = getSuffix();
+
+ if (StringUtils.isNotBlank(prefix) && !SourceVersion.isName(prefix)) {
+ warningLabel.setText(NbBundle.getMessage(JsfControllerPanel.class, "RepositoryPanel.invalidPrefix.message"));
+ return true;
+ }
+ if (StringUtils.isNotBlank(suffix) && !SourceVersion.isName(prefix + '_' + suffix)) {
+ warningLabel.setText(NbBundle.getMessage(JsfControllerPanel.class, "RepositoryPanel.invalidSuffix.message"));
+ return true;
+ }
+ if ("Service".equals(suffix)) {
+ warningLabel.setText(NbBundle.getMessage(JsfControllerPanel.class, "RepositoryPanel.reservedSuffix.message"));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void read() {
+ JsfControllerData data = this.getConfigData();
+ if (StringUtils.isNotBlank(data.getPackage())) {
+ setPackage(data.getPackage());
+ }
+ if (StringUtils.isNotBlank(data.getPrefixName())) {
+ setPrefix(data.getPrefixName());
+ }
+ if (StringUtils.isNotBlank(data.getSuffixName())) {
+ setSuffix(data.getSuffixName());
+ }
+ }
+
+ @Override
+ public void store() {
+ JsfControllerData data = this.getConfigData();
+ data.setPrefixName(getPrefix());
+ data.setSuffixName(getSuffix());
+ data.setPackage(getPackage());
+ }
+
+ @Override
+ public void init(String _package, Project project, SourceGroup sourceGroup) {
+ setPackage(DEFAULT_PACKAGE);
+ addChangeListener(prefixField);
+ addChangeListener(suffixField);
+ }
+
+ public String getPackage() {
+ return packageTextField.getText().trim();
+ }
+
+ private void setPackage(String _package) {
+ packageTextField.setText(_package);
+ }
+
+ public String getSuffix() {
+ return suffixField.getText().trim();
+ }
+
+ public String getPrefix() {
+ return prefixField.getText().trim();
+ }
+
+ private void setPrefix(String prefix) {
+ prefixField.setText(prefix);
+ }
+
+ private void setSuffix(String suffix) {
+ suffixField.setText(suffix);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ warningPanel = new javax.swing.JPanel();
+ warningLabel = new javax.swing.JLabel();
+ jPanel1 = new javax.swing.JPanel();
+ suffixPanel = new javax.swing.JPanel();
+ namePane = new javax.swing.JLayeredPane();
+ prefixField = new javax.swing.JTextField();
+ entityLabel = new javax.swing.JLabel();
+ suffixField = new javax.swing.JTextField();
+ nameLabel = new javax.swing.JLabel();
+ packagePanel = new javax.swing.JPanel();
+ packageLabel = new javax.swing.JLabel();
+ packageWrapper = new javax.swing.JLayeredPane();
+ packagePrefixLabel = new javax.swing.JLabel();
+ packageTextField = new javax.swing.JTextField();
+
+ warningPanel.setLayout(new java.awt.BorderLayout(10, 0));
+
+ warningLabel.setForeground(new java.awt.Color(200, 0, 0));
+ warningLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
+ org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.warningLabel.text")); // NOI18N
+ warningPanel.add(warningLabel, java.awt.BorderLayout.CENTER);
+
+ jPanel1.setLayout(new java.awt.GridLayout(4, 0, 0, 15));
+
+ suffixPanel.setLayout(new java.awt.BorderLayout(10, 0));
+
+ namePane.setLayout(new javax.swing.BoxLayout(namePane, javax.swing.BoxLayout.LINE_AXIS));
+
+ prefixField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
+ prefixField.setText(org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.prefixField.text")); // NOI18N
+ prefixField.setToolTipText(org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.prefixField.toolTipText")); // NOI18N
+ prefixField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ prefixFieldPropertyChange(evt);
+ }
+ });
+ namePane.add(prefixField);
+
+ entityLabel.setForeground(javax.swing.UIManager.getDefaults().getColor("Button.shadow"));
+ entityLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ org.openide.awt.Mnemonics.setLocalizedText(entityLabel, org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.entityLabel.text")); // NOI18N
+ entityLabel.setPreferredSize(new java.awt.Dimension(70, 27));
+ entityLabel.setRequestFocusEnabled(false);
+ namePane.add(entityLabel);
+
+ suffixField.setText(org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.suffixField.text")); // NOI18N
+ suffixField.setToolTipText(org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.suffixField.toolTipText")); // NOI18N
+ suffixField.setPreferredSize(new java.awt.Dimension(100, 27));
+ suffixField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ suffixFieldPropertyChange(evt);
+ }
+ });
+ namePane.add(suffixField);
+
+ suffixPanel.add(namePane, java.awt.BorderLayout.CENTER);
+
+ nameLabel.setLabelFor(suffixField);
+ org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.nameLabel.text")); // NOI18N
+ nameLabel.setPreferredSize(new java.awt.Dimension(100, 17));
+ suffixPanel.add(nameLabel, java.awt.BorderLayout.WEST);
+
+ jPanel1.add(suffixPanel);
+
+ packagePanel.setLayout(new java.awt.BorderLayout(10, 0));
+
+ org.openide.awt.Mnemonics.setLocalizedText(packageLabel, org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.packageLabel.text")); // NOI18N
+ packageLabel.setPreferredSize(new java.awt.Dimension(100, 17));
+ packagePanel.add(packageLabel, java.awt.BorderLayout.LINE_START);
+
+ packageWrapper.setLayout(new java.awt.BorderLayout());
+
+ packagePrefixLabel.setForeground(new java.awt.Color(153, 153, 153));
+ org.openide.awt.Mnemonics.setLocalizedText(packagePrefixLabel, org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.packagePrefixLabel.text")); // NOI18N
+ packagePrefixLabel.setPreferredSize(new java.awt.Dimension(185, 14));
+ packageWrapper.add(packagePrefixLabel, java.awt.BorderLayout.WEST);
+
+ packageTextField.setText(org.openide.util.NbBundle.getMessage(JsfControllerPanel.class, "JsfControllerPanel.packageTextField.text")); // NOI18N
+ packageWrapper.add(packageTextField, java.awt.BorderLayout.CENTER);
+
+ packagePanel.add(packageWrapper, java.awt.BorderLayout.CENTER);
+
+ jPanel1.add(packagePanel);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 615, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(warningPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 595, Short.MAX_VALUE)
+ .addContainerGap()))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addContainerGap()))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 187, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap(156, Short.MAX_VALUE)
+ .addComponent(warningPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap()))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(50, Short.MAX_VALUE)))
+ );
+ }// //GEN-END:initComponents
+
+ private void suffixFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_suffixFieldPropertyChange
+ fire();
+ }//GEN-LAST:event_suffixFieldPropertyChange
+
+ private void prefixFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_prefixFieldPropertyChange
+ fire();
+ }//GEN-LAST:event_prefixFieldPropertyChange
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel entityLabel;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JLabel nameLabel;
+ private javax.swing.JLayeredPane namePane;
+ private javax.swing.JLabel packageLabel;
+ private javax.swing.JPanel packagePanel;
+ private javax.swing.JLabel packagePrefixLabel;
+ private javax.swing.JTextField packageTextField;
+ private javax.swing.JLayeredPane packageWrapper;
+ private javax.swing.JTextField prefixField;
+ private javax.swing.JTextField suffixField;
+ private javax.swing.JPanel suffixPanel;
+ private javax.swing.JLabel warningLabel;
+ private javax.swing.JPanel warningPanel;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/viewer/Bundle.properties b/jsf/src/main/java/io/github/jeddict/jsf/viewer/Bundle.properties
new file mode 100644
index 00000000..050751b4
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/viewer/Bundle.properties
@@ -0,0 +1,19 @@
+MSG_Progress_Now_Generating= Generating CDI repository :
+TITLE_Maven_Project_Not_Found= Maven Project
+MSG_Maven_Project_Not_Found= Maven(pom.xml) Project not found
+JsfViewerPanel.nameLabel.text=File Pattern :
+JsfViewerPanel.invalidPackage.message= The\u00a0Package\u00a0Name\u00a0is\u00a0not\u00a0valid
+JsfViewerPanel.invalidSuffix.message= The\u00a0Suffix\u00a0Name\u00a0is\u00a0not\u00a0valid
+JsfViewerPanel.reservedSuffix.message= 'Service' is reserved suffix, please choose another suffix
+JsfViewerPanel.invalidPrefix.message= The\u00a0Prefix\u00a0Name\u00a0is\u00a0not\u00a0valid
+JsfViewerPanel.invalidAppPackage.message= The\u00a0Application Package\u00a0Name\u00a0is\u00a0not\u00a0valid
+JsfViewerPanel.suffixField.toolTipText=Suffix
+JsfViewerPanel.suffixField.text=Repository
+JsfViewerPanel.entityLabel.text=
+JsfViewerPanel.prefixField.toolTipText=Prefix
+JsfViewerPanel.prefixField.text=
+JsfViewerPanel.packageLabel.text=Package :
+JsfViewerPanel.warningLabel.text=
+JsfViewerPanel.packagePrefixLabel.text= +
+JsfViewerPanel.packageTextField.text=
+
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerData.java b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerData.java
new file mode 100644
index 00000000..b80d630f
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerData.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2013-2018 the original author or authors from the Jeddict project (https://jeddict.github.io/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.github.jeddict.jsf.viewer;
+
+import io.github.jeddict.jcode.LayerConfigData;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ *
+ * @author Shiwani Gupta
+ */
+public class JsfViewerData extends LayerConfigData {
+
+ private String prefixName;
+ private String suffixName;
+ private String _package;
+ private boolean isNamed;
+ private boolean cdi = true;
+
+ /**
+ * @return the _package
+ */
+ public String getPackage() {
+ return _package;
+ }
+
+ /**
+ * @param _package the _package to set
+ */
+ public void setPackage(String _package) {
+ this._package = _package;
+ }
+
+ /**
+ * @return the suffixName
+ */
+ public String getSuffixName() {
+ if(StringUtils.isBlank(suffixName)){
+ suffixName = "Repository";
+ }
+ return suffixName;
+ }
+
+ /**
+ * @param suffixName the suffixName to set
+ */
+ public void setSuffixName(String suffixName) {
+ this.suffixName = suffixName;
+ }
+
+ /**
+ * @return the prefixName
+ */
+ public String getPrefixName() {
+ return prefixName;
+ }
+
+ /**
+ * @param prefixName the prefixName to set
+ */
+ public void setPrefixName(String prefixName) {
+ this.prefixName = prefixName;
+ }
+
+ /**
+ * @return the isNamed
+ */
+ public boolean isNamed() {
+ return isNamed;
+ }
+
+ /**
+ * @param isNamed the isNamed to set
+ */
+ public void setNamed(boolean isNamed) {
+ this.isNamed = isNamed;
+ }
+
+ /**
+ * @return the isCDI
+ */
+ public boolean isCDI() {
+ return cdi;
+ }
+
+ /**
+ * @param cdi the cdi to set
+ */
+ public void setCDI(boolean cdi) {
+ this.cdi = cdi;
+ }
+
+ @Override
+ public List getUsageDetails() {
+ return Collections.emptyList();
+ }
+}
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerGenerator.java b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerGenerator.java
new file mode 100644
index 00000000..6358448f
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerGenerator.java
@@ -0,0 +1,219 @@
+/**
+ * Copyright 2013-2018 the original author or authors from the Jeddict project (https://jeddict.github.io/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.github.jeddict.jsf.viewer;
+
+import io.github.jeddict.jcode.ApplicationConfigData;
+import io.github.jeddict.jcode.Generator;
+import io.github.jeddict.jcode.annotation.ConfigData;
+import io.github.jeddict.jcode.annotation.Technology;
+import static io.github.jeddict.jcode.annotation.Technology.Type.VIEWER;
+import io.github.jeddict.jcode.task.progress.ProgressHandler;
+import io.github.jeddict.jcode.util.BuildManager;
+import io.github.jeddict.jcode.util.FileUtil;
+import io.github.jeddict.jcode.util.ProjectHelper;
+import io.github.jeddict.jcode.util.StringHelper;
+import static io.github.jeddict.jcode.util.StringHelper.firstLower;
+import static io.github.jeddict.jcode.util.StringHelper.firstUpper;
+import io.github.jeddict.jpa.spec.Entity;
+import io.github.jeddict.jpa.spec.EntityMappings;
+import io.github.jeddict.jpa.spec.extend.Attribute;
+import io.github.jeddict.jsf.controller.JsfControllerData;
+import io.github.jeddict.jsf.controller.JsfControllerGenerator;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import static java.util.stream.Collectors.toList;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.openide.filesystems.FileObject;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ * Generates repository for entity classes.
+ *
+ * @author Shiwani Gupta
+ */
+@ServiceProvider(service = Generator.class)
+@Technology(type = VIEWER,
+ label = "JSF",
+ panel = JsfViewerPanel.class,
+ parents = JsfControllerGenerator.class
+)
+public final class JsfViewerGenerator implements Generator {
+
+ private static final String TEMPLATE = "io/github/jeddict/template/";
+ public static final String REPOSITORY_ABSTRACT = "Abstract";
+
+ @ConfigData
+ private JsfViewerData jsfViewerData;
+
+ @ConfigData
+ private JsfControllerData controllerData;
+
+ @ConfigData
+ private EntityMappings entityMapping;
+
+ @ConfigData
+ private ApplicationConfigData appConfigData;
+
+ @ConfigData
+ private ProgressHandler handler;
+
+ @ConfigData
+ private ProjectHelper projectHelper;
+
+ private Project targetProject;
+
+ private SourceGroup targetSource;
+
+ private Project gatewayProject;
+
+ private SourceGroup gatewaySource;
+ private String webXmlData = "\n"
+ + " primefaces.THEME\n"
+ + " aristo\n"
+ + " \n"
+ + " \n"
+ + " Faces Servlet\n"
+ + " javax.faces.webapp.FacesServlet\n"
+ + " 1\n"
+ + " \n"
+ + " \n"
+ + " Faces Servlet\n"
+ + " /faces/*\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " 30\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " faces/index.xhtml\n"
+ + " ";
+
+ @Override
+ public void execute() throws IOException {
+ targetProject = appConfigData.getTargetProject();
+ targetSource = appConfigData.getTargetSourceGroup();
+ gatewayProject = appConfigData.getGatewayProject();
+ gatewaySource = appConfigData.getGatewaySourceGroup();
+ addMavenDependencies("jsf/pom/_pom.xml", targetProject);
+ appConfigData.addWebDescriptorContent(webXmlData, targetProject);
+ generate();
+ generateLayout();
+ generateResources();
+ }
+
+ private void addMavenDependencies(String pom, Project project) {
+ BuildManager.getInstance(project)
+ .copy(TEMPLATE + pom)
+ .setSourceVersion("1.8")
+ .commit()
+ .reload();
+ }
+
+ private void generate() throws IOException {
+ for (Entity entity : entityMapping.getGeneratedEntity().collect(toList())) {
+ handler.progress(jsfViewerData.getPrefixName() + entity.getClazz() + jsfViewerData.getSuffixName());
+ generateCRUD(entity, true);
+ generatePropertiesFile(entity, false);
+ }
+ }
+
+ private void generatePropertiesFile(final Entity entity, boolean overrideExisting) throws IOException {
+ final FileObject resourceFolder = projectHelper.getResourceDirectory(gatewayProject);
+
+ final String entitySimpleName = entity.getClazz();
+ String entityClass = firstUpper(entitySimpleName);
+
+ List attributeList = entity.getAttributes().getAllAttribute();
+ List attributes = new ArrayList<>();
+ for (Attribute attribute : attributeList) {
+ String attributeAsString = firstUpper(attribute.getName());
+ attributes.add(attributeAsString);
+ }
+ String fileName = "Bundle";
+ Map param = new HashMap<>();
+ param.put("Entity", entityClass);
+ param.put("attributes", attributes);
+
+ handler.progress(fileName);
+ FileUtil.expandTemplate(TEMPLATE + "util/Bundle.properties.ftl", resourceFolder, fileName + '.' + "properties", param);
+ }
+
+ private void generateLayout() throws IOException {
+ FileObject targetFolder = projectHelper.getProjectWebRoot(targetProject);//getFolderForPackage(source, _package, true);
+ String xmlTargetPath = "WEB-INF/";
+ FileObject xmlTargetFolder = projectHelper.getFileObject(targetFolder, xmlTargetPath, "/");
+ String fileName = "template";
+
+ Map params = new HashMap<>();
+ handler.progress(fileName);
+
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/template.xhtml.ftl", targetFolder, fileName + '.' + "xhtml", params);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/beans.xml.ftl", xmlTargetFolder, "beans" + '.' + "xml", params);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/faces-config.xml.ftl", xmlTargetFolder, "faces-config" + '.' + "xhtml", params);
+ }
+
+ public void generateCRUD(final Entity entity, boolean overrideExisting) throws IOException {
+ String entityName = entity.getName();
+ List attributes = entity.getAttributes().getAllAttribute();
+ String entityInstance = firstLower(entityName);
+ String targetPath = "app/entities/" + entityInstance;
+
+ FileObject rootFolder = projectHelper.getProjectWebRoot(targetProject);//getFolderForPackage(source, _package, true);
+ FileObject targetFolder = projectHelper.getFileObject(rootFolder, targetPath, "/");
+
+ String createFileName = "create" + entityName;
+ String viewFileName = "view" + entityName;
+ String editFileName = "edit" + entityName;
+ String listFileName = "list" + entityName;
+ String indexFilename = "index";
+ String controllerName = firstLower(controllerData.getPrefixName() + entityName + controllerData.getSuffixName());
+
+ Map params = new HashMap<>();
+ params.put("EntityController", controllerName);
+ params.put("Entity", entityName);
+ params.put("hash", "#");
+ params.put("attributes", attributes);
+ params.put("entityInstance", entityInstance);
+ handler.progress(createFileName);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/create.xhtml.ftl", targetFolder, createFileName + '.' + "xhtml", params);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/view.xhtml.ftl", targetFolder, viewFileName + '.' + "xhtml", params);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/edit.xhtml.ftl", targetFolder, editFileName + '.' + "xhtml", params);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/list.xhtml.ftl", targetFolder, listFileName + '.' + "xhtml", params);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/index.xhtml.ftl", rootFolder, indexFilename + '.' + "xhtml", params);
+
+ }
+
+ public void generateResources() throws IOException {
+ FileObject targetFolder = projectHelper.getProjectWebRoot(targetProject);//getFolderForPackage(source, _package, true);
+ String xmlTargetPath = "resources/";
+ FileObject cssTargetFolder = projectHelper.getFileObject(targetFolder, xmlTargetPath + "css/", "/");
+ FileObject jsTargetFolder = projectHelper.getFileObject(targetFolder, xmlTargetPath + "js/", "/");
+ FileObject imagesTargetFolder = projectHelper.getFileObject(targetFolder, xmlTargetPath + "images/", "/");
+
+ String fileName = "jsfcrud";
+ Map params = new HashMap<>();
+ handler.progress(fileName);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/jsfcrud.css.ftl", cssTargetFolder, fileName + '.' + "css", params);
+ io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/jsfcrud.js.ftl", jsTargetFolder, fileName + '.' + "js", params);
+// io.github.jeddict.jcode.util.FileUtil.expandTemplate(TEMPLATE + "jsf/images.js.ftl", jsTargetFolder, fileName + '.' + "js", params);
+
+ }
+}
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerPanel.form b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerPanel.form
new file mode 100644
index 00000000..a8b45301
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerPanel.form
@@ -0,0 +1,228 @@
+
+
+
diff --git a/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerPanel.java b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerPanel.java
new file mode 100644
index 00000000..ba93e27a
--- /dev/null
+++ b/jsf/src/main/java/io/github/jeddict/jsf/viewer/JsfViewerPanel.java
@@ -0,0 +1,260 @@
+/**
+ * Copyright 2013-2018 the original author or authors from the Jeddict project (https://jeddict.github.io/).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.github.jeddict.jsf.viewer;
+
+import io.github.jeddict.jcode.LayerConfigPanel;
+import javax.lang.model.SourceVersion;
+import org.apache.commons.lang.StringUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import static io.github.jeddict.jcode.util.JavaIdentifiers.isValidPackageName;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author Shiwani Gupta
+ */
+public class JsfViewerPanel extends LayerConfigPanel {
+
+ private static final String DEFAULT_PACKAGE = "repository";
+
+ public JsfViewerPanel() {
+ initComponents();
+ }
+
+ @Override
+ public boolean hasError() {
+ warningLabel.setText("");
+ if (!isValidPackageName(getPackage())) {
+ warningLabel.setText(NbBundle.getMessage(JsfViewerPanel.class, "RepositoryPanel.invalidPackage.message"));
+ return true;
+ }
+ String prefix = getPrefix();
+ String suffix = getSuffix();
+
+ if (StringUtils.isNotBlank(prefix) && !SourceVersion.isName(prefix)) {
+ warningLabel.setText(NbBundle.getMessage(JsfViewerPanel.class, "RepositoryPanel.invalidPrefix.message"));
+ return true;
+ }
+ if (StringUtils.isNotBlank(suffix) && !SourceVersion.isName(prefix + '_' + suffix)) {
+ warningLabel.setText(NbBundle.getMessage(JsfViewerPanel.class, "RepositoryPanel.invalidSuffix.message"));
+ return true;
+ }
+ if ("Service".equals(suffix)) {
+ warningLabel.setText(NbBundle.getMessage(JsfViewerPanel.class, "RepositoryPanel.reservedSuffix.message"));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void read() {
+ JsfViewerData data = this.getConfigData();
+ if (StringUtils.isNotBlank(data.getPackage())) {
+ setPackage(data.getPackage());
+ }
+ if (StringUtils.isNotBlank(data.getPrefixName())) {
+ setPrefix(data.getPrefixName());
+ }
+ if (StringUtils.isNotBlank(data.getSuffixName())) {
+ setSuffix(data.getSuffixName());
+ }
+ }
+
+ @Override
+ public void store() {
+ JsfViewerData data = this.getConfigData();
+ data.setPrefixName(getPrefix());
+ data.setSuffixName(getSuffix());
+ data.setPackage(getPackage());
+ }
+
+ @Override
+ public void init(String _package, Project project, SourceGroup sourceGroup) {
+ setPackage(DEFAULT_PACKAGE);
+ addChangeListener(prefixField);
+ addChangeListener(suffixField);
+ }
+
+ public String getPackage() {
+ return packageTextField.getText().trim();
+ }
+
+ private void setPackage(String _package) {
+ packageTextField.setText(_package);
+ }
+
+ public String getSuffix() {
+ return suffixField.getText().trim();
+ }
+
+ public String getPrefix() {
+ return prefixField.getText().trim();
+ }
+
+ private void setPrefix(String prefix) {
+ prefixField.setText(prefix);
+ }
+
+ private void setSuffix(String suffix) {
+ suffixField.setText(suffix);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ warningPanel = new javax.swing.JPanel();
+ warningLabel = new javax.swing.JLabel();
+ jPanel1 = new javax.swing.JPanel();
+ suffixPanel = new javax.swing.JPanel();
+ namePane = new javax.swing.JLayeredPane();
+ prefixField = new javax.swing.JTextField();
+ entityLabel = new javax.swing.JLabel();
+ suffixField = new javax.swing.JTextField();
+ nameLabel = new javax.swing.JLabel();
+ packagePanel = new javax.swing.JPanel();
+ packageLabel = new javax.swing.JLabel();
+ packageWrapper = new javax.swing.JLayeredPane();
+ packagePrefixLabel = new javax.swing.JLabel();
+ packageTextField = new javax.swing.JTextField();
+
+ warningPanel.setLayout(new java.awt.BorderLayout(10, 0));
+
+ warningLabel.setForeground(new java.awt.Color(200, 0, 0));
+ warningLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
+ org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.warningLabel.text")); // NOI18N
+ warningPanel.add(warningLabel, java.awt.BorderLayout.CENTER);
+
+ jPanel1.setLayout(new java.awt.GridLayout(4, 0, 0, 15));
+
+ suffixPanel.setLayout(new java.awt.BorderLayout(10, 0));
+
+ namePane.setLayout(new javax.swing.BoxLayout(namePane, javax.swing.BoxLayout.LINE_AXIS));
+
+ prefixField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
+ prefixField.setText(org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.prefixField.text")); // NOI18N
+ prefixField.setToolTipText(org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.prefixField.toolTipText")); // NOI18N
+ prefixField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ prefixFieldPropertyChange(evt);
+ }
+ });
+ namePane.add(prefixField);
+
+ entityLabel.setForeground(javax.swing.UIManager.getDefaults().getColor("Button.shadow"));
+ entityLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ org.openide.awt.Mnemonics.setLocalizedText(entityLabel, org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.entityLabel.text")); // NOI18N
+ entityLabel.setPreferredSize(new java.awt.Dimension(70, 27));
+ entityLabel.setRequestFocusEnabled(false);
+ namePane.add(entityLabel);
+
+ suffixField.setText(org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.suffixField.text")); // NOI18N
+ suffixField.setToolTipText(org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.suffixField.toolTipText")); // NOI18N
+ suffixField.setPreferredSize(new java.awt.Dimension(100, 27));
+ suffixField.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ suffixFieldPropertyChange(evt);
+ }
+ });
+ namePane.add(suffixField);
+
+ suffixPanel.add(namePane, java.awt.BorderLayout.CENTER);
+
+ nameLabel.setLabelFor(suffixField);
+ org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.nameLabel.text")); // NOI18N
+ nameLabel.setPreferredSize(new java.awt.Dimension(100, 17));
+ suffixPanel.add(nameLabel, java.awt.BorderLayout.WEST);
+
+ jPanel1.add(suffixPanel);
+
+ packagePanel.setLayout(new java.awt.BorderLayout(10, 0));
+
+ org.openide.awt.Mnemonics.setLocalizedText(packageLabel, org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.packageLabel.text")); // NOI18N
+ packageLabel.setPreferredSize(new java.awt.Dimension(100, 17));
+ packagePanel.add(packageLabel, java.awt.BorderLayout.LINE_START);
+
+ packageWrapper.setLayout(new java.awt.BorderLayout());
+
+ packagePrefixLabel.setForeground(new java.awt.Color(153, 153, 153));
+ org.openide.awt.Mnemonics.setLocalizedText(packagePrefixLabel, org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.packagePrefixLabel.text")); // NOI18N
+ packagePrefixLabel.setPreferredSize(new java.awt.Dimension(185, 14));
+ packageWrapper.add(packagePrefixLabel, java.awt.BorderLayout.WEST);
+
+ packageTextField.setText(org.openide.util.NbBundle.getMessage(JsfViewerPanel.class, "JsfViewerPanel.packageTextField.text")); // NOI18N
+ packageWrapper.add(packageTextField, java.awt.BorderLayout.CENTER);
+
+ packagePanel.add(packageWrapper, java.awt.BorderLayout.CENTER);
+
+ jPanel1.add(packagePanel);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(warningPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 595, Short.MAX_VALUE)
+ .addContainerGap()))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(50, Short.MAX_VALUE))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap(156, Short.MAX_VALUE)
+ .addComponent(warningPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap()))
+ );
+ }// //GEN-END:initComponents
+
+ private void suffixFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_suffixFieldPropertyChange
+ fire();
+ }//GEN-LAST:event_suffixFieldPropertyChange
+
+ private void prefixFieldPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_prefixFieldPropertyChange
+ fire();
+ }//GEN-LAST:event_prefixFieldPropertyChange
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel entityLabel;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JLabel nameLabel;
+ private javax.swing.JLayeredPane namePane;
+ private javax.swing.JLabel packageLabel;
+ private javax.swing.JPanel packagePanel;
+ private javax.swing.JLabel packagePrefixLabel;
+ private javax.swing.JTextField packageTextField;
+ private javax.swing.JLayeredPane packageWrapper;
+ private javax.swing.JTextField prefixField;
+ private javax.swing.JTextField suffixField;
+ private javax.swing.JPanel suffixPanel;
+ private javax.swing.JLabel warningLabel;
+ private javax.swing.JPanel warningPanel;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/jsf/src/main/nbm/manifest.mf b/jsf/src/main/nbm/manifest.mf
new file mode 100644
index 00000000..a81d0d5e
--- /dev/null
+++ b/jsf/src/main/nbm/manifest.mf
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+OpenIDE-Module-Display-Category: Jeddict
+OpenIDE-Module: io.github.jeddict.jsf
+OpenIDE-Module-Short-Description: JSF Generator
\ No newline at end of file
diff --git a/jsf/src/main/resources/io/github/jeddict/template/controller/EntityController.java.ftl b/jsf/src/main/resources/io/github/jeddict/template/controller/EntityController.java.ftl
new file mode 100644
index 00000000..39a60ef7
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/controller/EntityController.java.ftl
@@ -0,0 +1,234 @@
+package ${package};
+
+import java.io.Serializable;
+import java.util.ResourceBundle;
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.FacesConverter;
+import javax.faces.model.DataModel;
+import javax.faces.model.ListDataModel;
+import javax.faces.model.SelectItem;
+import javax.inject.Inject;
+import ${EntityClass_FQN};
+import ${RepositoryClass_FQN};
+import ${JsfUtil_FQN};
+import ${PaginationHelper_FQN};
+
+@Named("${entityInstance}Controller")
+@RequestScoped
+public class ${EntityController} implements Serializable{
+
+ private ${Entity} ${entityInstance};
+ private DataModel items = null;
+ @Inject
+ private ${EntityRepository} ${RepositoryInstance};
+ private int selectedItemIndex;
+ private PaginationHelper pagination;
+
+
+
+ public ${Entity} getSelected() {
+ if (${entityInstance} == null) {
+ ${entityInstance} = new ${Entity}();
+ selectedItemIndex = -1;
+ }
+ return ${entityInstance};
+ }
+ public void setSelected(${Entity} selected) {
+ this.${entityInstance} = selected;
+ }
+
+ private ${EntityRepository} getRepository() {
+ return ${RepositoryInstance};
+ }
+
+ public PaginationHelper getPagination() {
+ if (pagination == null) {
+ pagination = new PaginationHelper(10) {
+
+ @Override
+ public int getItemsCount() {
+ return getRepository().count();
+ }
+
+ @Override
+ public DataModel createPageDataModel() {
+ return new ListDataModel(getRepository().findRange(getPageFirstItem(), getPageFirstItem() + getPageSize()));
+ }
+ };
+ }
+ return pagination;
+ }
+
+ public String prepareList() {
+ recreateModel();
+ return "list${Entity}";
+ }
+
+ public String prepareView() {
+ ${entityInstance} = (${Entity}) getItems().getRowData();
+ selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
+ return "view${Entity}";
+ }
+
+ public String prepareCreate() {
+ ${entityInstance} = new ${Entity}();
+ selectedItemIndex = -1;
+ return "create${Entity}";
+ }
+
+ public String create() {
+ try {
+ getRepository().create(${entityInstance});
+ JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("${Entity}Created"));
+ return prepareList();
+ } catch (Exception e) {
+ JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
+ return null;
+ }
+ }
+
+ public String prepareEdit() {
+ ${entityInstance} = (${Entity}) getItems().getRowData();
+ selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
+ return "edit${Entity}";
+ }
+
+ public String update() {
+ try {
+ getRepository().edit(${entityInstance});
+ JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("${Entity}Updated"));
+ return "list${Entity}";
+ } catch (Exception e) {
+ JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
+ return null;
+ }
+ }
+
+ public String destroy() {
+ ${entityInstance} = (${Entity}) getItems().getRowData();
+ selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
+ performDestroy();
+ recreatePagination();
+ recreateModel();
+ return prepareList();
+ }
+
+ public String destroyAndView() {
+ performDestroy();
+ recreateModel();
+ if (selectedItemIndex >= 0) {
+ return "list${Entity}";
+ } else {
+ recreateModel();
+ return "list${Entity}";
+ }
+ }
+
+ private void performDestroy() {
+ try {
+ getRepository().remove(${entityInstance});
+ JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("${Entity}Deleted"));
+ } catch (Exception e) {
+ JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
+ }
+ }
+
+ private void updateCurrentItem() {
+ int count = getRepository().count();
+ if (selectedItemIndex >= count) {
+ // selected index cannot be bigger than number of items:
+ selectedItemIndex = count - 1;
+ // go to previous page if last page disappeared:
+ if (pagination.getPageFirstItem() >= count) {
+ pagination.previousPage();
+ }
+ }
+ if (selectedItemIndex >= 0) {
+ ${entityInstance} = getRepository().findRange(selectedItemIndex, selectedItemIndex + 1).get(0);
+ }
+ }
+
+ public DataModel getItems() {
+ if (items == null) {
+ items = getPagination().createPageDataModel();
+ }
+ return items;
+ }
+
+ private void recreateModel() {
+ items = null;
+ }
+
+ private void recreatePagination() {
+ pagination = null;
+ }
+
+ public String next() {
+ getPagination().nextPage();
+ recreateModel();
+ return "list${Entity}";
+ }
+
+ public String previous() {
+ getPagination().previousPage();
+ recreateModel();
+ return "list${Entity}";
+ }
+
+ public SelectItem[] getItemsAvailableSelectMany() {
+ return JsfUtil.getSelectItems(${RepositoryInstance}.findAll(), false);
+ }
+
+ public SelectItem[] getItemsAvailableSelectOne() {
+ return JsfUtil.getSelectItems(${RepositoryInstance}.findAll(), true);
+ }
+
+ public ${Entity} get${Entity}(long id) {
+ return ${RepositoryInstance}.find(id);
+ }
+
+ @FacesConverter(forClass = ${Entity}.class)
+ public static class ${EntityController}Converter implements Converter {
+
+ @Override
+ public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
+ if (value == null || value.length() == 0) {
+ return null;
+ }
+ ${EntityController} controller = (${EntityController}) facesContext.getApplication().getELResolver().
+ getValue(facesContext.getELContext(), null, "${EntityController}");
+ return controller.get${Entity}(getKey(value));
+ }
+
+ long getKey(String value) {
+ long key;
+ key = Long.parseLong(value);
+ return key;
+ }
+
+ String getStringKey(long value) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(value);
+ return sb.toString();
+ }
+
+ @Override
+ public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
+ if (object == null) {
+ return null;
+ }
+ if (object instanceof ${Entity}) {
+ ${Entity} o = (${Entity}) object;
+ return getStringKey(o.getId());
+ } else {
+ throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + ${Entity}.class.getName());
+ }
+ }
+
+ }
+
+}
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/beans.xml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/beans.xml.ftl
new file mode 100644
index 00000000..2777559c
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/beans.xml.ftl
@@ -0,0 +1,6 @@
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/create.xhtml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/create.xhtml.ftl
new file mode 100644
index 00000000..b95e7eb8
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/create.xhtml.ftl
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Create ${Entity}
+
+
+
+ <#list attributes as attribute>
+ <#if attribute.attributeType == "String">
+
+
+
+
+ <#elseif attribute.attributeType == "long" >
+
+
+
+
+ <#elseif attribute.attributeType == "int" >
+
+
+
+
+ <#elseif attribute.attributeType == "boolean" >
+
+
+
+
+
+
+
+ #if>
+ #list>
+
+
+
+
+
+
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/edit.xhtml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/edit.xhtml.ftl
new file mode 100644
index 00000000..f26227a8
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/edit.xhtml.ftl
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Edit ${Entity}
+
+
+
+ <#list attributes as attribute>
+ <#if attribute.attributeType == "String">
+
+
+
+
+ <#elseif attribute.attributeType == "long" >
+
+
+
+
+ <#elseif attribute.attributeType == "int" >
+
+
+
+
+ <#elseif attribute.attributeType == "boolean" >
+
+
+
+
+
+
+
+ #if>
+ #list>
+
+
+
+
+
+
+
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/faces-config.xml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/faces-config.xml.ftl
new file mode 100644
index 00000000..b6b84e60
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/faces-config.xml.ftl
@@ -0,0 +1,12 @@
+
+
+
+
+ /Bundle
+ bundle
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/index.xhtml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/index.xhtml.ftl
new file mode 100644
index 00000000..c4f7cab1
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/index.xhtml.ftl
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ Facelet Title
+
+
+
+
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/jsfcrud.css.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/jsfcrud.css.ftl
new file mode 100644
index 00000000..bf0aa87c
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/jsfcrud.css.ftl
@@ -0,0 +1,17 @@
+.ui-widget {
+ font-size: 12px !important;
+}
+.ui-layout-north {
+ z-index: 20 !important;
+ overflow: visible !important;;
+}
+.ui-layout-north .ui-layout-unit-content {
+ overflow: visible !important;
+}
+.ui-widget-header {
+ text-align: center;
+ text-transform: uppercase;
+}
+.ui-button {
+ margin-top: 10px !important;
+}
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/jsfcrud.js.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/jsfcrud.js.ftl
new file mode 100644
index 00000000..fb1c8c63
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/jsfcrud.js.ftl
@@ -0,0 +1,8 @@
+function handleSubmit(args, dialog) {
+ var jqDialog = jQuery('#' + dialog);
+ if (args.validationFailed) {
+ jqDialog.effect('shake', {times: 3}, 100);
+ } else {
+ PF(dialog).hide();
+ }
+}
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/list.xhtml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/list.xhtml.ftl
new file mode 100644
index 00000000..1550f9db
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/list.xhtml.ftl
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
${Entity} Registration
+
+
+
+
+
+ <#list attributes as attribute>
+
+
+
+
+
+
+ #list>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/pom/_pom.xml b/jsf/src/main/resources/io/github/jeddict/template/jsf/pom/_pom.xml
new file mode 100644
index 00000000..2f9d9f25
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/pom/_pom.xml
@@ -0,0 +1,145 @@
+
+
+ 4.0.0
+
+ io.github.jeddict
+ app_pom
+ 1.0-SNAPSHOT
+ jar
+ app_pom
+
+
+ 8.0
+ 3.7.0
+ ${project.build.directory}/endorsed
+
+
+
+
+
+ commons-beanutils
+ commons-beanutils
+ 1.9.2
+
+
+ org.apache.commons
+ commons-lang3
+ 3.8.1
+
+
+
+ org.primefaces
+ primefaces
+ jar
+ 6.2
+
+
+ org.primefaces.themes
+ aristo
+ 1.0.1
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.core
+ provided
+ 2.5.2
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.asm
+ provided
+ 2.5.2
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.antlr
+ provided
+ 2.5.2
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.jpa
+ provided
+ 2.5.2
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.jpa.jpql
+ 2.5.2
+ provided
+
+
+ org.eclipse.persistence
+ javax.persistence
+ provided
+ 2.1.0
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.jpa.modelgen.processor
+ provided
+ 2.5.2
+
+
+
+
+
+
+ prime-repo
+ PrimeFaces Maven Repository
+ https://repository.primefaces.org
+
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/template.xhtml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/template.xhtml.ftl
new file mode 100644
index 00000000..bdd1171f
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/template.xhtml.ftl
@@ -0,0 +1,41 @@
+
+
+
+
+
+ Default Title
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/jsf/view.xhtml.ftl b/jsf/src/main/resources/io/github/jeddict/template/jsf/view.xhtml.ftl
new file mode 100644
index 00000000..61517b7b
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/jsf/view.xhtml.ftl
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
View ${Entity}
+
+
+
+
+ <#list attributes as attribute>
+
+
+ #list>
+
+
+
+
+
+
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/repository/AbstractRepository.java.ftl b/jsf/src/main/resources/io/github/jeddict/template/repository/AbstractRepository.java.ftl
new file mode 100644
index 00000000..eecc6417
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/repository/AbstractRepository.java.ftl
@@ -0,0 +1,138 @@
+package ${package};
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+<#if cdi>import javax.transaction.Transactional;
+import static javax.transaction.Transactional.TxType.REQUIRED;
+import static javax.transaction.Transactional.TxType.SUPPORTS;#if>
+
+<#if cdi>@Transactional(SUPPORTS)#if>
+public abstract class ${AbstractRepository} {
+
+ private final Class entityClass;
+
+ public ${AbstractRepository}(Class entityClass) {
+ this.entityClass = entityClass;
+ }
+
+ protected abstract EntityManager getEntityManager();
+
+ <#if cdi>@Transactional(REQUIRED)#if>
+ public void create(E entity) {
+ getEntityManager().persist(entity);
+ }
+
+ <#if cdi>@Transactional(REQUIRED)#if>
+ public E edit(E entity) {
+ return getEntityManager().merge(entity);
+ }
+
+ <#if cdi>@Transactional(REQUIRED)#if>
+ public void remove(E entity) {
+ getEntityManager().remove(getEntityManager().merge(entity));
+ }
+
+ public P getIdentifier(E entity) {
+ return (P)getEntityManager().getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(entity);
+ }
+
+ public E find(P id) {
+ return getEntityManager().find(entityClass, id);
+ }
+
+ public List findAll() {
+ CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
+ cq.select(cq.from(entityClass));
+ return getEntityManager().createQuery(cq).getResultList();
+ }
+
+ public List findRange(int startPosition, int size) {
+ return findRange(startPosition, size, null);
+ }
+
+ public List findRange(int startPosition, int size, String entityGraph) {
+ CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
+ cq.select(cq.from(entityClass));
+ Query q = getEntityManager().createQuery(cq);
+ q.setMaxResults(size);
+ q.setFirstResult(startPosition);
+ if (entityGraph != null) {
+ q.setHint("javax.persistence.loadgraph", getEntityManager().getEntityGraph(entityGraph));
+ }
+ return q.getResultList();
+ }
+
+ public int count() {
+ CriteriaQuery criteriaQuery = getEntityManager().getCriteriaBuilder().createQuery();
+ Root root = criteriaQuery.from(entityClass);
+ criteriaQuery.select(getEntityManager().getCriteriaBuilder().count(root));
+ Query query = getEntityManager().createQuery(criteriaQuery);
+ return ((Long) query.getSingleResult()).intValue();
+ }
+
+ public Optional findSingleByNamedQuery(String namedQueryName) {
+ return findOrEmpty(() -> getEntityManager().createNamedQuery(namedQueryName, entityClass).getSingleResult());
+ }
+
+ public Optional findSingleByNamedQuery(String namedQueryName, Map parameters) {
+ return findSingleByNamedQuery(namedQueryName, null, parameters);
+ }
+
+ public Optional findSingleByNamedQuery(String namedQueryName, String entityGraph, Map parameters) {
+ Set> rawParameters = parameters.entrySet();
+ TypedQuery query = getEntityManager().createNamedQuery(namedQueryName, entityClass);
+ rawParameters.forEach(entry -> query.setParameter(entry.getKey(), entry.getValue()));
+ if(entityGraph != null){
+ query.setHint("javax.persistence.loadgraph", getEntityManager().getEntityGraph(entityGraph));
+ }
+ return findOrEmpty(query::getSingleResult);
+ }
+
+ public List findByNamedQuery(String namedQueryName) {
+ return findByNamedQuery(namedQueryName, -1);
+ }
+
+ public List findByNamedQuery(String namedQueryName, Map parameters) {
+ return findByNamedQuery(namedQueryName, parameters, -1);
+ }
+
+ public List findByNamedQuery(String namedQueryName, int resultLimit) {
+ return findByNamedQuery(namedQueryName, Collections.EMPTY_MAP, resultLimit);
+ }
+
+ public List findByNamedQuery(String namedQueryName, Map parameters, int resultLimit) {
+ Set> rawParameters = parameters.entrySet();
+ Query query = getEntityManager().createNamedQuery(namedQueryName);
+ if (resultLimit > 0) {
+ query.setMaxResults(resultLimit);
+ }
+ rawParameters.forEach(entry -> query.setParameter(entry.getKey(), entry.getValue()));
+ return query.getResultList();
+ }
+
+ public static Optional findOrEmpty(final DaoRetriever retriever) {
+ try {
+ return Optional.of(retriever.retrieve());
+ } catch (NoResultException ex) {
+ //log
+ }
+ return Optional.empty();
+ }
+
+ @FunctionalInterface
+ public interface DaoRetriever {
+
+ E retrieve() throws NoResultException;
+ }
+
+}
diff --git a/jsf/src/main/resources/io/github/jeddict/template/repository/EntityRepository.java.ftl b/jsf/src/main/resources/io/github/jeddict/template/repository/EntityRepository.java.ftl
new file mode 100644
index 00000000..936b6026
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/repository/EntityRepository.java.ftl
@@ -0,0 +1,27 @@
+package ${package};
+
+<#if !cdi>import javax.ejb.Stateless;#if>
+<#if named>import javax.inject.Named;#if>
+import javax.persistence.EntityManager;
+import javax.inject.Inject;
+import ${EntityClass_FQN};
+<#if AbstractRepository_FQN!="">import ${appPackage}${AbstractRepository_FQN};#if>
+<#if EntityPKClass_FQN!="">import ${EntityPKClass_FQN};#if>
+
+<#if !cdi>@Stateless#if>
+<#if named>@Named("${entityInstance}")#if>
+public class ${EntityRepository} extends ${AbstractRepository}<${EntityClass}, ${EntityPKClass}> {
+
+ @Inject
+ private EntityManager em;
+
+ @Override
+ protected EntityManager getEntityManager() {
+ return em;
+ }
+
+ public ${EntityRepository}() {
+ super(${EntityClass}.class);
+ }
+
+}
diff --git a/jsf/src/main/resources/io/github/jeddict/template/service/producer/EntityManagerProducer.java.ftl b/jsf/src/main/resources/io/github/jeddict/template/service/producer/EntityManagerProducer.java.ftl
new file mode 100644
index 00000000..13e0dd5f
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/service/producer/EntityManagerProducer.java.ftl
@@ -0,0 +1,23 @@
+<#if package??>package ${package};#if>
+
+import javax.enterprise.inject.Produces;
+import javax.enterprise.context.RequestScoped;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+/**
+ * Producer for injectable EntityManager
+ *
+ */
+@RequestScoped
+public class EntityManagerProducer {
+
+ @PersistenceContext(unitName = "${PU}")
+ private EntityManager em;
+
+ @Produces
+ public EntityManager getEntityManager(){
+ return em;
+ }
+
+}
\ No newline at end of file
diff --git a/jsf/src/main/resources/io/github/jeddict/template/util/Bundle.properties.ftl b/jsf/src/main/resources/io/github/jeddict/template/util/Bundle.properties.ftl
new file mode 100644
index 00000000..c2dd3f42
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/util/Bundle.properties.ftl
@@ -0,0 +1,46 @@
+PersistenceErrorOccured=A persistence error occurred.
+Create=Create
+View=View
+Edit=Edit
+Delete=Delete
+Close=Close
+Cancel=Cancel
+Save=Save
+SelectOneMessage=Select One...
+Home=Home
+Maintenance=Maintenance
+
+
+AppName=${Entity} Registration Demo
+${Entity}Created=${Entity} was successfully created.
+${Entity}Updated=${Entity} was successfully updated.
+${Entity}Deleted=${Entity} was successfully deleted.
+
+Create${Entity}Title=Create New ${Entity}
+Create${Entity}SaveLink=Save
+Create${Entity}ShowAllLink=Show All ${Entity} Items
+Create${Entity}IndexLink=Index
+
+
+Edit${Entity}Title=Edit ${Entity}
+Edit${Entity}SaveLink=Save
+Edit${Entity}ViewLink=View
+Edit${Entity}ShowAllLink=Show All ${Entity} Items
+Edit${Entity}IndexLink=Index
+
+
+View${Entity}Title=View ${Entity}
+View${Entity}DestroyLink=Destroy
+View${Entity}EditLink=Edit
+View${Entity}CreateLink=Create New ${Entity}
+View${Entity}ShowAllLink=Show All ${Entity} Items
+View${Entity}IndexLink=Index
+
+List${Entity}Title=List
+List${Entity}Empty=(No ${Entity} Items Found)
+List${Entity}DestroyLink=Destroy
+List${Entity}EditLink=Edit
+List${Entity}ViewLink=View
+List${Entity}CreateLink=Create New ${Entity}
+List${Entity}IndexLink=Index
+
diff --git a/jsf/src/main/resources/io/github/jeddict/template/util/JsfUtil.java.ftl b/jsf/src/main/resources/io/github/jeddict/template/util/JsfUtil.java.ftl
new file mode 100644
index 00000000..3169bbd9
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/util/JsfUtil.java.ftl
@@ -0,0 +1,73 @@
+package ${package};
+
+import java.util.List;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.model.SelectItem;
+
+/**
+ * Producer for injectable JsfUtil
+ *
+ */
+public class JsfUtil {
+
+ public static SelectItem[] getSelectItems(List> entities, boolean selectOne) {
+ int size = selectOne ? entities.size() + 1 : entities.size();
+ SelectItem[] items = new SelectItem[size];
+ int i = 0;
+ if (selectOne) {
+ items[0] = new SelectItem("", "---");
+ i++;
+ }
+ for (Object x : entities) {
+ items[i++] = new SelectItem(x, x.toString());
+ }
+ return items;
+ }
+
+ public static boolean isValidationFailed() {
+ return FacesContext.getCurrentInstance().isValidationFailed();
+ }
+
+ public static void addErrorMessage(Exception ex, String defaultMsg) {
+ String msg = ex.getLocalizedMessage();
+ if (msg != null && msg.length() > 0) {
+ addErrorMessage(msg);
+ } else {
+ addErrorMessage(defaultMsg);
+ }
+ }
+
+ public static void addErrorMessages(List messages) {
+ for (String message : messages) {
+ addErrorMessage(message);
+ }
+ }
+
+ public static void addErrorMessage(String msg) {
+ FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
+ FacesContext.getCurrentInstance().addMessage(null, facesMsg);
+ }
+
+ public static void addSuccessMessage(String msg) {
+ FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
+ FacesContext.getCurrentInstance().addMessage("successInfo", facesMsg);
+ }
+
+ public static String getRequestParameter(String key) {
+ return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);
+ }
+
+ public static Object getObjectFromRequestParameter(String requestParameterName, Converter converter, UIComponent component) {
+ String theId = JsfUtil.getRequestParameter(requestParameterName);
+ return converter.getAsObject(FacesContext.getCurrentInstance(), component, theId);
+ }
+
+ public static enum PersistAction {
+ CREATE,
+ DELETE,
+ UPDATE
+ }
+}
\ No newline at end of file
diff --git a/jsf/src/main/resources/io/github/jeddict/template/util/PaginationHelper.java.ftl b/jsf/src/main/resources/io/github/jeddict/template/util/PaginationHelper.java.ftl
new file mode 100644
index 00000000..a134817b
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/util/PaginationHelper.java.ftl
@@ -0,0 +1,62 @@
+package ${package};
+
+import javax.faces.model.DataModel;
+
+/**
+ * Producer for injectable Pagination Util
+ *
+ */
+public abstract class PaginationHelper {
+
+ private int pageSize;
+ private int page;
+
+ public PaginationHelper(int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public abstract int getItemsCount();
+
+ public abstract DataModel createPageDataModel();
+
+ public int getPageFirstItem() {
+ return page * pageSize;
+ }
+
+ public int getPageLastItem() {
+ int i = getPageFirstItem() + pageSize - 1;
+ int count = getItemsCount() - 1;
+ if (i > count) {
+ i = count;
+ }
+ if (i < 0) {
+ i = 0;
+ }
+ return i;
+ }
+
+ public boolean isHasNextPage() {
+ return (page + 1) * pageSize + 1 <= getItemsCount();
+ }
+
+ public void nextPage() {
+ if (isHasNextPage()) {
+ page++;
+ }
+ }
+
+ public boolean isHasPreviousPage() {
+ return page > 0;
+ }
+
+ public void previousPage() {
+ if (isHasPreviousPage()) {
+ page--;
+ }
+ }
+
+ public int getPageSize() {
+ return pageSize;
+ }
+
+}
\ No newline at end of file
diff --git a/jsf/src/main/resources/io/github/jeddict/template/web/descriptor/_web.xml.ftl b/jsf/src/main/resources/io/github/jeddict/template/web/descriptor/_web.xml.ftl
new file mode 100644
index 00000000..c83d8e62
--- /dev/null
+++ b/jsf/src/main/resources/io/github/jeddict/template/web/descriptor/_web.xml.ftl
@@ -0,0 +1,6 @@
+
+${content}
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 49ffdd6e..528f1452 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,6 +12,7 @@
runtime
infra
jakarta-ee
+ jsf
${basedir}