# TreeController.jpf Sample

This topic inludes the source code for the TreeController.jpf Sample.

## Sample Location

This sample is located in the following directory in your WebLogic Workshop installation:

BEA_HOME/weblogic81/samples/workshop/SamplesApp/WebApp/tagSamples/netui/tree_dynamic/

## Sample Source Code

`001 package tagSamples.netui.tree_dynamic; 002 003 import com.bea.wlw.netui.pageflow.PageFlowController; 004 import com.bea.wlw.netui.pageflow.Forward; 005 import com.bea.wlw.netui.pageflow.FormData; 006 007 import com.bea.wlw.netui.tags.html.TreeNode; 008 import com.bea.xml.XmlObject; 009 import java.io.File; 010 import javax.xml.parsers.*; 011 012 /** 013 * This sample demonstrates how to build a navigation tree dynamically from an arbitrary XML document. 014 * 015 * Any XML document can be consumed by this controller and displayed as a set of links, 016 * arranged as an expandable/collapsible tree of nodes. 017 * 018 * The XML document is parsed (by the makeTree() method below) and from 019 * the parsed data a set of TreeNodes is constructed (by calling the TreeNode API). 020 * TreeNodes are the server-side representations of <netui:node> tags. 021 * The TreeNodes are displayed by data binding the TreeNodes to a <netui:tree> tag (on tree.jsp). 022 * 023 * Any attributes in the XML docuument can be parsed for href and label content. 024 * If an element cannot be parsed for url and label content, then 025 * a dummy TreeNode is created for that element. 026 * 027 * @jpf:controller 028 * @jpf:view-properties view-properties:: 029 * <!-- This data is auto-generated. Hand-editing this section is not recommended. --> 030 * <view-properties> 031 * <pageflow-object id="pageflow:/tagSamples/netui/tree_dynamic/treeController.jpf"/> 032 * <pageflow-object id="action:treeState.do"> 033 * <property value="80" name="x"/> 034 * <property value="160" name="y"/> 035 * </pageflow-object> 036 * <pageflow-object id="action:begin.do"> 037 * <property value="80" name="x"/> 038 * <property value="60" name="y"/> 039 * </pageflow-object> 040 * <pageflow-object id="action-call:@page:tree.jsp@#@action:treeState.do@"> 041 * <property value="204,160,160,116" name="elbowsX"/> 042 * <property value="152,152,141,141" name="elbowsY"/> 043 * <property value="West_1" name="fromPort"/> 044 * <property value="East_0" name="toPort"/> 045 * </pageflow-object> 046 * <pageflow-object id="page:tree.jsp"> 047 * <property value="240" name="x"/> 048 * <property value="160" name="y"/> 049 * </pageflow-object> 050 * <pageflow-object id="page:frameSet.jsp"> 051 * <property value="240" name="x"/> 052 * <property value="60" name="y"/> 053 * </pageflow-object> 054 * <pageflow-object id="forward:path#tree#tree.jsp#@action:treeState.do@"> 055 * <property value="116,160,160,204" name="elbowsX"/> 056 * <property value="152,152,141,141" name="elbowsY"/> 057 * <property value="East_1" name="fromPort"/> 058 * <property value="West_0" name="toPort"/> 059 * <property value="tree" name="label"/> 060 * </pageflow-object> 061 * <pageflow-object id="forward:path#begin#frameSet.jsp#@action:begin.do@"> 062 * <property value="116,160,160,204" name="elbowsX"/> 063 * <property value="52,52,52,52" name="elbowsY"/> 064 * <property value="East_1" name="fromPort"/> 065 * <property value="West_1" name="toPort"/> 066 * <property value="begin" name="label"/> 067 * </pageflow-object> 068 * </view-properties> 069 * :: 070 */ 071 public class treeController extends PageFlowController 072 { 073 /** 074 * This TreeNode object is the top-level parent node of the tree. 075 * The makeTree() method constructs and adds children TreeNodes to this top level node. 076 * 077 * The tree is displayed by data binding the top-level node (along with its 078 * children branch nodes) to a <netui:tree> tag (on tree.jsp). 079 */ 080 public TreeNode _rootNode = null; 081 082 public void onCreate() throws Exception 083 { 084 //System.out.println(getClass().getResource("/content/toc1.xml").getFile()); 085 086 //String beaHomePath = weblogic.Home.getFile().getParentFile().toString() + "/samples/workshop/SamplesApp/WebApp/"; 087 String beaHomePath = weblogic.Home.getPath().replaceAll("/server", "/samples/workshop/SamplesApp/WebApp/"); 088 System.out.println(beaHomePath); 089 090 _rootNode = this.makeTree( 091 "http://localhost:7001/WebApp/tagSamples/netui/tree_dynamic/content/", 092 beaHomePath + "tagSamples/netui/tree_dynamic/toc.xml", 093 "url", 094 "label", 095 true); 096 } 097 098 /** 099 * Parses an XML docuemnt and creates a set of links, arranging them as an expandable and collapsible tree 100 * with the same shape as the XML document. 101 * 102 * The labelAttribute and hrefAttribute parameters specify the attributes in the XML document that 103 * hold the label and href content. 104 * 105 * The links are constructed from TreeNode objects, the server-side representations of <netui:node> tags. 106 * The method returns a single TreeNode containing the remaining TreeNode as children. 107 * 108 * @param String rootHref The url fragment to prepend to each links' href attribute. 109 * @param String tocFile Location of the toc.xml file. A link will be made for each 110 * element in the file. 111 * @param String hrefAttribute The name of the attribute where the href content can be found. 112 * @param String labelAttribute The name of the attribute where the label content can be found. 113 * @param boolean nodesInit Whether the nodes should be initially open or closed. 114 * 115 * @return TreeNode The top-level node containing all the child, branch nodes. 116 */ 117 public TreeNode makeTree(String rootHref, String tocFile, String hrefAttribute, String labelAttribute, boolean nodesInit) 118 throws Exception 119 { 120 // Get the toc.xml file 121 File fl = new File(tocFile); 122 // Parse it as an org.w3c.doc.Document 123 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 124 factory.setNamespaceAware(true); 125 DocumentBuilder parser = factory.newDocumentBuilder(); 126 org.w3c.dom.Document document = parser.parse(fl); 127 // Get the list of Nodes. 128 org.w3c.dom.NodeList nodeList = document.getElementsByTagName("*"); 129 130 // Make an Array of TreeNode, each TreeNode has the label and url of the nodes in toc.xml. 131 // No parent information is added to the TreeNodes yet. 132 int length = nodeList.getLength(); 133 TreeNode[] treeNodeArr = new TreeNode[length]; 134 for(int i = 0; i<length; i++) 135 { 136 // Try to make a TreeNode based on the org.w3c.dom.Node. 137 // If the node does not have both "label" and "url" attributes... 138 try 139 { 140 treeNodeArr[i] = new TreeNode( 141 null, 142 nodeList.item(i).getAttributes().getNamedItem(labelAttribute).getNodeValue(), 143 null, 144 rootHref 145 + nodeList.item(i).getAttributes().getNamedItem(hrefAttribute).getNodeValue(), 146 "contentFrame", 147 nodesInit); 148 } 149 catch(Exception e) 150 { 151 // ...make a dummy TreeNode 152 treeNodeArr[i] = new TreeNode( 153 null, 154 "[-label-]", 155 null, 156 "[-href-]", 157 "contentFrame", 158 nodesInit); 159 System.out.println("<Warning> Could not parse " + labelAttribute + " and " + hrefAttribute 160 + " attributes in node: <" + nodeList.item(i).getNodeName() + ">, #" + i); 161 } 162 } 163 164 // Make a parent mapping: parentMap[child_i] = parent_k. 165 int[] parentMap = new int[length]; 166 // for each Node... 167 for(int i = 0; i<length; i++) 168 { 169 // ... find its parent (loop goes from 0 - i for the sake of efficiency, no parent is found after the child) 170 org.w3c.dom.Node parentNode = nodeList.item(i).getParentNode(); 171 for(int k = 0; k<i; k++) 172 { 173 if(parentNode == nodeList.item(k)) 174 { 175 parentMap[i] = k; 176 } 177 } 178 } 179 180 // Assign parentage to the Array of TreeNodes. 181 // The top-level TreeNode is made the rootNode. 182 TreeNode rootNode = treeNodeArr[0]; 183 // Apply parent map to the TreeNode Array 184 for(int i=1; i<length; i++) 185 { 186 if(treeNodeArr[parentMap[i]] != null) 187 { 188 treeNodeArr[parentMap[i]].addChild(treeNodeArr[i]); 189 } 190 } 191 192 return rootNode; 193 } 194 195 /** 196 * Handles the state of the tree when a a link is clicked. 197 * 198 * @jpf:action 199 * @jpf:forward name="tree" path="tree.jsp" 200 */ 201 public Forward treeState() 202 { 203 String nodeSel = null; 204 String nodeExpanded = null; 205 206 /* 207 * Handles expansion / collapse of a tree node. 208 * 209 * Get the String name of the content node or the expandable/collapsable node 210 * selected by the user. 211 */ 212 nodeSel = getRequest().getParameter(TreeNode.SELECTED_NODE); 213 nodeExpanded = getRequest().getParameter(TreeNode.EXPAND_NODE); 214 215 /* 216 * If the user selected an expandable/collapsable node... 217 */ 218 if (nodeExpanded != null) 219 { 220 /* 221 * ...then get the TreeNode object based on the node's String name... 222 */ 223 TreeNode node = _rootNode.findNode(nodeExpanded); 224 if (node != null) 225 { 226 /* 227 * ...and reverse the expand/collapse state of the node. 228 * (I.e. if the node was previously collapsed, then expand it; 229 * if it was previously expanded, then collapse it.) 230 */ 231 node.setExpanded(!node.isExpanded()); 232 233 } 234 /* 235 * When a node is selected for expansion/collapse, display changes only in the 236 * navigation frame. 237 */ 238 return new Forward("tree"); 239 } 240 241 return new Forward(nodeSel); 242 } 243 244 /** 245 * @jpf:action 246 * @jpf:forward name="begin" path="frameSet.jsp" 247 */ 248 public Forward begin() 249 { 250 return new Forward("begin"); 251 } 252 253 254 }`