You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2012/03/30 03:12:31 UTC

svn commit: r1307198 - in /myfaces: core/branches/1.2.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java shared/trunk_3.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java

Author: lu4242
Date: Fri Mar 30 01:12:31 2012
New Revision: 1307198

URL: http://svn.apache.org/viewvc?rev=1307198&view=rev
Log:
MYFACES-3518 and MYFACES-1528 Regression: <h:DataTable> empty with CachedRowSet

Modified:
    myfaces/core/branches/1.2.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java
    myfaces/shared/trunk_3.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java

Modified: myfaces/core/branches/1.2.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1.2.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java?rev=1307198&r1=1307197&r2=1307198&view=diff
==============================================================================
--- myfaces/core/branches/1.2.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java (original)
+++ myfaces/core/branches/1.2.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java Fri Mar 30 01:12:31 2012
@@ -19,8 +19,14 @@
 package org.apache.myfaces.renderkit.html;
 
 import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
 
+import javax.faces.component.UIColumn;
+import javax.faces.component.behavior.AjaxBehavior;
 import javax.faces.component.html.HtmlDataTable;
+import javax.faces.component.html.HtmlOutputText;
+import javax.faces.model.ListDataModel;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -64,6 +70,11 @@ public class HtmlTableRendererTest exten
                 dataTable.getRendererType(),
                 new HtmlTableRenderer());
 
+        HtmlOutputText text = new HtmlOutputText();
+        facesContext.getRenderKit().addRenderer(
+                text.getFamily(),
+                text.getRendererType(),
+                new HtmlTextRenderer());
     }
 
     public void tearDown() throws Exception
@@ -94,4 +105,148 @@ public class HtmlTableRendererTest exten
             fail(HtmlCheckAttributesUtil.constructErrorMessage(attrs, writer.getWriter().toString()));
         }
     }
+    
+    /**
+     * Components that render client behaviors should always render "id" and "name" attribute
+     */
+    public void testClientBehaviorHolderRendersIdAndName() 
+    {
+        dataTable.addClientBehavior("keypress", new AjaxBehavior());
+        try 
+        {
+            dataTable.encodeAll(facesContext);
+            String output = ((StringWriter) writer.getWriter()).getBuffer().toString();
+            assertTrue(output.matches("(?s).+id=\".+\".+"));
+            assertTrue(output.matches("(?s).+name=\".+\".+"));
+        }
+        catch (Exception e)
+        {
+            fail(e.getMessage());
+        }
+        
+    }
+    
+    /**
+     * Check table renderer behavior when DataModel returns -1 from getRowCount(). It should
+     * render the same as if that value is provided. Note t:dataTable newspaper mode requires
+     * row count to calculate newspaperRows and newspaperColumns. 
+     */
+    public void testNoRowCountRender()
+    {
+        List<Person> list = new ArrayList<Person>();
+        list.add(new Person("John"  , "Smith"));
+        list.add(new Person("Pepito", "Perez"));
+        list.add(new Person("Kurt",   "Kobain"));
+        
+        dataTable.setId("data");
+        dataTable.setRowClasses("class1, class2");
+        dataTable.setVar("person");
+        
+        UIColumn column1 = new UIColumn();
+        HtmlOutputText text = new HtmlOutputText();
+        text.setValueExpression("value", 
+                facesContext.getApplication().getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(), "#{person.firstName}", String.class));
+        column1.getChildren().add(text);
+        
+        dataTable.getChildren().add(column1);
+        UIColumn column2 = new UIColumn();
+        HtmlOutputText text2 = new HtmlOutputText();
+        text2.setValueExpression("value", 
+                facesContext.getApplication().getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(), "#{person.lastName}", String.class));
+        column2.getChildren().add(text2);
+        dataTable.getChildren().add(column2);
+
+        dataTable.setValue(new UnknownRowCountDemoDataModel<Person>(list));
+
+        String output1 = null;
+        try 
+        {
+            dataTable.encodeAll(facesContext);
+            output1 = ((StringWriter) writer.getWriter()).getBuffer().toString();
+        }
+        catch (Exception e)
+        {
+            fail(e.getMessage());
+        }
+        
+        dataTable.setValue(new ListDataModel<Person>(list));
+        ((StringWriter) writer.getWriter()).getBuffer().setLength(0);
+        
+        String output2 = null;
+        try 
+        {
+            dataTable.encodeAll(facesContext);
+            output2 = ((StringWriter) writer.getWriter()).getBuffer().toString();
+        }
+        catch (Exception e)
+        {
+            fail(e.getMessage());
+        }
+        
+        assertTrue(output2.contains("John"));
+        assertTrue(output2.contains("Smith"));
+        assertTrue(output2.contains("class1"));
+        assertTrue(output2.contains("class2"));
+        
+        assertTrue(output1.contains("John"));
+        assertTrue(output1.contains("Smith"));
+        assertTrue(output1.contains("class1"));
+        assertTrue(output1.contains("class2"));
+        
+        assertEquals(output2, output1);
+    }
+
+    public class Person
+    {
+        private String firstName;
+        
+        private String lastName;
+        
+        public Person(String firstName, String lastName)
+        {
+            this.firstName = firstName;
+            this.lastName = lastName;
+        }
+        
+        public String getFirstName()
+        {
+            return firstName;
+        }
+        
+        public void setFirstName(String firstName)
+        {
+            this.firstName = firstName;
+        }
+        
+        public String getLastName()
+        {
+            return lastName;
+        }
+        
+        public void setLastName(String lastName)
+        {
+            this.lastName = lastName;
+        }
+    }
+    
+    public class UnknownRowCountDemoDataModel<E> extends ListDataModel<E>
+    {
+        public UnknownRowCountDemoDataModel()
+        {
+            super();
+        }
+
+        public UnknownRowCountDemoDataModel(List<E> list)
+        {
+            super(list);
+        }
+        
+        @Override
+        public int getRowCount()
+        {
+            return -1;
+        }
+    }
 }

