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

doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/master by this push:
     new 1d6952d1 EMPIREDB-404 New FormGridTag to customize ControlTag rendering
1d6952d1 is described below

commit 1d6952d1bef6f640f344dae6b0f78c8528ee987a
Author: Rainer Döbele <[email protected]>
AuthorDate: Sun Mar 19 15:47:08 2023 +0100

    EMPIREDB-404
    New FormGridTag to customize ControlTag rendering
---
 .../jsf2/websample/web/SampleApplication.java      |  15 +-
 .../jsf2/websample/web/pages/EmployeeListPage.java |   7 +-
 .../src/main/webapp/META-INF/context.xml           |   5 +-
 .../src/main/webapp/WEB-INF/config.xml             |   6 +-
 .../src/main/webapp/WEB-INF/faces-config.xml       |   4 +
 .../src/main/webapp/pages/employeeDetailPage.xhtml |  76 +++++-----
 .../src/main/webapp/resources/empire/control.xhtml |  18 ++-
 .../empire/{input.xhtml => formGrid.xhtml}         |  73 +++++-----
 .../src/main/webapp/resources/empire/input.xhtml   |   7 +
 .../apache/empire/jsf2/components/ControlTag.java  | 107 ++++++++++----
 .../apache/empire/jsf2/components/FormGridTag.java | 156 +++++++++++++++++++++
 .../empire/jsf2/utils/ControlRenderInfo.java       |  49 +++++++
 .../empire/jsf2/utils/TagEncodingHelper.java       |  30 ++++
 13 files changed, 432 insertions(+), 121 deletions(-)

diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleApplication.java
 
b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleApplication.java
index 00c4add6..3e55bf5d 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleApplication.java
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/SampleApplication.java
@@ -68,9 +68,6 @@ public class SampleApplication extends WebApplication {
                
                // trace
                SampleApplication.log.trace("SampleApplication created");
-
-               // register custom control types
-               InputControlManager.registerControl(new FileInputControl());
        }
 
        @Override
