I have some questions about a <tr:table> with an
org.apache.myfaces.trinidad.model.CollectionModel.
If I attach a CollectionModel to a <tr:table> as defined in the tag
specification, I see some things
happening that I don't understand. Could anybody help me out?
I use the following simple JSP file to create the table (with all
irrelevant statements removed):
<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root version="2.0"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:tr="http://myfaces.apache.org/trinidad">
<jsp:directive.page contentType="text/html; charset=utf-8"/>
<f:view>
<tr:document title="tr:table test">
<tr:form>
<tr:table value="#{blocks.all}" var="row">
<tr:column>
<f:facet name="header"><tr:outputText
value="ID"/></f:facet>
<tr:outputText value="#{row.id}"/>
</tr:column>
</tr:table>
</tr:form>
<h:messages layout="table" globalOnly="true"/>
</tr:document>
</f:view>
</jsp:root>
The table is connected to the following bean:
package nl.timeware.vrtsim.beans;
import java.util.*;
import org.apache.myfaces.trinidad.model.*;
public class BlockBean
{
private TableModel tableModel;
public BlockBean()
{ tableModel = new TableModel();
}
public TableModel getAll()
{ return tableModel;
}
private class TableModel extends CollectionModel
{
private List<BlockRow> blockList;
private int selectedRow = -1;
public TableModel()
{ blockList = new ArrayList<BlockRow>();
for (int id = 0; id < 5; id++)
blockList.add(new BlockRow(id));
setWrappedData(blockList);
}
public void setWrappedData(Object data)
{ blockList = (List<BlockRow>)data;
selectedRow = blockList.size() > 0 ? 0 : -1;
}
public Object getWrappedData()
{ return blockList;
}
public int getRowIndex()
{ System.out.println("getRowIndex(): " + selectedRow);
return selectedRow;
}
public void setRowIndex(int rowIndex)
{ System.out.println("setRowIndex(" + rowIndex + ")");
if (rowIndex < -1)
{ System.out.println("setRowIndex(" + rowIndex + "): throws
IllegalArgumentException()");
throw new IllegalArgumentException("invalid row");
}
selectedRow = rowIndex;
}
public boolean isRowAvailable()
{ boolean available = selectedRow >= 0 && selectedRow <
blockList.size();
System.out.println("isRowAvailable(): " + available);
return available;
}
public boolean isRowAvailable(int rowIndex)
{ boolean available = rowIndex >= 0 && rowIndex < blockList.size();
System.out.println("isRowAvailable(" + rowIndex + "): " +
available);
return available;
}
public int getRowCount()
{ System.out.println("getRowCount(): " + blockList.size());
return blockList.size();
}
public Object getRowData()
{ if (blockList == null)
{ System.out.println("getRowData(): no list");
return null;
}
else if (selectedRow < 0)
{ System.out.println("getRowData(): no selected row");
throw new IllegalArgumentException("invalid row");
}
else
{ System.out.println("getRowData(): row = " +
blockList.get(selectedRow).getId());
return blockList.get(selectedRow);
}
}
public Object getRowData(int rowIndex)
{ if (blockList == null)
{ System.out.println("getRowData(" + rowIndex + "): no list");
return null;
}
else if (selectedRow < 0)
{ System.out.println("getRowData(" + rowIndex + "): no
selected row");
throw new IllegalArgumentException("invalid row");
}
else
{ System.out.println("getRowData(" + rowIndex + "): row = "
+ blockList.get(selectedRow).getId());
return blockList.get(selectedRow);
}
}
public Object getRowKey()
{ if (blockList == null)
{ System.out.println("getRowKey(): no list");
return null;
}
else if (selectedRow < 0)
{ System.out.println("getRowKey(): no selection");
return null; // actually should throw new
IllegalArgumentException("invalid row");
}
else
{ System.out.println("getRowKey(): row = " + selectedRow +
"; key = " + blockList.get(selectedRow).getId());
return blockList.get(selectedRow).getId();
}
}
public void setRowKey(Object key)
{ System.out.println("setRowKey(" + key + ")");
if (blockList == null)
{ System.out.println("setRowKey(" + key + "): no list");
return;
}
else if (key == null) // not supposed to be called like this
{ System.out.println("setRowKey(" + key + ")");
selectedRow = -1;
}
else if (selectedRow < 0 && selectedRow >= blockList.size())
{ System.out.println("setRowKey(" + key + "): invalid row "
+ selectedRow);
throw new IllegalArgumentException("invalid row");
}
else
for (int index = 0; index < blockList.size(); index++)
if (blockList.get(index).getId() == (Integer)key)
{ selectedRow = index;
System.out.println("setRowKey(" + key + "): selected
row = " + index);
break;
}
}
private class BlockRow
{
private int originalID;
public BlockRow(int id)
{ originalID = id;
}
public int getId()
{ return originalID;
}
}
}
}
Now during rendering I get the following output from my printf's:
setRowIndex(-1)
getRowKey(): no selection
getRowKey(): no selection
setRowIndex(-1)
isRowAvailable(): false
getRowKey(): no selection
getRowCount(): 5
isRowAvailable(4): true
getRowCount(): 5
getRowCount(): 5
isRowAvailable(4): true
setRowIndex(0)
isRowAvailable(): true
getRowData(): row = 0
getRowKey(): row = 0; key = 0
getRowIndex(): 0
getRowIndex(): 0
setRowKey(null)
setRowKey(null)
isRowAvailable(): false
getRowKey(): no selection
Question 1: Why is the row index set twice to -1, while plenty of rows
are available? (and all the other repetitions...)
Question 2: What should I return on getRowKey() when no row is selected?
I would like to throw an exception but that stops the whole show...
Question 3: Why does it insist on making that non-existent row current
by setRowKey(null)?
Question 4: Why does it finally throw an
org.apache.jasper.el.JspPropertyNotFoundException:
/jsp/tr-table.jsp(15,41) '#{row.id}' Property 'id' not readable on type
int? public int getId() is a correct signature, isn't it?
Any help would of course very much be appreciated!
Regards, Paul.