Monday, September 29, 2008

Determining RichTree node hierarchy type with tree node selection or row disclosure

There is plenty of documentation available demonstrating selection handlers or row disclosure handlers for a node of an ADF RichTree. However, information on manipulation of the node data in these handlers is sketchy to come by. For a RichTree defined based on hierarchical data-binding with ADF BC objects, a specific use case is presented here: How to determine the node hierarchy type of a selected or expanded/contracted node?

For a RichTree definition such as below, assuming myFancyBean maps to a bean MyFancyBean.java, sample code for solving the use case above is presented. With a declarative databinding approach, an EL expression such as #{node.hierType.viewDefName} evaluates the node hierarchy type. However, such EL expression when evaluated inside a Java selection/row disclosure handler would not return the same result, due to not having appropriate context for the variable "node".

<af:tree
 value="#{bindings.myVO.treeModel}"
 var="node" rowselection="single" displayrow="selected"
 rowdisclosurelistener="{myFancyBean.handleRowDisclosure}">
Corresponding code in a Java handler for determining node hierarchy type is presented below. For the purpose of getting the point across, this code assumes that a tree node is being expanded. Tree node contraction is not handled in this code, however equivalent code can easily be written for handling contraction by using getRemovedSet instead of getAddedSet.
package com.whatever;

import oracle.adf.view.rich.component.rich.data.RichTree;

import org.apache.myfaces.trinidad.event.RowDisclosureEvent;
import org.apache.myfaces.trinidad.model.RowKeySet;

import oracle.adfinternal.view.faces.model.binding.FacesCtrlHierNodeBinding;

public class MyFancyBean {
  public MyFancyBean() {

  }


  //.....

  public void handleRowDisclosure(RowDisclosureEvent rowDisclosureEvent) throws Exception {
    Object rowKey = null;

    FacesCtrlHierNodeBinding rowData = null;
    String viewDefName = null;
    RichTree tree = (RichTree)rowDisclosureEvent.getSource();
    RowKeySet rks = rowDisclosureEvent.getAddedSet();
    if (rks != null) {
       int setSize = rks.size();
       if (setSize > 1) {
           throw new Exception("Unexpected multiple row disclosure row sets");
       }

       if (setSize == 0)
           return;
       rowKey = rks.iterator().next();
       tree.setRowKey(rowKey);
       rowData = (FacesCtrlHierNodeBinding)tree.getRowData();

       if (rowData.getHierTypeBinding() != null) {
           viewDefName =
                   rowData.getHierTypeBinding().getStructureDefName();
       }
    }
  }
}

1 comment:

Sachin Gupta said...

Though it may not be intentional, but - FacesCtrlHierNodeBinding is an internal class and should not be used, rather JUCtrlHierNodeBinding should be the one to be used.

Thanks
Sachin