UITree binding and other issues
christian.bauer Mar 19, 2007 11:44 AMYou guys should use the Swing TreeModel/TreeNode combo and not invent your own model.
The RichFaces TreeNode concept seems to be limited to exactly what the demo is doing - read an XML file and implement a separate class that represents the root node. I found no example with more dynamic tree adapters (what you usually do with a custom TreeModel in Swing).
This is how it looks. Most people want lazy loading of children on the server. So what you need to support is this:
- Composite Pattern: Node(Directory -to-many-> Document, Document)
- The following code loads the root "node", imagine a C:/ directory
- On-demand loading of subdirectories of C:/ and wrapping when the tree is expanded
- No "files" are shown
@Name("treeNodeAdapter")
public static class TreeNodeAdapter {
@Factory(value = "directoryTree", scope = ScopeType.CONVERSATION, autoCreate = true)
public TreeNode loadReadableDirectoryTree() {
Directory wikiroot = (Directory) Component.getInstance("wikiRoot");
return new WikiTreeNode(wikiroot);
}
class WikiTreeNode implements TreeNode {
private Node wikiNode;
private Map<Object, TreeNode> childrenMap = new LinkedHashMap<Object,TreeNode>();
public WikiTreeNode(Node wikiNode) {
if (wikiNode != null) {
this.wikiNode = wikiNode;
for (Node childNode : wikiNode.getChildren()) {
if (!WikiUtil.isDirectory(childNode)) continue;
childrenMap.put(childNode.getId(), new WikiTreeNode(childNode));
}
}
}
public Object getData() { return wikiNode; }
public void setData(Object node) { this.wikiNode = (Node)node; }
public boolean isLeaf() {
return childrenMap.size() == 0;
}
public Iterator getChildren() {
return childrenMap.entrySet().iterator();
}
public TreeNode getChild(Object identifier) {
return childrenMap.get( identifier );
}
public void addChild(Object identifier, TreeNode treeNode) {
childrenMap.put(identifier, treeNode);
}
public void removeChild(Object identifier) {
// Immutable
}
public TreeNode getParent() {
return new WikiTreeNode(wikiNode.getParent());
}
public void setParent(TreeNode treeNode) {
// Immutable
}
}
}
If you render #{directoryTree} with <rich:tree>, you get the C:/ ROOT shown - after all that is what is returned from this factory. There doesn't seem to be a way to hide the ROOT node. That wouldn't be really bad, what is bad is that you get a NullPointerException when you try to collapse the ROOT node. The rest of the tree seems to work fine (which is better than what I ever got in Icefaces or Oracle ADF after 2 hours of work).
You should also as soon as possible extend the Tree documentation with an example for selection - nobody cares about drag and drop, people want to select a node first. Also, the word "cashing" is really spelled "caching".
Please put this in an appropriate JIRA entry.
Thanks