@@ -86,6 +83,9 @@ public class SampleApplication extends WebApplication {
 
                log.info("*** initDatabase() ***");
                initDatabase();
+               
+        log.info("*** initControls() ***");
+               initControls();
 
                log.info("*** initPages() ***");
                initPages(servletContext);
@@ -95,6 +95,15 @@ public class SampleApplication extends WebApplication {
 
                // Done
        }
+       
+    /**
+     * initializes JSF control components
+     */
+    private void initControls()
+    {
+        // register custom control types
+        InputControlManager.registerControl(new FileInputControl());
+       }
 
     /*
      * getJDBCConnection
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java
 
b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java
index 5d04b786..42266083 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/java/org/apache/empire/jsf2/websample/web/pages/EmployeeListPage.java
@@ -33,6 +33,7 @@ import org.apache.empire.exceptions.BeanPropertyGetException;
 import org.apache.empire.jsf2.pageelements.BeanListPageElement;
 import org.apache.empire.jsf2.pageelements.ListPageElement;
 import org.apache.empire.jsf2.pageelements.ListPageElement.ParameterizedItem;
+import org.apache.empire.jsf2.websample.db.SampleDB.Gender;
 import org.apache.empire.jsf2.websample.db.SampleDB.TDepartments;
 import org.apache.empire.jsf2.websample.db.SampleDB.TEmployees;
 import org.apache.empire.jsf2.websample.web.SampleUtils;
@@ -54,7 +55,7 @@ public class EmployeeListPage extends SamplePage
 
         private int               id; // employeeId;
         private String            name;
-        private String            gender;
+        private Gender            gender;
         private Date              dateOfBirth;
         private String            department;
         private boolean                      retired;
@@ -100,12 +101,12 @@ public class EmployeeListPage extends SamplePage
             this.name = name;
         }
 
-        public String getGender()
+        public Gender getGender()
         {
             return gender;
         }
 
-        public void setGender(String gender)
+        public void setGender(Gender gender)
         {
             this.gender = gender;
         }
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/META-INF/context.xml
 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/META-INF/context.xml
index aa689b21..98c3f4cf 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/META-INF/context.xml
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/META-INF/context.xml
@@ -17,13 +17,12 @@
   under the License.
  -->
 <!-- This file is read by Tomcat 6 and creates the datasources required just 
by being in the META-INF directory -->
-<Context path="/empire-db" docBase="jsf-example" debug="5" reloadable="true" 
crossContext="true">
-
+<Context path="/empjsf" debug="5" reloadable="true" crossContext="true">
 
        <!-- Connection pool definition - not used in sample 
        <Resource name="jdbc/sampleDataSource" auth="Container" 
type="javax.sql.DataSource"
                maxActive="20" maxIdle="10" maxWait="-1" 
driverClassName="oracle.jdbc.driver.OracleDriver"
-               url="jdbc:oracle:thin:@esteams2:1521:ora10" username="DBSAMPLE" 
password="DBSAMPLE" />
+               url="jdbc:oracle:thin:@devserver:1521:ora19" 
username="DBSAMPLE" password="DBSAMPLE" />
        -->
 
 </Context>
\ No newline at end of file
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/config.xml 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/config.xml
index 756b130d..18af5a8e 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/config.xml
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/config.xml
@@ -21,7 +21,7 @@
 
        <properties>
                <!-- provider name must match the property-section containing 
the connection data -->
-               <databaseProvider>hsqldb</databaseProvider>
+               <databaseProvider>sqlserver</databaseProvider>
        </properties>
 
        <properties-hsqldb>
@@ -98,7 +98,7 @@
                <!-- JDBC properties for an Oracle Database connection -->
                <!-- Required jar file: ojdbc14.jar -->
                <jdbcClass>oracle.jdbc.driver.OracleDriver</jdbcClass>
-               <jdbcURL>jdbc:oracle:thin:@esteams12:1521:ora12</jdbcURL>
+               <jdbcURL>jdbc:oracle:thin:@devserver:1521:ora19</jdbcURL>
                <jdbcUser>DBSAMPLE</jdbcUser>
                <jdbcPwd>DBSAMPLE</jdbcPwd>
                <!-- Empire-db driver configuration -->
@@ -111,7 +111,7 @@
        <properties-sqlserver>
                <!-- JDBC properties for a Microsoft SQL-Server Database 
connection -->
                
<jdbcClass>com.microsoft.sqlserver.jdbc.SQLServerDriver</jdbcClass>
-               <jdbcURL>jdbc:sqlserver://esteams12\sql17</jdbcURL>
+               <jdbcURL>jdbc:sqlserver://devserver</jdbcURL>
                <jdbcUser>jdbcUser</jdbcUser>
                <jdbcPwd>jdbcPwd</jdbcPwd>
                <!-- Empire-db driver configuration -->
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml
 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml
index 2d6d4ccc..caf21913 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/WEB-INF/faces-config.xml
@@ -90,6 +90,10 @@
                <component-type>components.InputTag</component-type>
                
<component-class>org.apache.empire.jsf2.components.InputTag</component-class>
        </component>
+       <component>
+               <component-type>components.FormGridTag</component-type>
+               
<component-class>org.apache.empire.jsf2.components.FormGridTag</component-class>
+       </component>
        <component>
                <component-type>components.LabelTag</component-type>
                
<component-class>org.apache.empire.jsf2.components.LabelTag</component-class>
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/pages/employeeDetailPage.xhtml
 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/pages/employeeDetailPage.xhtml
index 012e78a6..b6bcb75c 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/pages/employeeDetailPage.xhtml
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/pages/employeeDetailPage.xhtml
@@ -37,14 +37,29 @@
 
                <h:form id="employeeDetail">
 
-               <e:tabView minHeight="400px" activeIndex="#{page.activeTab}" 
tabChangedListener="#{page.onTabChanged}">
-                       <e:tabPage title="#{msg.employeeDetail_tab_basic}" 
id="tabBasic">
-
                                <e:record value="#{page.employeeRecord}">
+                               
+                               <h2>mode="grid"</h2>
+                               <div class="formPanel">
+                               <e:formGrid mode="grid" styleClass="formGrid">
+                                       <e:control 
column="#{db.EMPLOYEES.SALUTATION}" />
+                                       <e:control 
column="#{db.EMPLOYEES.FIRST_NAME}" />
+                                       <e:control 
column="#{db.EMPLOYEES.SALARY}" custom="true">
+                                               <span 
style="display:inline-block;background-color:aqua">CUSTOM_CONTROL</span>
+                                       </e:control>
+                               </e:formGrid>
+                               </div>
+                               
                                <!-- input form -->
-                               <sample:formPanel>
-                                       <tr><e:control 
column="#{db.EMPLOYEES.SALUTATION}" /></tr>
-                                       <tr><e:control 
column="#{db.EMPLOYEES.FIRST_NAME}" /></tr>
+                               <h2>mode="table"</h2>
+                               <div class="formPanel">
+                               <e:formGrid mode="table" styleClass="inputForm">
+                                       <e:control 
column="#{db.EMPLOYEES.SALUTATION}" />
+                                       <e:control 
column="#{db.EMPLOYEES.FIRST_NAME}" />
+                                       <e:control 
column="#{db.EMPLOYEES.SALARY}" custom="true">
+                                               <span 
style="display:inline-block;background-color:aqua">CUSTOM_CONTROL</span>
+                                       </e:control>
+                                       <!-- 
                                        <tr><e:control 
column="#{db.EMPLOYEES.LAST_NAME}" /></tr>
                                        <tr><e:control 
column="#{db.EMPLOYEES.DATE_OF_BIRTH}"/></tr>
                                        <tr><e:control 
column="#{db.EMPLOYEES.DEPARTMENT_ID}" /></tr>
@@ -53,40 +68,23 @@
                                        <tr><e:control 
column="#{db.EMPLOYEES.EMAIL}" /></tr>
                                        <tr><e:control 
column="#{db.EMPLOYEES.SALARY}" /></tr>
                                        <tr><e:control 
column="#{db.EMPLOYEES.RETIRED}" /></tr>
-                                       <tr><e:control 
column="#{db.EMPLOYEES.UPDATE_TIMESTAMP}"/></tr> 
-                               </sample:formPanel>
-                               </e:record>
+                                       <tr><e:control 
column="#{db.EMPLOYEES.UPDATE_TIMESTAMP}"/></tr>
+                                        -->
+                               </e:formGrid>
+                               </div>
+                               
+                               <h2>legacy - neu</h2>
+                               <e:formGrid styleClass="formPanel">
+                                       <table class="inputForm">
+                                               <tr><e:control 
column="#{db.EMPLOYEES.SALUTATION}" /></tr>
+                                               <tr><e:control 
column="#{db.EMPLOYEES.FIRST_NAME}" /></tr>
+                                               <tr><e:control 
column="#{db.EMPLOYEES.SALARY}" custom="true">
+                                                       <span 
style="display:inline-block;background-color:aqua">CUSTOM_CONTROL</span>
+                                               </e:control></tr>
+                                       </table>
+                               </e:formGrid>
                                
-                       </e:tabPage>
-                       
-                       <e:tabPage title="#{msg.employeeDetail_tab_extended}" 
id="tabExtended" disabled="#{not page.employeeRecord.exists}">
-                               <h3><h:outputText 
value="#{msg.employeeDetail_payments}"/></h3>
-                               <!-- Payment data -->
-                               <h:dataTable id="paymentData" 
value="#{page.payments}" var="item" rowClasses="odd,even">
-                                       <h:column>
-                                               <f:facet name="header">
-                                                       <e:title 
column="#{db.PAYMENTS.YEAR}" />
-                                               </f:facet>
-                                               <e:value record="#{item}" 
column="#{db.PAYMENTS.YEAR}"/>
-                                       </h:column>
-                                       <h:column>
-                                               <f:facet name="header">
-                                                       <e:title 
column="#{db.PAYMENTS.MONTH}" />
-                                               </f:facet>
-                                               <e:value record="#{item}" 
column="#{db.PAYMENTS.MONTH}"/>
-                                       </h:column>
-                                       <h:column>
-                                               <f:facet name="header">
-                                                       <e:title 
column="#{db.PAYMENTS.AMOUNT}" />
-                                               </f:facet>
-                                               <e:value record="#{item}" 
column="#{db.PAYMENTS.AMOUNT}"/>
-                                       </h:column>
-                               </h:dataTable>
-                               <h:panelGroup layout="block" 
styleClass="info-msg">
-                                       <h:outputText 
value="#{msg.employeeDetail_msg_extended}"/>
-                               </h:panelGroup>
-                       </e:tabPage>
-               </e:tabView>    
+                               </e:record>
                
                <!-- button bar -->
                <h:panelGroup styleClass="buttonBar" layout="block">
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/control.xhtml
 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/control.xhtml
index b58a9ea9..fc82e744 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/control.xhtml
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/control.xhtml
@@ -23,12 +23,22 @@
 
        <!-- Interface -->
        <cc:interface componentType="components.ControlTag">
-               <cc:attribute name="record" />
                <cc:attribute name="column" required="true" />  
-               <cc:attribute name="readonly" />        
+               <cc:attribute name="record" />
                <cc:attribute name="custom" />  
-               <cc:attribute name="colspan" />
-               <cc:attribute name="value" />   
+               <cc:attribute name="value" />
+               <cc:attribute name="options" />
+               <cc:attribute name="mandatory"/>
+               <cc:attribute name="readonly" />        
+               <cc:attribute name="disabled"/>
+               <cc:attribute name="tabindex"/>
+               <cc:attribute name="format"/> 
+               <cc:attribute name="minValue"/> 
+               <cc:attribute name="maxValue"/>
+               <cc:attribute name="styleClass" />
+               <cc:attribute name="labelClass" /> 
+               <cc:attribute name="inputClass" /> 
+               <cc:attribute name="label" />
        </cc:interface>
        
        <!-- Implementation -->
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/input.xhtml
 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/formGrid.xhtml
similarity index 79%
copy from 
empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/input.xhtml
copy to 
empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/formGrid.xhtml
index 3dc4dd93..4367bfbe 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/input.xhtml
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/formGrid.xhtml
@@ -1,36 +1,39 @@
-<!-- 
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you 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.
- --> 
-<html xmlns="http://www.w3.org/1999/xhtml";
-       xmlns:h="http://java.sun.com/jsf/html";
-       xmlns:c="http://java.sun.com/jsp/jstl/core";
-       xmlns:cc="http://java.sun.com/jsf/composite";>
-
-       <!-- Interface -->
-       <cc:interface componentType="components.InputTag">
-               <cc:attribute name="column" required="true" />
-               <cc:attribute name="record" />
-               <cc:attribute name="value" />
-               <cc:attribute name="readonly" />        
-       </cc:interface>
-       
-       <!-- Implementation -->
-       <cc:implementation>
-       </cc:implementation>
-       
+<!-- 
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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.
+ --> 
+<html xmlns="http://www.w3.org/1999/xhtml";
+       xmlns:h="http://java.sun.com/jsf/html";
+       xmlns:c="http://java.sun.com/jsp/jstl/core";
+       xmlns:cc="http://java.sun.com/jsf/composite";>
+
+       <!-- Interface -->
+       <cc:interface componentType="components.FormGridTag">
+               <cc:attribute name="mode" />
+               <!-- overrides -->
+               <cc:attribute name="tag" />
+               <cc:attribute name="controlTag" />      
+               <cc:attribute name="labelTag" />        
+               <cc:attribute name="inputTag" />        
+       </cc:interface>
+       
+       <!-- Implementation -->
+       <cc:implementation>
+               <cc:insertChildren/>
+       </cc:implementation>
+       
 </html>
\ No newline at end of file
diff --git 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/input.xhtml
 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/input.xhtml
index 3dc4dd93..d61b1d9c 100644
--- 
a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/input.xhtml
+++ 
b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/input.xhtml
@@ -26,7 +26,14 @@
                <cc:attribute name="column" required="true" />
                <cc:attribute name="record" />
                <cc:attribute name="value" />
+               <cc:attribute name="options" />
+               <cc:attribute name="mandatory"/>
                <cc:attribute name="readonly" />        
+               <cc:attribute name="disabled"/>
+               <cc:attribute name="tabindex"/>
+               <cc:attribute name="format"/> 
+               <cc:attribute name="minValue"/> 
+               <cc:attribute name="maxValue"/>
        </cc:interface>
        
        <!-- Implementation -->
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
index e89eb58c..66f64490 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java
@@ -39,6 +39,7 @@ import org.apache.empire.data.Column;
 import org.apache.empire.db.exceptions.FieldIllegalValueException;
 import org.apache.empire.exceptions.EmpireException;
 import org.apache.empire.jsf2.controls.InputControl;
+import org.apache.empire.jsf2.utils.ControlRenderInfo;
 import org.apache.empire.jsf2.utils.TagEncodingHelper;
 import org.apache.empire.jsf2.utils.TagEncodingHelperFactory;
 import org.slf4j.Logger;
@@ -46,17 +47,21 @@ import org.slf4j.LoggerFactory;
 
 public class ControlTag extends UIInput implements NamingContainer
 {
-    public static String DEFAULT_CONTROL_SEPARATOR_TAG = "td";
     public static String DEFAULT_LABEL_SEPARATOR_CLASS = "eCtlLabel";
     public static String DEFAULT_INPUT_SEPARATOR_CLASS = "eCtlInput";
 
+    /**
+     * ControlSeparatorComponent
+     */
     public static abstract class ControlSeparatorComponent extends 
javax.faces.component.UIComponentBase
     {
         private ControlTag control = null;
         
-        private String tagName = "td";
+        protected String tagName = null;
 
-        protected abstract void writeAttributes(ResponseWriter writer, 
TagEncodingHelper helper, String tagName)
+        protected abstract String getTagName(ControlRenderInfo renderInfo);
+        
+        protected abstract void writeAttributes(ResponseWriter writer, 
TagEncodingHelper helper)
             throws IOException;
 
         @Override
@@ -65,7 +70,7 @@ public class ControlTag extends UIInput implements 
NamingContainer
             return UINamingContainer.COMPONENT_FAMILY;
         }
 
-        protected ControlTag getControl()
+        protected final ControlTag getControl()
         {
             return control;
         }
@@ -85,25 +90,26 @@ public class ControlTag extends UIInput implements 
NamingContainer
             }
 
             this.control = (ControlTag) parent;
