KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > webapp > admin > TreeControlTag


1 /*
2  * Copyright 2001,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17
18 package org.apache.webapp.admin;
19
20
21 import java.io.IOException JavaDoc;
22 import java.net.URLEncoder JavaDoc;
23 import javax.servlet.http.HttpServletResponse JavaDoc;
24 import javax.servlet.jsp.JspException JavaDoc;
25 import javax.servlet.jsp.JspWriter JavaDoc;
26 import javax.servlet.jsp.PageContext JavaDoc;
27 import javax.servlet.jsp.tagext.TagSupport JavaDoc;
28
29
30 /**
31  * <p>JSP custom tag that renders a tree control represented by the
32  * <code>TreeControl</code> and <code>TreeControlNode</code> classes.
33  * This tag has the following user-settable attributes:</p>
34  * <ul>
35  * <li><strong>action</strong> - Hyperlink to which expand/contract actions
36  * should be sent, with a string "<code>{name}</code> marking where
37  * the node name of the affected node should be included.</li>
38  * <li><strong>images</strong> - Name of the directory containing the images
39  * for our icons, relative to the page including this tag. If not
40  * specified, defaults to "images".</li>
41  * <li><strong>scope</strong> - Attribute scope in which the <code>tree</code>
42  * attribute is to be found (page, request, session, application). If
43  * not specified, the attribute is searched for in all scopes.</li>
44  * <li><strong>style</strong> - CSS style <code>class</code> to be applied
45  * to be applied to the entire rendered output of the tree control.
46  * If not specified, no style class is applied.</li>
47  * <li><strong>styleSelected</strong> - CSS style <code>class</code> to be
48  * applied to the text of any element that is currently selected. If not
49  * specified, no additional style class is applied.</li>
50  * <li><strong>styleUnselected</strong> - CSS style <code>class</code> to be
51  * applied to the text of any element that is not currently selected.
52  * If not specified, no additional style class is applied.</li>
53  * <li><strong>tree</strong> - Attribute name under which the
54  * <code>TreeControl</code> bean of the tree we are rendering
55  * is stored, in the scope specified by the <code>scope</code>
56  * attribute. This attribute is required.</li>
57  * </ul>
58  *
59  * <strong>FIXME</strong> - Internationalize the exception messages!
60  *
61  * @author Craig R. McClanahan
62  * @version $Revision: 1.5 $ $Date: 2004/12/02 03:49:01 $
63  */