Modified: myfaces/shared/trunk_3.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_3.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java?rev=1307198&r1=1307197&r2=1307198&view=diff
==============================================================================
--- myfaces/shared/trunk_3.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java (original)
+++ myfaces/shared/trunk_3.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java Fri Mar 30 01:12:31 2012
@@ -218,6 +218,7 @@ public class HtmlTableRendererBase exten
         }
     }
 
+
     /**
      * Renders everything inside the TBODY tag by iterating over the row objects
      * between offsets first and first+rows and applying the UIColumn components
@@ -233,7 +234,16 @@ public class HtmlTableRendererBase exten
 
         int rowCount = uiData.getRowCount();
 
-        if (rowCount == 0) {
+        int newspaperColumns = getNewspaperColumns(component);
+
+        if (rowCount == -1 && newspaperColumns == 1)
+        {
+            encodeInnerHtmlUnknownRowCount(facesContext, component);
+            return;
+        }
+        
+        if (rowCount == 0)
+        {
             //nothing to render, to get valid xhtml we render an empty dummy row
             writer.startElement(HTML.TR_ELEM, uiData);
             writer.startElement(HTML.TD_ELEM, uiData);
@@ -263,11 +273,15 @@ public class HtmlTableRendererBase exten
            }
         }
 
-        int newspaperColumns = getNewspaperColumns(component);
         int newspaperRows;
         if((last - first) % newspaperColumns == 0)
+        {
             newspaperRows = (last - first) / newspaperColumns;
-        else newspaperRows = ((last - first) / newspaperColumns) + 1;
+        }
+        else
+        {
+            newspaperRows = ((last - first) / newspaperColumns) + 1;
+        }
         boolean newspaperHorizontalOrientation = isNewspaperHorizontalOrientation(component);
 
         // walk through the newspaper rows
@@ -275,26 +289,36 @@ public class HtmlTableRendererBase exten
         {
             boolean rowStartRendered = false;
             // walk through the newspaper columns
-            for(int nc = 0; nc < newspaperColumns; nc++) {
+            for(int nc = 0; nc < newspaperColumns; nc++)
+            {
 
                 // the current row in the 'real' table
                 int currentRow;
                 if (newspaperHorizontalOrientation)
+                {
                     currentRow = nr * newspaperColumns + nc + first;
+                }
                 else
+                {
                     currentRow = nc * newspaperRows + nr + first;
+                }
                 
                 // if this row is not to be rendered
-                if(currentRow >= last) continue;
+                if(currentRow >= last)
+                {
+                    continue;
+                }
 
                 // bail if any row does not exist
                 uiData.setRowIndex(currentRow);
-                if(!uiData.isRowAvailable()) {
+                if(!uiData.isRowAvailable())
+                {
                     log.error("Row is not available. Rowindex = " + currentRow);
                     break;
                 }
     
-                if (nc == 0) {
+                if (nc == 0)
+                {
                     // first column in table, start new row
                     beforeRow(facesContext, uiData);
 
@@ -303,28 +327,40 @@ public class HtmlTableRendererBase exten
                     rowStartRendered = true;
                 }
 
-                List children = getChildren(component);
+                List children = null;
                 for (int j = 0, size = getChildCount(component); j < size; j++)
                 {
+                    if (children == null)
+                    {
+                        children = getChildren(component);
+                    }
                     UIComponent child = (UIComponent) children.get(j);
                     if (child.isRendered())
                     {
                         boolean columnRendering = child instanceof UIColumn;
                         
                         if (columnRendering)
+                        {
                             beforeColumn(facesContext, uiData, j);
+                        }
                            
-                        encodeColumnChild(facesContext, writer, uiData, child, styles, nc * uiData.getChildCount() + j);                    
+                        encodeColumnChild(facesContext, writer, uiData, child, 
+                                styles, nc * uiData.getChildCount() + j);                    
                        
                         if (columnRendering)
+                        {
                             afterColumn(facesContext, uiData, j);
+                        }
                     }
                 }
 
                 if (hasNewspaperTableSpacer(uiData))
                 {
                     // draw the spacer facet
-                    if(nc < newspaperColumns - 1) renderSpacerCell(facesContext, writer, uiData);
+                    if(nc < newspaperColumns - 1)
+                    {
+                        renderSpacerCell(facesContext, writer, uiData);
+                    }
                 }
             }
             if (rowStartRendered)
@@ -335,6 +371,83 @@ public class HtmlTableRendererBase exten
         }
     }
 
+    private void encodeInnerHtmlUnknownRowCount(FacesContext facesContext, UIComponent component)throws IOException
+    {
+        UIData uiData = (UIData) component;
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        Styles styles = getStyles(uiData);
+        
+        int first = uiData.getFirst();
+        int rows = uiData.getRows();
+        int currentRow = first;
+        boolean isRowRendered = false;
+        
+        while(true)
+        {
+            uiData.setRowIndex(currentRow);
+            if (!uiData.isRowAvailable())
+            {
+                break;
+            }
+            
+            isRowRendered = true;
+            
+            // first column in table, start new row
+            beforeRow(facesContext, uiData);
+
+            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+            renderRowStart(facesContext, writer, uiData, styles, currentRow);
+            
+            List<UIComponent> children = null;
+            for (int j = 0, size = getChildCount(component); j < size; j++)
+            {
+                if (children == null)
+                {
+                    children = getChildren(component);
+                }
+                UIComponent child = (UIComponent) children.get(j);
+                if (child.isRendered())
+                {
+                    boolean columnRendering = child instanceof UIColumn;
+                    
+                    if (columnRendering)
+                    {
+                        beforeColumn(facesContext, uiData, j);
+                    }
+                       
+                    encodeColumnChild(facesContext, writer, uiData, child, 
+                            styles, j);                    
+                   
+                    if (columnRendering)
+                    {
+                        afterColumn(facesContext, uiData, j);
+                    }
+                }
+            }
+
+            renderRowEnd(facesContext, writer, uiData);
+            afterRow(facesContext, uiData);
+            
+            currentRow++;
+
+            if (rows > 0 && currentRow-first > rows )
+            {
+                break;
+            }
+        }
+        
+        if (!isRowRendered)
+        {
+            //nothing to render, to get valid xhtml we render an empty dummy row
+            writer.startElement(HTML.TR_ELEM, uiData);
+            writer.startElement(HTML.TD_ELEM, uiData);
+            writer.endElement(HTML.TD_ELEM);
+            writer.endElement(HTML.TR_ELEM);
+            return;
+        }
+    }
+
     protected void encodeColumnChild(FacesContext facesContext, ResponseWriter writer,
         UIData uiData, UIComponent component, Styles styles, int columnStyleIndex) throws IOException
     {