Showing posts with label ADF Tree. Show all posts
Showing posts with label ADF Tree. Show all posts

Friday, 21 October 2011

ADF Tree : Row Disclosure Listener which expands below the disclosed node

I recently had the scenario where more than one level of a tree node had to be expanded on the disclosure of a particular tree node.

For example, say you have the below tree:
-A
-B
  - B1
  - B2
    - B2a
    - B2b
  - B3
-C
then, on the disclosure of tree node B you would want all the children (B1, B2, B3, B2a, B2b) of tree node B to be expanded.

I've done it as follow. I've added the following property to my ADF Tree:
rowDisclosureListener="#{treeBean.discloseTreeNodeChildren}" 

Then I implemented the referenced method in my "treeBean" backing bean. It assumes a tree binding called: "tree." See the listing below:
public void discloseTreeNodeChildren(RowDisclosureEvent event) {
    RowKeySet addedKeys = event.getAddedSet();
    Iterator addedIt = addedKeys.iterator();
    if(addedIt.hasNext()) {
        Object addedKey = addedIt.next();
        TreeModel treeModel = (TreeModel) this.tree.getValue();
        JUCtrlHierNodeBinding nodeBinding = (JUCtrlHierNodeBinding)
               treeModel.getRowData(addedKey);
        String isLeaf = (String) nodeBinding.getAttribute("isLeaf");
       
          // you have to have a condition to break the series of disclosure events!!
        if(!(new Boolean(isLeaf))) {
            TreeUtility.expandAllNodes(nodeBinding, this.tree.getDisclosedRowKeys(), 0, 1);
            AdfFacesContext.getCurrentInstance().addPartialTarget(this.tree);
        }
    }
}

Now the utility method called: "expandAllNodes()" I've implemented as such:
protected static void expandAllNodes(JUCtrlHierNodeBinding nodeBinding, RowKeySet
          disclosedKeys) {   
    List<JUCtrlHierNodeBinding> childNodes = (List<JUCtrlHierNodeBinding>)
        nodeBinding.getChildren();     
    ArrayList newKeys = new ArrayList();
    if(childNodes != null) {
        for(JUCtrlHierNodeBinding node : childNodes) {           
            newKeys.add(node.getKeyPath());
            // recursive call to the method expandAllNodes()         
            expandAllNodes(node, disclosedKeys);
        }
    }
    disclosedKeys.addAll(newKeys);     

}
A handy addition to the utility method above is to add currentLevel and targetLevel integers in order to apply a boundary to the expansion of nodes. This gives the ability to only expand n levels below the disclosed node...comes in handy in those "big oak trees!!" :-)

Thursday, 28 July 2011

ADF Tree : Setting Bind Parameters on a hierarchy of View Objects in your backing bean code

I was faced with the scenario of a hierarchical View Object defined in a View Link in order to make use of it in an ADF Tree component. The re-used/recursive View Object has bind parameters which are required and have to be set.

It was easy enough to get to the "parent" View Object in the hierarchy by using the Iterator binding as in the code sniplet below:

// get reference to the parent view object via the iterator binding
DCIteratorBinding iter = ADFUtils.findIterator("IteratorName");
ViewObject parentVO = iter.getViewObject();

// set bind parameter value on parent view object
parentVO.ensureVariableManager().setVariableValue("BindParameterName",      "BindParameterValue");

However, the "child" View Object in the hierarchy remained without its bind parameters set. Eventually, I got to the following solution (PLEASE NOTE: You have to use the destination view object accessor name as it is defined in the View Link you've created):

// get reference to the child view object via the parent view object binding
ViewObject childVO = ADFUtils.getChildViewObjectFromParent(parentVO, "ChildVOAccessorName");

// set bind parameter value on child view oibject
childVO.ensureVariableManager().setVariableValue("BindParameterName", "BindParameterValue");

The ADFUtils utility methods used above were implemented as follow:

public static DCIteratorBinding findIterator(String name) {
    DCIteratorBinding iter = getDCBindingContainer().findIteratorBinding(name);
    if(iter == null) {
      throw new RuntimeException("Iterator '" + name + "' not found");
    }
    return iter;
}

public static ViewObject getChildViewObjectFromParent(ViewObject parentVO, String childAccessorName) {
    AttributeDef attrDef = parentVO.findAttributeDef(childAccessorName);
    if(attrDef == null) {
      throw new RuntimeException("Attribute Definition '" + childAccessorName + "' not found on parent view object");
    }   
    return attrDef.getAccessorVO(parentVO);
}