org.apache.myfaces.trinidad.model
Class TreeModel

java.lang.Object
  extended by javax.faces.model.DataModel
      extended by org.apache.myfaces.trinidad.model.CollectionModel
          extended by org.apache.myfaces.trinidad.model.TreeModel
All Implemented Interfaces:
RowKeyIndex
Direct Known Subclasses:
ChildPropertyTreeModel, MenuModel

public abstract class TreeModel
extends CollectionModel

The data model used by Trinidad Tree components. A TreeModel is responsible for understanding how to iterate through an object graph, enter and leave containers, and identify rows of objects within each container. Within any one container, a TreeModel looks just like a CollectionModel, which extends the JSF DataModel class. (So, to understand this class, start by learning how DataModel works).

Entering and exiting containers

TreeModel extends CollectionModel to add support for container rows, which are entered and exited with enterContainer() and exitContainer() methods. Within a container, row indices (get/setRowIndex()) are relative to the container. However, row keys - get/setRowKey(), from the CollectionModel API - are always global for the entire tree model, so it is sufficient to call setRowKey() to enter and exit all the needed parents.

Lazy loading of contents

When a tree or treeTable iterates through the model, it will generally seek to see if a given node is a container - with the isContainer() method - and also see if the node is empty (and therefore not expandable) with the isContainerEmpty() method. The default implementation of that latter method involves entering the child and seeing how many children it has. As a result, by default, you will see one more level of content being requested than is actually visible on screen. To avoid this, provide a custom override of isContainerEmpty() to return a value without actually entering the container. It is acceptable for this method to return a "false negative" - to return false when there might actually not be any contents - if that is the most efficient approach possible.

The ChildPropertyTreeModel class is a useful basic subclass, but largely requires that you have the entire object model fully loaded. If you require lazy loading, you'll likely need a custom implementation.

Further documentation

Rows in the TreeModel may (recursively) contain other rows. To figure out if the current row is a container, call the isContainer() method. If a row is a container, use the enterContainer() method to access its child rows. Once the enterContainer() method is called all the CollectionModel API's methods (like DataModel.getRowCount()) operate on the child collection. To return back to the parent row, use the exitContainer() method.

Given the following tree structure:

 |-Root1 (rowKey="r1", rowIndex=0)
 |  |-Folder1 (rowKey="r1f1", rowIndex=0)
 |  |  |-Node1 (rowKey="r1f1n1", rowIndex=0)
 |  |  |-Node2 (rowKey="r1f1n2", rowIndex=1)
 |  |  |-Node3 (rowKey="r1f1n3", rowIndex=2)
 |  |
 |  |-Folder2 (rowKey="r1f2", rowIndex=1)
 |     |-Node4 (rowKey="r1f2n1", rowIndex=0)
 |
 |-Root2 (rowKey="r2", rowIndex=1)
 |-Root3 (rowKey="r3", rowIndex=2)
 |-Root4 (rowKey="r4", rowIndex=3)
 
To point the tree to the root collection call: setRowKey(null).
Now, getRowCount() returns 4.
setRowIndex(1);getRowData() returns Root2.
setRowKey("r4");getRowData() returns Root4.

To access Node4 use:

 setRowIndex(0); // isContainer()==true
 enterContainer(); // enter Root1, getRowCount()==2
 setRowIndex(1); // isContainer()==true
 enterContainer(); // enter Folder2, getRowCount()==1
 setRowIndex(0); // isContainer()==false
 getRowData();
 
Or, more simply:
 setRowKey("r1f2n1");
 getRowData();
 
At this point, to get at Node3 use:
 exitContainer(); // exit Folder2, Root1 is now the current row.
 setRowIndex(0);
 enterContainer(); // enter Folder1, getRowCount()==3
 setRowIndex(2);
 getRowData();
 
Or, more simply:
 setRowKey("r1f1n3");
 getRowData();
 


Constructor Summary
TreeModel()
           
 
Method Summary
abstract  void enterContainer()
          This Collection changes to reflect the children of the current rowData, and the current rowData changes to be null.
abstract  void exitContainer()
          Pops back up to the parent collection.
 java.util.List<java.lang.Object> getAllAncestorContainerRowKeys(java.lang.Object childRowKey)
          Gets the rowkey of each container, starting from the top most container, down to the container of the given child rowKey.
 java.lang.Object getContainerRowKey()
          Gets the rowKey of the current row's container row.
