* This method is separated from the encodeChildren so that it can be overridden by
* subclasses. One class that uses this functionality is autoUpdateDataTable.
*/
public void encodeInnerHtml(FacesContext facesContext, UIComponent component)throws IOException{
UIData uiData = (UIData) component;
ResponseWriter writer = facesContext.getResponseWriter();
int rowCount = uiData.getRowCount();
if (rowCount == 0) {
//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;
}
// begin the table
// get the CSS styles
Styles styles = getStyles(uiData);
int first = uiData.getFirst();
int rows = uiData.getRows();
int last;
if (rows <= 0)
{
last = rowCount;
}
else
{
last = first + rows;
if (last > rowCount)
{
last = rowCount;
}
}
int newspaperColumns = getNewspaperColumns(component);
int newspaperRows;
if((last - first) % newspaperColumns == 0)
newspaperRows = (last - first) / newspaperColumns;
else newspaperRows = ((last - first) / newspaperColumns) + 1;
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;
}
int bodyrowsCount = 0;
// walk through the newspaper rows
for(int nr = 0; nr < newspaperRows; nr++)
{
boolean rowStartRendered = false;
// walk through the newspaper columns
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;
// bail if any row does not exist
uiData.setRowIndex(currentRow);
if(!uiData.isRowAvailable()) {
log.severe("Row is not available. Rowindex = " + currentRow);
break;
}
if (nc == 0) {
// 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, nr);
rowStartRendered = true;
}
List children = getChildren(component);
for (int j = 0, size = getChildCount(component); j < size; j++)
{
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);
if (columnRendering)
afterColumn(facesContext, uiData, j);
}
}