Saturday, February 27, 2010

How To Traverse ADF Tree

If you are thinking how to delete nodes from ADF tree, there is Frank Nimphius blog post - ADF Faces RC: Single row / Multi row delete from a tree component. However, Frank says that his blog entry is still a raw diamond and needs some polishing. In his example, if you remove root node, all child nodes still will remain in database. This means tree hierarchy will be broken. I decided to polish raw diamond, to describe how you can traverse ADF tree and remove all selected nodes together with children.

Download sample application - TreeTraversal.zip. This sample implements ADF tree traversal algorithm without recursion. ADF tree component provides Java API to get parent node for current node, this allows to avoid recursion.

I have defined tree binding and created action listener method, where tree traversal code is implemented:


Tree traversal algorithm scans selected nodes, and walks through all child nodes. When it reaches last child in tree branch, it returns back until it finds next child sibling. At the end it will return to the initial node, where tree traversal was started - root node.

I'm using two helper methods, one to get first child and second to get next sibling. Its ADF tree Java API, nothing special:


Let's see how it works. We can select multiple nodes, children of all those selected nodes will be traversed:


I intentionally commented node.getRow().remove; in my sample, just to prevent you from all nodes deletion by mistake :-) Traversed nodes are reported in the log:


It starts from first selection and walks from 100 to 102, reports parent node 90 and goes to second selection, walks through and reports parent node 110.

You can select such node, which contains multiple branches:


Tree traversal will work as well - it will enter first branch, traverse it and move to next sibling branch. Whole report for previous selection:


If you are planning to traverse large tree branches, you should increase ADF tree RangeSize property value. Default value is 25, means it will keep only 25 nodes in memory, so you will not be able to traverse whole hierarchy. With default RangeSize it will render large tree hierarchy structures pretty slow, I recommend to increase it to something at least 500:


It will keep 500 nodes in memory, and will allow such tree operations as Expand All Nodes and Expand All Nodes Below to perform faster.

16 comments:

Rathis said...

Hi Andrejus,
In my task flow, i need to delete a container but container hierarchy is container->pallet->pallet->case.

So when i delete the container then it has to delete the whole hierarchy, but when i tried with ur code its throwing null pointer exception and its deleting only pallet row but when i commented the remove(node.getRow().remove(); and root.getRow().remove();) its working fine & in the log window its displaying the hierarchy details correctly.

If i place the remove then its giving NULL pointer exception.

can you please help and i am new to ADF & this is my first task in project.

my email id is : kmsivanadiyan@gmail.com

Andrejus Baranovskis said...

Hi,

You need to make sure, it will mark as removed only child nodes first and then move to parent.

I will update it, when I will get time.

Regards,
Andrejus

Rathis said...

Andrejus,

Can you please assist me.

Thanks, Sivanadiyan

Anonymous said...

Can you pls fix the case when deleting a parent node?

Thanks Andrejus.

Vinitha said...

Hi Andrejus,
I ran your app.. it was running fine... I am working with tree for first time and i noticed certain buttons like detach, show as top buttons avail in treetable is not avail in tree... is it poss to add tat component in tree as well, if so can u tel me how and can u guide me thro some samples by which i can know all features and operations that can be done on tree..


My id ... vini.gopal@gmail.com

Gopal Rao said...

Hi Vinitha,

The components "Detach", "Show as top" etc come from the PanelCollection component. Unfortunately, the button "Detach" is available only for TABLE and TREETABLE.

Oracle has a really very helpful demo running at the following location:

http://jdevadf.oracle.com/adf-richclient-demo/faces/components

You could learn quite a bit from this site. It gives you the link to the page source (not as an HTML, but as the JSPX page ) which will describe how the page is laid out.

Regards
Gopal

Tomo said...

Hi Andrejus,

Thank you for this solution. I implemented it to my application, and it was working fine (I thought) with 11.1.1.3. Now we upgraded to 11.1.1.4 and I encountered an issue. (I am not sure if it is related to the upgrade or not. It could be me causing this problem.)
The issue is that it does not delete grand children nodes. The tree structure displays correctly in my tree table. When I select a parent node and then try to delete it and its all descendants, it just deletes the direct child and the parent node itself. When I debug, getChildren() returns null for the child node though the child node has several grand children nodes. The funny thing is that when I select the child node and try to delete it, getChildren() returns the correct number of elements.
Do you have any suggestions for me? Thank you for your help in advance!

Andrejus Baranovskis said...

Hi,

