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:13:06 UTC
svn commit: r1307200 - in /myfaces/core/trunk:
impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java
shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java
Author: lu4242
Date: Fri Mar 30 01:13:06 2012
New Revision: 1307200
URL: http://svn.apache.org/viewvc?rev=1307200&view=rev
Log:
MYFACES-3518 and MYFACES-1528 Regression: <h:DataTable> empty with CachedRowSet
Modified:
myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java
myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java
Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java?rev=1307200&r1=1307199&r2=1307200&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlTableRendererTest.java Fri Mar 30 01:13:06 2012
@@ -19,18 +19,23 @@
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;
-import org.apache.myfaces.test.utils.HtmlCheckAttributesUtil;
-import org.apache.myfaces.test.utils.HtmlRenderedAttr;
import org.apache.myfaces.test.base.AbstractJsfTestCase;
import org.apache.myfaces.test.mock.MockRenderKitFactory;
import org.apache.myfaces.test.mock.MockResponseWriter;
+import org.apache.myfaces.test.utils.HtmlCheckAttributesUtil;
+import org.apache.myfaces.test.utils.HtmlRenderedAttr;
/**
* @author Bruno Aranda (latest modification by $Author$)
@@ -64,7 +69,13 @@ public class HtmlTableRendererTest exten
dataTable.getFamily(),
dataTable.getRendererType(),
new HtmlTableRenderer());
-
+
+ HtmlOutputText text = new HtmlOutputText();
+ facesContext.getRenderKit().addRenderer(
+ text.getFamily(),
+ text.getRendererType(),
+ new HtmlTextRenderer());
+
facesContext.getAttributes().put("org.apache.myfaces.RENDERED_JSF_JS", Boolean.TRUE);
}
@@ -116,4 +127,128 @@ public class HtmlTableRendererTest exten
}
}
+
+ /**
+ * 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/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java?rev=1307200&r1=1307199&r2=1307200&view=diff
==============================================================================
--- myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java (original)
+++ myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlTableRendererBase.java Fri Mar 30 01:13:06 2012
@@ -327,6 +327,29 @@ public class HtmlTableRendererBase exten
}
}
+ private Integer[] getBodyRows(FacesContext facesContext, UIComponent component)
+ {
+ Integer[] bodyrows = null;
+ String bodyrowsAttr = (String) component.getAttributes().get(JSFAttr.BODYROWS_ATTR);
+ if(bodyrowsAttr != null && !"".equals(bodyrowsAttr))
+ {
+ String[] bodyrowsString = StringUtils.trim(StringUtils.splitShortString(bodyrowsAttr, ','));
+ // parsing with no exception handling, because of JSF-spec:
+ // "If present, this must be a comma separated list of integers."
+ bodyrows = new Integer[bodyrowsString.length];
+ for(int i = 0; i < bodyrowsString.length; i++)
+ {
+ bodyrows[i] = new Integer(bodyrowsString[i]);
+ }
+
+ }
+ else
+ {
+ bodyrows = ZERO_INT_ARRAY;
+ }
+ return bodyrows;
+ }
+
/**
* Renders everything inside the TBODY tag by iterating over the row objects
* between offsets first and first+rows and applying the UIColumn components
@@ -337,12 +360,19 @@ public class HtmlTableRendererBase exten
*/
public void encodeInnerHtml(FacesContext facesContext, UIComponent component)throws IOException
{
-
UIData uiData = (UIData) component;
ResponseWriter writer = facesContext.getResponseWriter();
int rowCount = uiData.getRowCount();
+ 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
@@ -377,7 +407,6 @@ public class HtmlTableRendererBase exten
}
}
- int newspaperColumns = getNewspaperColumns(component);
int newspaperRows;
if((last - first) % newspaperColumns == 0)
{
@@ -390,24 +419,7 @@ public class HtmlTableRendererBase exten
boolean newspaperHorizontalOrientation = isNewspaperHorizontalOrientation(component);
// get the row indizes for which a new TBODY element should be created
- Integer[] bodyrows = null;
- String bodyrowsAttr = (String) component.getAttributes().get(JSFAttr.BODYROWS_ATTR);
- if(bodyrowsAttr != null && !"".equals(bodyrowsAttr))
- {
- String[] bodyrowsString = StringUtils.trim(StringUtils.splitShortString(bodyrowsAttr, ','));
- // parsing with no exception handling, because of JSF-spec:
- // "If present, this must be a comma separated list of integers."
- bodyrows = new Integer[bodyrowsString.length];
- for(int i = 0; i < bodyrowsString.length; i++)
- {
- bodyrows[i] = new Integer(bodyrowsString[i]);
- }
-
- }
- else
- {
- bodyrows = ZERO_INT_ARRAY;
- }
+ Integer[] bodyrows = getBodyRows(facesContext, component);
int bodyrowsCount = 0;
// walk through the newspaper rows
@@ -520,6 +532,113 @@ public class HtmlTableRendererBase exten
writer.endElement(HTML.TBODY_ELEM);
}
}
+
+ private void encodeInnerHtmlUnknownRowCount(FacesContext facesContext, UIComponent component)throws IOException
+ {
+ UIData uiData = (UIData) component;
+ ResponseWriter writer = facesContext.getResponseWriter();
+
+ Styles styles = getStyles(uiData);
+
+ Integer[] bodyrows = getBodyRows(facesContext, component);
+ int bodyrowsCount = 0;
+
+ 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);
+
+ // is the current row listed in the bodyrows attribute
+ if(ArrayUtils.contains(bodyrows, currentRow))
+ {
+ // close any preopened TBODY element first
+ if(bodyrowsCount != 0)
+ {
+ HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+ writer.endElement(HTML.TBODY_ELEM);
+ }
+ HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+ writer.startElement(HTML.TBODY_ELEM, uiData);
+ // Do not attach bodyrowsCount to the first TBODY element, because of backward compatibility
+ writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element" +
+ (bodyrowsCount == 0 ? "" : bodyrowsCount), null);
+ bodyrowsCount++;
+ }
+
+ 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.TBODY_ELEM, uiData);
+ writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element", null);
+ writer.startElement(HTML.TR_ELEM, uiData);
+ writer.startElement(HTML.TD_ELEM, uiData);
+ writer.endElement(HTML.TD_ELEM);
+ writer.endElement(HTML.TR_ELEM);
+ writer.endElement(HTML.TBODY_ELEM);
+ return;
+ }
+
+ if(bodyrowsCount != 0)
+ {
+ // close the last TBODY element
+ HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+ writer.endElement(HTML.TBODY_ELEM);
+ }
+ }
protected void encodeColumnChild(FacesContext facesContext, ResponseWriter writer,
UIData uiData, UIComponent component, Styles styles, int columnStyleIndex) throws IOException