abstract  java.lang.Object getContainerRowKey(java.lang.Object childRowKey)
          Gets the rowKey of a given child row's container row.
 int getDepth()
          Gets the depth of the current row within this tree hierarchy.
 int getDepth(java.lang.Object rowKey)
          Gets the depth of the given row within the tree hierarchy.
abstract  boolean isContainer()
          Tests to see if the row identified by getRowData() is a container element.
 boolean isContainerEmpty()
          Tests to see if the current container element actually has children.
 
Methods inherited from class org.apache.myfaces.trinidad.model.CollectionModel
getRowData, getRowKey, getSortCriteria, isRowAvailable, isSortable, setRowKey, setSortCriteria
 
Methods inherited from class javax.faces.model.DataModel
addDataModelListener, getDataModelListeners, getRowCount, getRowData, getRowIndex, getWrappedData, isRowAvailable, removeDataModelListener, setRowIndex, setWrappedData
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.apache.myfaces.trinidad.model.RowKeyIndex
getRowCount, getRowData, getRowIndex, isRowAvailable, setRowIndex
 

Constructor Detail

TreeModel

public TreeModel()
Method Detail

isContainer

public abstract boolean isContainer()
Tests to see if the row identified by getRowData() is a container element. Use isContainerEmpty() to see if the current container element actually has children, or is an empty container.

Returns:
true if the current element may contain children.

isContainerEmpty

public boolean isContainerEmpty()
Tests to see if the current container element actually has children. This could be more efficient than calling enterContainer() followed by DataModel.getRowCount(). This method is permitted to return false even if the container is actually empty. This method should only be called if isContainer() returns true.

Returns:
true if the current container element has no children. If there is any doubt as to whether or not the container has children, this method should return false.

enterContainer

public abstract void enterContainer()
This Collection changes to reflect the children of the current rowData, and the current rowData changes to be null. The current rowIndex becomes -1. This method should only be called if isContainer() returns true. DataModel.getRowCount() can be used to get the number of children.


exitContainer

public abstract void exitContainer()
Pops back up to the parent collection. The current rowData becomes the rowData of the parent. This Collection will change to include the children of the new rowData.


getContainerRowKey

public final java.lang.Object getContainerRowKey()
Gets the rowKey of the current row's container row. This implementation calls getContainerRowKey(Object) with the current rowKey.


getAllAncestorContainerRowKeys

public java.util.List<java.lang.Object> getAllAncestorContainerRowKeys(java.lang.Object childRowKey)
Gets the rowkey of each container, starting from the top most container, down to the container of the given child rowKey. The root container (which always has the null rowKey) is not included in this list. The given childRowKey is not included in this list.

Given the following tree structure:

 |-Root1 (rowKey="r1")
 |  |-Folder1 (rowKey="r1f1")
 |  |  |-Node1 (rowKey="r1f1n1")
 
Calling getAllAncestorContainerRowKeys("r1f1n1") returns a List of two items:"r1" and "r1f1", in that order.

Parameters:
childRowKey - identifies the child row.
Returns:
An empty list is returned if the child row is a root row and has no parent containers. Each item in this list is a rowKey and is of type Object. The first rowKey (in this list) is the top most container. The last rowKey is the immediate container of the given childRowKey.

getContainerRowKey

public abstract java.lang.Object getContainerRowKey(java.lang.Object childRowKey)
Gets the rowKey of a given child row's container row.
 |-Root1 (rowKey="r1", containerRowKey=null)
 |  |-Folder1 (rowKey="r1f1", containerRowKey="r1")
 |  |  |-Node1 (rowKey="r1f1n1", containerRowKey="r1f1")
 |  |  |-Node2 (rowKey="r1f1n2", containerRowKey="r1f1")
 

Parameters:
childRowKey - the rowKey of the child row.
Returns:
the rowKey of the container, or null if the child is a root row.

getDepth

public final int getDepth()
Gets the depth of the current row within this tree hierarchy.
This implementation simply calls getDepth(Object) with the current rowKey.


getDepth

public int getDepth(java.lang.Object rowKey)
Gets the depth of the given row within the tree hierarchy. The depth is a measure of how far the given row is from its top-level container row. Root-level rows have a depth of zero. All the immediate children of each root row have a depth of one.
 |-Root1 (depth=0)
 |  |-Folder1 (depth=1)
 |  |  |-Node1 (depth=2)
 |  |  |-Node2 (depth=2)
 |  |  |-Node3 (depth=2)
 |  |-Folder2 (depth=1)
 |-Root2 (depth=0)
 



Copyright © 2001-2008 The Apache Software Foundation. All Rights Reserved.