64
65 public class TreeControlTag extends TagSupport JavaDoc {
66
67
68     /**
69      * The default directory name for icon images.
70      */

71     static final String JavaDoc DEFAULT_IMAGES = "images";
72
73
74     /**
75      * The names of tree state images that we need.
76      */

77     static final String JavaDoc IMAGE_HANDLE_DOWN_LAST = "handledownlast.gif";
78     static final String JavaDoc IMAGE_HANDLE_DOWN_MIDDLE = "handledownmiddle.gif";
79     static final String JavaDoc IMAGE_HANDLE_RIGHT_LAST = "handlerightlast.gif";
80     static final String JavaDoc IMAGE_HANDLE_RIGHT_MIDDLE = "handlerightmiddle.gif";
81     static final String JavaDoc IMAGE_LINE_LAST = "linelastnode.gif";
82     static final String JavaDoc IMAGE_LINE_MIDDLE = "linemiddlenode.gif";
83     static final String JavaDoc IMAGE_LINE_VERTICAL = "linevertical.gif";
84
85
86     // ------------------------------------------------------------- Properties
87

88
89     /**
90      * The hyperlink to be used for submitting requests to expand and
91      * contract tree nodes. The placeholder "<code>{name}</code>" will
92      * be replaced by the <code>name</code> property of the current
93      * tree node.
94      */

95     protected String JavaDoc action = null;
96
97     public String JavaDoc getAction() {
98         return (this.action);
99     }
100
101     public void setAction(String JavaDoc action) {
102         this.action = action;
103     }
104
105
106     /**
107      * The name of the directory containing the images for our icons,
108      * relative to the page including this tag.
109      */

110     protected String JavaDoc images = DEFAULT_IMAGES;
111
112     public String JavaDoc getImages() {
113         return (this.images);
114     }
115
116     public void setImages(String JavaDoc images) {
117         this.images = images;
118     }
119
120
121     /**
122      * The name of the scope in which to search for the <code>tree</code>
123      * attribute. Must be "page", "request", "session", or "application"
124      * (or <code>null</code> for an ascending-visibility search).
125      */

126     protected String JavaDoc scope = null;
127
128     public String JavaDoc getScope() {
129         return (this.scope);
130     }
131
132     public void setScope(String JavaDoc scope) {
133         if (!"page".equals(scope) &&
134             !"request".equals(scope) &&
135             !"session".equals(scope) &&
136             !"application".equals(scope))
137             throw new IllegalArgumentException JavaDoc("Invalid scope '" +
138                                                scope + "'");
139         this.scope = scope;
140     }
141
142
143     /**
144      * The CSS style <code>class</code> to be applied to the entire tree.
145      */

146     protected String JavaDoc style = null;
147
148     public String JavaDoc getStyle() {
149         return (this.style);
150     }
151
152     public void setStyle(String JavaDoc style) {
153         this.style = style;
154     }
155
156
157     /**
158      * The CSS style <code>class</code> to be applied to the text
159      * of selected nodes.
160      */

161     protected String JavaDoc styleSelected = null;
162
163     public String JavaDoc getStyleSelected() {
164         return (this.styleSelected);
165     }
166
167     public void setStyleSelected(String JavaDoc styleSelected) {
168         this.styleSelected = styleSelected;
169     }
170
171
172     /**
173      * The CSS style <code>class</code> to be applied to the text
174      * of unselected nodes.
175      */

176     protected String JavaDoc styleUnselected = null;
177
178     public String JavaDoc getStyleUnselected() {
179         return (this.styleUnselected);
180     }
181
182     public void setStyleUnselected(String JavaDoc styleUnselected) {
183         this.styleUnselected = styleUnselected;
184     }
185
186
187     /**
188      * The name of the attribute (in the specified scope) under which our
189      * <code>TreeControl</code> instance is stored.
190      */

191     protected String JavaDoc tree = null;
192
193     public String JavaDoc getTree() {
194         return (this.tree);
195     }
196
197     public void setTree(String JavaDoc tree) {
198         this.tree = tree;
199     }
200
201
202     // --------------------------------------------------------- Public Methods
203

204
205     /**
206      * Render this tree control.
207      *
208      * @exception JspException if a processing error occurs
209      */

210     public int doEndTag() throws JspException JavaDoc {
211
212         TreeControl treeControl = getTreeControl();
213         JspWriter JavaDoc out = pageContext.getOut();
214         try {
215             out.print
216                 ("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"");
217             if (style != null) {
218                 out.print(" class=\"");
219                 out.print(style);
220                 out.print("\"");
221             }
222             out.println(">");
223             int level = 0;
224             TreeControlNode node = treeControl.getRoot();
225             render(out, node, level, treeControl.getWidth(), true);
226             out.println("</table>");
227         } catch (IOException JavaDoc e) {
228             throw new JspException JavaDoc(e);
229         }
230
231         return (EVAL_PAGE);
232
233     }
234
235
236     /**
237      * Release all state information set by this tag.
238      */

239     public void release() {
240
241         this.action = null;
242         this.images = DEFAULT_IMAGES;
243         this.scope = null;
244         this.style = null;
245         this.styleSelected = null;
246         this.styleUnselected = null;
247         this.tree = null;
248
249     }
250
251
252     // ------------------------------------------------------ Protected Methods
253

254
255     /**
256      * Return the <code>TreeControl</code> instance for the tree control that
257      * we are rendering.
258      *
259      * @exception JspException if no TreeControl instance can be found
260      */

261     protected TreeControl getTreeControl() throws JspException JavaDoc {
262
263         Object JavaDoc treeControl = null;
264         if (scope == null)
265             treeControl = pageContext.findAttribute(tree);
266         else if ("page".equals(scope))
267             treeControl =
268                 pageContext.getAttribute(tree, PageContext.PAGE_SCOPE);
269         else if ("request".equals(scope))
270             treeControl =
271                 pageContext.getAttribute(tree, PageContext.REQUEST_SCOPE);
272         else if ("session".equals(scope))
273             treeControl =
274                 pageContext.getAttribute(tree, PageContext.SESSION_SCOPE);
275         else if ("application".equals(scope))
276             treeControl =
277                 pageContext.getAttribute(tree, PageContext.APPLICATION_SCOPE);
278         if (treeControl == null)
279             throw new JspException JavaDoc("Cannot find tree control attribute '" +
280                                    tree + "'");
281         else if (!(treeControl instanceof TreeControl))
282             throw new JspException JavaDoc("Invalid tree control attribute '" +
283                                    tree + "'");
284         else
285             return ((TreeControl) treeControl);
286
287     }
288
289
290     /**
291      * Render the specified node, as controlled by the specified parameters.
292      *
293      * @param out The <code>JspWriter</code> to which we are writing
294      * @param node The <code>TreeControlNode</code> we are currently
295      * rendering
296      * @param level The indentation level of this node in the tree
297      * @param width Total displayable width of the tree
298      * @param last Is this the last node in a list?
299      *
300      * @exception IOException if an input/output error occurs
301      */

302     protected void render(JspWriter JavaDoc out, TreeControlNode node,
303                           int level, int width, boolean last)
304         throws IOException JavaDoc {
305
306         HttpServletResponse JavaDoc response =
307             (HttpServletResponse JavaDoc) pageContext.getResponse();
308     
309         // if the node is root node and the label value is
310
// null, then do not render root node in the tree.
311

312         if ("ROOT-NODE".equalsIgnoreCase(node.getName()) &&
313         (node.getLabel() == null)) {
314             // Render the children of this node
315
TreeControlNode children[] = node.findChildren();
316             int lastIndex = children.length - 1;
317             int newLevel = level + 1;
318             for (int i = 0; i < children.length; i++) {
319                 render(out, children[i], newLevel, width, i == lastIndex);
320             }
321             return;
322         }
323         
324         // Render the beginning of this node
325
out.println(" <tr valign=\"middle\">");
326
327         // Create the appropriate number of indents
328
for (int i = 0; i < level; i++) {
329             int levels = level - i;
330             TreeControlNode parent = node;
331             for (int j = 1; j <= levels; j++)
332                 parent = parent.getParent();
333             if (parent.isLast())
334                 out.print(" <td></td>");
335             else {
336                 out.print(" <td><img SRC=\"");
337                 out.print(images);
338                 out.print("/");
339                 out.print(IMAGE_LINE_VERTICAL);
340                 out.print("\" alt=\"\" border=\"0\"></td>");
341             }
342             out.println();
343         }
344
345         // Render the tree state image for this node
346

347         // HACK to take into account special characters like = and &
348
// in the node name, could remove this code if encode URL
349
// and later request.getParameter() could deal with = and &
350
// character in parameter values.
351
String JavaDoc encodedNodeName = URLEncoder.encode(node.getName(),TomcatTreeBuilder.URL_ENCODING);
352
353         String JavaDoc action = replace(getAction(), "{name}", encodedNodeName);
354
355         
356         String JavaDoc updateTreeAction =
357             replace(getAction(), "tree={name}", "select=" + encodedNodeName);
358         updateTreeAction =
359             ((HttpServletResponse JavaDoc) pageContext.getResponse()).
360             encodeURL(updateTreeAction);
361
362         out.print(" <td>");
363         if ((action != null) && !node.isLeaf()) {
364             out.print("<a HREF=\"");
365             out.print(response.encodeURL(action));
366             out.print("\">");
367         }
368         out.print("<img SRC=\"");
369         out.print(images);
370         out.print("/");
371         if (node.isLeaf()) {
372             if (node.isLast())
373                 out.print(IMAGE_LINE_LAST);
374             else
375                 out.print(IMAGE_LINE_MIDDLE);
376             out.print("\" alt=\"");
377         } else if (node.isExpanded()) {
378             if (node.isLast())
379                 out.print(IMAGE_HANDLE_DOWN_LAST);
380             else
381                 out.print(IMAGE_HANDLE_DOWN_MIDDLE);
382             out.print("\" alt=\"close node");
383         } else {
384             if (node.isLast())
385                 out.print(IMAGE_HANDLE_RIGHT_LAST);
386             else
387                 out.print(IMAGE_HANDLE_RIGHT_MIDDLE);
388             out.print("\" alt=\"expand node");
389         }
390         out.print("\" border=\"0\">");
391         if ((action != null) && !node.isLeaf())
392             out.print("</a>");
393         out.println("</td>");
394
395         // Calculate the hyperlink for this node (if any)
396
String JavaDoc hyperlink = null;
397         if (node.getAction() != null)
398             hyperlink = ((HttpServletResponse JavaDoc) pageContext.getResponse()).
399                 encodeURL(node.getAction());
400
401         // Render the icon for this node (if any)
402
out.print(" <td colspan=\"");
403         out.print(width - level + 1);
404         out.print("\">");
405         if (node.getIcon() != null) {
406             if (hyperlink != null) {
407                 out.print("<a HREF=\"");
408                 out.print(hyperlink);
409                 out.print("\"");
410                 String JavaDoc target = node.getTarget();
411                 if(target != null) {
412                     out.print(" target=\"");
413                     out.print(target);
414                     out.print("\"");
415                 }
416                 // to refresh the tree in the same 'self' frame
417
out.print(" onclick=\"");
418                 out.print("self.location.href='" + updateTreeAction + "'");
419                 out.print("\"");
420                 out.print(">");
421             }
422             out.print("<img SRC=\"");
423             out.print(images);
424             out.print("/");
425             out.print(node.getIcon());
426             out.print("\" alt=\"");
427             out.print("\" border=\"0\">");
428             if (hyperlink != null)
429                 out.print("</a>");
430         }
431
432         // Render the label for this node (if any)
433

434         if (node.getLabel() != null) {
435             String JavaDoc labelStyle = null;
436             if (node.isSelected() && (styleSelected != null))
437                 labelStyle = styleSelected;
438             else if (!node.isSelected() && (styleUnselected != null))
439                 labelStyle = styleUnselected;
440             if (hyperlink != null) {
441                 // Note the leading space so that the text has some space
442
// between it and any preceding images
443
out.print(" <a HREF=\"");
444                 out.print(hyperlink);
445                 out.print("\"");
446                 String JavaDoc target = node.getTarget();
447                 if(target != null) {
448                     out.print(" target=\"");
449                     out.print(target);
450                     out.print("\"");
451                 }
452                 if (labelStyle != null) {
453                     out.print(" class=\"");
454                     out.print(labelStyle);
455                     out.print("\"");
456                 }
457                 // to refresh the tree in the same 'self' frame
458
out.print(" onclick=\"");
459                 out.print("self.location.href='" + updateTreeAction + "'");
460                 out.print("\"");
461                 out.print(">");
462             } else if (labelStyle != null) {
463                 out.print("<span class=\"");
464                 out.print(labelStyle);
465                 out.print("\">");
466             }
467             out.print(node.getLabel());
468             if (hyperlink != null)
469                 out.print("</a>");
470             else if (labelStyle != null)
471                 out.print("</span>");
472         }
473         out.println("</td>");
474
475         // Render the end of this node
476
out.println(" </tr>");
477
478         // Render the children of this node
479
if (node.isExpanded()) {
480             TreeControlNode children[] = node.findChildren();
481             int lastIndex = children.length - 1;
482             int newLevel = level + 1;
483             for (int i = 0; i < children.length; i++) {
484                 render(out, children[i], newLevel, width, i == lastIndex);
485             }
486         }
487
488     }
489
490
491     /**
492      * Replace any occurrence of the specified placeholder in the specified
493      * template string with the specified replacement value.
494      *
495      * @param template Pattern string possibly containing the placeholder
496      * @param placeholder Placeholder expression to be replaced
497      * @param value Replacement value for the placeholder
498      */

499     protected String JavaDoc replace(String JavaDoc template, String JavaDoc placeholder,
500                              String JavaDoc value) {
501
502         if (template == null)
503             return (null);
504         if ((placeholder == null) || (value == null))
505             return (template);
506         while (true) {
507             int index = template.indexOf(placeholder);
508             if (index < 0)
509                 break;
510             StringBuffer JavaDoc temp = new StringBuffer JavaDoc(template.substring(0, index));
511             temp.append(value);
512             temp.append(template.substring(index + placeholder.length()));
513             template = temp.toString();
514         }
515         return (template);
516
517     }
518
519
520 }
521
Popular Tags