-            // Start
-            
-            // write end tag
-            TagEncodingHelper helper = this.control.helper;
-            this.tagName = helper.getTagAttributeString("tag", "td");
+            this.tagName = getTagName(control.renderInfo);
 
-            // render components
-            ResponseWriter writer = context.getResponseWriter();
-            writer.startElement(tagName, this);
-            writeAttributes(writer, helper, tagName);
+            // Start
+            if (tagName!=null && tagName.length()>0) 
+            {   // render tag
+                ResponseWriter writer = context.getResponseWriter();
+                writer.startElement(tagName, this);
+                writeAttributes(writer, this.control.helper);
+            }
         }
         
         @Override
         public void encodeEnd(FacesContext context)
             throws IOException
         {
-            // render components
-            ResponseWriter writer = context.getResponseWriter();
-            writer.endElement(tagName);
+            if (tagName!=null && tagName.length()>0) 
+            {   // render tag
+                ResponseWriter writer = context.getResponseWriter();
+                writer.endElement(tagName);
+            }
             // call default
             super.encodeEnd(context);
         }
@@ -119,7 +125,13 @@ public class ControlTag extends UIInput implements 
NamingContainer
     public static class LabelSeparatorComponent extends 
ControlSeparatorComponent
     {
         @Override
-        protected void writeAttributes(ResponseWriter writer, 
TagEncodingHelper helper, String tagName)
+        protected String getTagName(ControlRenderInfo renderInfo)
+        {
+            return renderInfo.LABEL_WRAPPER_TAG;
+        }
+        
+        @Override
+        protected void writeAttributes(ResponseWriter writer, 
TagEncodingHelper helper)
             throws IOException
         {
             String styleClass = helper.getTagAttributeString("labelClass", 
ControlTag.DEFAULT_LABEL_SEPARATOR_CLASS);
@@ -140,9 +152,14 @@ public class ControlTag extends UIInput implements 
NamingContainer
 
     public static class InputSeparatorComponent extends 
ControlSeparatorComponent
     {
+        @Override
+        protected String getTagName(ControlRenderInfo renderInfo)
+        {
+            return renderInfo.INPUT_WRAPPER_TAG;
+        }
 
         @Override
-        protected void writeAttributes(ResponseWriter writer, 
TagEncodingHelper helper, String tagName)
+        protected void writeAttributes(ResponseWriter writer, 
TagEncodingHelper helper)
             throws IOException
         {
             String styleClass = helper.getTagAttributeString("inputClass", 
ControlTag.DEFAULT_INPUT_SEPARATOR_CLASS);
@@ -226,6 +243,7 @@ public class ControlTag extends UIInput implements 
NamingContainer
 
     protected InputControl            control              = null;
     protected InputControl.InputInfo  inpInfo              = null;
+    protected ControlRenderInfo       renderInfo           = null;
     protected boolean                 hasRequiredFlagSet   = false;
     protected boolean                 encodeLabel          = true;
     private boolean                   creatingComponents   = false;
@@ -298,12 +316,25 @@ public class ControlTag extends UIInput implements 
NamingContainer
     {
         // add label and input components when the view is loaded for the 
first time
         super.encodeBegin(context);
+        
+        // renderInfo
+        if (this.renderInfo==null)
+            this.renderInfo=helper.getControlRenderInfo();
 
         // init
         helper.encodeBegin();
         this.control = helper.getInputControl();
         boolean isCustomInput = isCustomInput();
-
+        
+        // encodeBegin
+        if (renderInfo.CONTROL_TAG!=null)
+        {   // control wrapper tag
+            ResponseWriter writer = context.getResponseWriter();
+            writer.startElement(renderInfo.CONTROL_TAG, this);
+            String styleClass = helper.getTagAttributeString("styleClass", 
"eControl"); 
+            helper.writeAttribute(writer, InputControl.HTML_ATTR_CLASS, 
styleClass);
+        }
+        
         // LabelSeparatorComponent
         if (this.encodeLabel)
         {   // Create Label Separator Tag
@@ -359,20 +390,27 @@ public class ControlTag extends UIInput implements 
NamingContainer
     {
         if (isRendered() && isCustomInput())
         {   // Custom input
-            String tagName  = helper.getTagAttributeString("tag", 
ControlTag.DEFAULT_CONTROL_SEPARATOR_TAG);
-            String inpClass = helper.getTagAttributeString("inputClass", 
ControlTag.DEFAULT_INPUT_SEPARATOR_CLASS);
-            String colSpan  = helper.getTagAttributeString("colspan");
-
-            ResponseWriter writer = context.getResponseWriter();
-            writer.startElement(tagName, this);
-            if (StringUtils.isNotEmpty(inpClass))
-                writer.writeAttribute("class", inpClass, null);
-            if (StringUtils.isNotEmpty(colSpan) && 
tagName.equalsIgnoreCase("td"))
-                writer.writeAttribute("colspan", colSpan, null);
+            ResponseWriter writer = null;
+            String tagName  = renderInfo.INPUT_WRAPPER_TAG;
+            if (tagName!=null && tagName.length()>0)
+            {   // attributes
+                String inpClass = helper.getTagAttributeString("inputClass", 
ControlTag.DEFAULT_INPUT_SEPARATOR_CLASS);
+                String colSpan  = helper.getTagAttributeString("colspan");
+                // render tag
+                writer = context.getResponseWriter();
+                writer.startElement(tagName, this);
+                if (StringUtils.isNotEmpty(inpClass))
+                    writer.writeAttribute("class", inpClass, null);
+                if (StringUtils.isNotEmpty(colSpan) && 
tagName.equalsIgnoreCase("td"))
+                    writer.writeAttribute("colspan", colSpan, null);
+            }
             // encode children
             super.encodeChildren(context);
             // end of element
-            writer.endElement(tagName);
+            if (writer!=null)
+            {   // render tag
+                writer.endElement(tagName);
+            }
         }
     }
 
@@ -380,7 +418,14 @@ public class ControlTag extends UIInput implements 
NamingContainer
     public void encodeEnd(FacesContext context)
         throws IOException
     {
+        // call base
         super.encodeEnd(context);
+        // encodeEnd
+        if (renderInfo.CONTROL_TAG!=null)
+        {   // control wrapper tag
+            ResponseWriter writer = context.getResponseWriter();
+            writer.endElement(renderInfo.CONTROL_TAG);
+        }
     }
     
     @Override
@@ -417,7 +462,7 @@ public class ControlTag extends UIInput implements 
NamingContainer
             return ObjectUtils.getBoolean(custom);
         return false;
     }
-
+    
     /**
      * called from LabelSeparatorComponent
      * @param context
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/FormGridTag.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/FormGridTag.java
new file mode 100644
index 00000000..a1e37ea5
--- /dev/null
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/FormGridTag.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.empire.jsf2.components;
+
+import java.io.IOException;
+
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.UIOutput;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.empire.jsf2.controls.InputControl;
+import org.apache.empire.jsf2.utils.ControlRenderInfo;
+import org.apache.empire.jsf2.utils.TagEncodingHelper;
+import org.apache.empire.jsf2.utils.TagEncodingHelperFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FormGridTag extends UIOutput implements NamingContainer
+{
+    // Logger
+    private static final Logger log = 
LoggerFactory.getLogger(FormGridTag.class);
+    
+    /*
+     * FormGridMode
+     */
+    private enum FormGridMode 
+    {
+        LEGACY(InputControl.HTML_TAG_DIV, null, InputControl.HTML_TAG_TD, 
InputControl.HTML_TAG_TD),
+        TABLE ("table", InputControl.HTML_TAG_TR,  InputControl.HTML_TAG_TD, 
InputControl.HTML_TAG_TD),
+        GRID  (InputControl.HTML_TAG_DIV, InputControl.HTML_TAG_DIV,  
InputControl.HTML_TAG_DIV, InputControl.HTML_TAG_DIV);
+        
+        public final String GRID_TAG;
+        public final String DEFAULT_CONTROL_TAG;
+        public final String DEFAULT_LABEL_TAG;
+        public final String DEFAULT_INPUT_TAG;
+        
+        private FormGridMode(String gridTag, String controlTag, String 
labelTag, String inputTag)
+        {
+            this.GRID_TAG = gridTag;
+            this.DEFAULT_CONTROL_TAG = controlTag;
+            this.DEFAULT_LABEL_TAG = labelTag;
+            this.DEFAULT_INPUT_TAG = inputTag;
+        }
+        
+        public static FormGridMode detect(String mode)
+        {
+            if (mode==null || mode.length()==0)
+                return LEGACY;
+            // find
+            FormGridMode[] values = values();
+            for (int i=0; i<values.length; i++)
+            {
+                if (values[i].name().equalsIgnoreCase(mode))
+                    return values[i]; 
+            }
+            // not found
+            log.warn("FormGridMode \"{}\" not found. Using default!", mode);
+            return LEGACY;
+        }
+        
+        @Override
+        public String toString()
+        {
+            return name();
+        }
+    }
+    
+    protected final TagEncodingHelper helper = 
TagEncodingHelperFactory.create(this, "eFormGrid");
+    
+    protected ControlRenderInfo controlRenderInfo = null;
+    
+    private String tagName;
+
+    @Override
+    public String getFamily()
+    {
+        return UINamingContainer.COMPONENT_FAMILY; 
+    }
+        
+    @Override
+    public void encodeBegin(FacesContext context)
+        throws IOException
+    {
+        // call base
+        super.encodeBegin(context);
+        
+        // tagName
+        FormGridMode mode = 
FormGridMode.detect(helper.getTagAttributeString("mode")); 
+        this.tagName = helper.getTagAttributeString("tag", mode.GRID_TAG);
+        
+        // render components
+        ResponseWriter writer = context.getResponseWriter();
+        writer.startElement(tagName, this);
+        writer.writeAttribute(InputControl.HTML_ATTR_ID, getClientId(), null);
+        helper.writeAttribute(writer, InputControl.HTML_ATTR_CLASS, 
helper.getTagAttributeString("styleClass", "eFormGrid"));
+        helper.writeAttribute(writer, InputControl.HTML_ATTR_STYLE, 
helper.getTagAttributeString("style"));
+    }
+
+    @Override
+    public boolean getRendersChildren()
+    {
+        return super.getRendersChildren();
+    }
+    
+    @Override
+    public void encodeChildren(FacesContext context)
+        throws IOException
+    {
+        super.encodeChildren(context);
+    }
+
+    @Override
+    public void encodeEnd(FacesContext context)
+        throws IOException
+    {
+        // call base
+        super.encodeEnd(context);
+        // close
+        ResponseWriter writer = context.getResponseWriter();
+        writer.endElement(this.tagName);
+    }
+    
+    public ControlRenderInfo getControlRenderInfo()
+    {
+        // already set?
+        if (controlRenderInfo!=null)
+            return controlRenderInfo;
+        // check mode
+        FormGridMode mode = 
FormGridMode.detect(helper.getTagAttributeString("mode")); 
+        // override?
+        String controlTag = helper.getTagAttributeString("controlTag", 
mode.DEFAULT_CONTROL_TAG);
+        String labelTag   = helper.getTagAttributeString("labelTag",   
mode.DEFAULT_LABEL_TAG);
+        String inputTag   = helper.getTagAttributeString("inputTag",   
mode.DEFAULT_INPUT_TAG);
+        // done
+        this.controlRenderInfo = new ControlRenderInfo(controlTag, labelTag, 
inputTag);
+        return controlRenderInfo;
+    }
+}
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/ControlRenderInfo.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/ControlRenderInfo.java
new file mode 100644
index 00000000..9ceffd3c
--- /dev/null
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/ControlRenderInfo.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.empire.jsf2.utils;
+
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.jsf2.controls.InputControl;
+
+/**
+ * ControlRenderInfo
+ */
+public class ControlRenderInfo
+{
+    public static final ControlRenderInfo DEFAULT_CONTROL_RENDER_INFO = new 
DefaultControlRenderInfo();
+    
+    private static class DefaultControlRenderInfo extends ControlRenderInfo
+    {
+        public DefaultControlRenderInfo()
+        {
+            super(null, InputControl.HTML_TAG_TD, InputControl.HTML_TAG_TD);
+        }
+    }
+    
+    public final String CONTROL_TAG;
+    public final String LABEL_WRAPPER_TAG;
+    public final String INPUT_WRAPPER_TAG;
+    
+    public ControlRenderInfo(String controlTag, String labelTag, String 
inputTag)
+    {
+        this.CONTROL_TAG = StringUtils.nullIfEmpty(controlTag);
+        this.LABEL_WRAPPER_TAG = StringUtils.nullIfEmpty(labelTag);
+        this.INPUT_WRAPPER_TAG = StringUtils.nullIfEmpty(inputTag);
+    }
+}
diff --git 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
index afbcf9cf..76c5fc57 100644
--- 
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
+++ 
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
@@ -67,6 +67,7 @@ import org.apache.empire.jsf2.app.FacesUtils;
 import org.apache.empire.jsf2.app.TextResolver;
 import org.apache.empire.jsf2.app.WebApplication;
 import org.apache.empire.jsf2.components.ControlTag;
+import org.apache.empire.jsf2.components.FormGridTag;
 import org.apache.empire.jsf2.components.InputTag;
 import org.apache.empire.jsf2.components.LabelTag;
 import org.apache.empire.jsf2.components.LinkTag;
@@ -418,6 +419,7 @@ public class TagEncodingHelper implements NamingContainer
     protected Object              record       = null;
     protected RecordTag           recordTag    = null;
     protected UIData              uiDataTag    = null;
+    protected FormGridTag         formGridTag  = null;
     // protected Boolean          tagRequired  = null;
     protected Boolean             hasValueExpr = null;
     protected InputControl        control      = null;
@@ -1431,6 +1433,34 @@ public class TagEncodingHelper implements NamingContainer
     {
         return getTagAttributeString(name, null);
     }
+    
+    /* ********************** FormGridTag ********************** */
+
+    protected FormGridTag getFormGrid()
+    {
+        if (this.formGridTag!=null)
+            return formGridTag;
+        // walk upwards the parent component tree and return the first record 
component found (if any)
+        UIComponent parent = component;
+        while ((parent = parent.getParent()) != null)
+        {
+            if (parent instanceof FormGridTag)
+            {   // found
+                this.formGridTag = (FormGridTag) parent;
+                return this.formGridTag;
+            }
+        }
+        return null;
+    }
+    
+    public ControlRenderInfo getControlRenderInfo()
+    {
+        FormGridTag formGrid = getFormGrid();
+        if (formGrid!=null)
+            return formGrid.getControlRenderInfo();
+        else
+            return ControlRenderInfo.DEFAULT_CONTROL_RENDER_INFO;
+    }
 
     /* ********************** label ********************** */
 


Reply via email to