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 }
|