Latest public release is 11.1.1.3. I cant test with internal 11.1.1.4

Regards,
Andrejus

Tomo said...

Thank you, Andrejus. I tried your sample program in 11.1.1.4.0 and it is working fine. So it must be the issue cause by me. :(
My VOs and VLs look fine to me. I probably try to re-create the tree table....
Please let me know if you think of anything I can check.
Again, I appreciate your sample code.

Priya said...

Hi Andrejus,
I am using drag and drop between two af:tree.

I have two trees in my page ,one is having dragSource and another one is having dropTarget.Both the trees are initially expanded.In the drop listener of the drop target i have called a method in the backing bean.In this method i have written my business logic to insert a row in the target tree.
When i run this code in JDeveloper 11.1.1.3 Drag and drop is working very well and target tree shows the newly inserted row after the drop without any problem.

But when i run the same code in JDeveloper 11.1.1.4,the target tree is not refreshing properly.it is not showing the newly inserted record.Instead it is showing the loading symbol and "Fetching data...." for long time.
If i try to collapse and expand the whole tree then it shows the newly inserted record.

My drag source and drop target trees are:

<af:tree value="#{bindings.MenuOptionsView1.treeModel}" var="node"
rowSelection="single" id="t3" partialTriggers="::ctb1"
binding="#{myWorkflow.menuOptionsTree}">
<af:dragSource actions="COPY" discriminant="DnDDemoModel"/>
<f:facet name="nodeStamp">
<af:outputText value="#{node.OptionText}" id="ot1"/>
</f:facet>
</af:tree>

<af:tree value="#{bindings.EditWorkflowNodesView1.treeModel}" var="node"
selectionListener="#{bindings.EditWorkflowNodesView1.treeModel.makeCurrent}"
rowSelection="single" id="t2" initiallyExpanded="true"
binding="#{myWorkflow.editWorkflowNodesTree}"
partialTriggers="::cb2">
<af:collectionDropTarget actions="COPY" modelName="DnDDemoModel"
dropListener="#{myWorkflow.editWorkflow}"/>
<f:facet name="nodeStamp">
<af:outputText value="#{node.DisplayText}" id="ot2"
styleClass="treeNode"/>
</f:facet>
</af:tree>

I tried to refresh the tree in many ways but i was not able to reach my target.

I am not able to find that why it is not working specifically in JDeveloper 11.1.1.4.Please throw some light on this problem.

Thanks,
Priya.

subu said...

thanks a lot..

thanks a lot..

again a thanks. i achieved task.

with help of your idea.

Fonz D said...

Hello Andrejus,

Is there a way to progrmatically add a node to ADF Tree. Also, is there a way to progmatically show/hide a node(including its subtree) in ADF Tree.

Andrejus Baranovskis said...

Yes - you can do it programmatically, no problem.

Andrejus

Eusebio Garcia said...

Hello, i have one problem to resolve. I have a tree that is a n level tree, and in design time i can't know how deep are going to be my tree. I make it from one view object, i try to override the createViewLinkAccessorRS() method like Jobinesh said in his blog and don't work. The tree are going to be very big, so i need that the user search on the hole tree, how can i search over the hole tree using the af:query and treetable? Sorry for my English...Regards

Eusebio Garcia said...

Hello, i have one problem to resolve. I have a tree that is a n level tree, and in design time i can't know how deep are going to be my tree. I make this (db)view to query the oracle DB

SELECT ID, FULLCODE,ID_PARENT
FROM my_table
CONNECT BY PRIOR ID = ID_PARENT
START WITH ID_PARENT IS NULL
ORDER BY FULLCODE
I make an entity object using this view and i make a view object using that entity. I construct the tree using only one view object and the View link to connect that view object himself, everything is fine, except the search, because only search on the root elements of the tree, i try to override the createViewLinkAccessorRS() method like Jobinesh said in his blog [http://jobinesh.blogspot.com/2010/01/search-by-child-attributes-on-tree.html] and don't work, because don't search the child nodes, even if i drop the criteria from the child view object instance. The tree are going to be very big, so i need that the user search over the hole tree. The question is, how can i search over the hole tree using the af:query and treetable? And a plus, if i can get the hierarchy when the user search, that will be even better. Sorry for my English...Regards and thanks in advance.

Anonymous said...

Hi Andrejus,

The sample program work with 11.1.1.7, but no with 11.1.2.3:
java.lang.NullPointerException
ADF_FACES-60097, ADF_FACES-60096.

Can you help me?

Regards,
Theo.