KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > webapp > taglib > TreeControlTag


1 /*
2  * $Header: /cvsroot/jonas/jonas/src/org/objectweb/jonas/webapp/taglib/TreeControlTag.java,v 1.2 2003/11/12 17:19:38 antonma Exp $
3  * $Revision: 1.2 $
4  * $Date: 2003/11/12 17:19:38 $
5  *
6  * ====================================================================
7  *
8  * The Apache Software License, Version 1.1
9  *
10  * Copyright (c) 2001 The Apache Software Foundation. All rights
11  * reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in
22  * the documentation and/or other materials provided with the
23  * distribution.
24  *
25  * 3. The end-user documentation included with the redistribution, if
26  * any, must include the following acknowlegement:
27  * "This product includes software developed by the
28  * Apache Software Foundation (http://www.apache.org/)."
29  * Alternately, this acknowlegement may appear in the software itself,
30  * if and wherever such third-party acknowlegements normally appear.
31  *
32  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
33  * Foundation" must not be used to endorse or promote products derived
34  * from this software without prior written permission. For written
35  * permission, please contact apache@apache.org.
36  *
37  * 5. Products derived from this software may not be called "Apache"
38  * nor may "Apache" appear in their names without prior written
39  * permission of the Apache Group.
40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  * ====================================================================
54  *
55  * This software consists of voluntary contributions made by many
56  * individuals on behalf of the Apache Software Foundation. For more
57  * information on the Apache Software Foundation, please see
58  * <http://www.apache.org/>.
59  *
60  */

61
62 package org.objectweb.jonas.webapp.taglib;
63
64 import java.io.IOException JavaDoc;
65 import java.net.URLEncoder JavaDoc;
66
67 import javax.servlet.http.HttpServletResponse JavaDoc;
68 import javax.servlet.jsp.JspException JavaDoc;
69 import javax.servlet.jsp.JspWriter JavaDoc;
70 import javax.servlet.jsp.PageContext JavaDoc;
71 import javax.servlet.jsp.tagext.TagSupport JavaDoc;
72
73
74 /**
75  * <p>JSP custom tag that renders a tree control represented by the
76  * <code>TreeControl</code> and <code>TreeControlNode</code> classes.
77  * This tag has the following user-settable attributes:</p>
78  * <ul>
79  * <li><strong>action</strong> - Hyperlink to which expand/contract actions
80  * should be sent, with a string "<code>${node}</code> marking where
81  * the node name of the affected node should be included.</li>
82  * <li><strong>images</strong> - Name of the directory containing the images
83  * for our icons, relative to the page including this tag. If not
84  * specified, defaults to "images".</li>
85  * <li><strong>scope</strong> - Attribute scope in which the <code>tree</code>
86  * attribute is to be found (page, request, session, application). If
87  * not specified, the attribute is searched for in all scopes.</li>
88  * <li><strong>style</strong> - CSS style <code>class</code> to be applied
89  * to be applied to the entire rendered output of the tree control.
90  * If not specified, no style class is applied.</li>
91  * <li><strong>styleSelected</strong> - CSS style <code>class</code> to be
92  * applied to the text of any element that is currently selected. If not
93  * specified, no additional style class is applied.</li>
94  * <li><strong>styleUnselected</strong> - CSS style <code>class</code> to be
95  * applied to the text of any element that is not currently selected.
96  * If not specified, no additional style class is applied.</li>
97  * <li><strong>tree</strong> - Attribute name under which the
98  * <code>TreeControl</code> bean of the tree we are rendering
99  * is stored, in the scope specified by the <code>scope</code>
100  * attribute. This attribute is required.</li>
101  * </ul>
102  *
103  * <strong>FIXME</strong> - Internationalize the exception messages!
104  *
105  * @author Craig R. McClanahan
106  * @version $Revision: 1.2 $ $Date: 2003/11/12 17:19:38 $
107  */

108
109 public class TreeControlTag extends TagSupport JavaDoc {
110
111     /**
112      * The default directory name for icon images.
113      */

114     static final String JavaDoc DEFAULT_IMAGES = "images";
115
116     /**
117      * The names of tree state images that we need.
118      */

119     static final String JavaDoc IMAGE_HANDLE_DOWN_LAST = "handledownlast.gif";
120     static final String JavaDoc IMAGE_HANDLE_DOWN_MIDDLE = "handledownmiddle.gif";
121     static final String JavaDoc IMAGE_HANDLE_RIGHT_LAST = "handlerightlast.gif";
122     static final String JavaDoc IMAGE_HANDLE_RIGHT_MIDDLE = "handlerightmiddle.gif";
123     static final String JavaDoc IMAGE_LINE_LAST = "linelastnode.gif";
124     static final String JavaDoc IMAGE_LINE_MIDDLE = "linemiddlenode.gif";
125     static final String JavaDoc IMAGE_LINE_VERTICAL = "linevertical.gif";
126
127 // ------------------------------------------------------------- Properties
128

129     /**
130      * The hyperlink to be used for submitting requests to expand and
131      * contract tree nodes. The placeholder "<code>${name}</code>" will
132      * be replaced by the <code>name</code> property of the current
133      * tree node.
134      */

135     protected String JavaDoc action = null;
136
137     public String JavaDoc getAction() {
138         return (this.action);
139     }
140
141     public void setAction(String JavaDoc action) {
142         this.action = action;
143     }
144
145     /**
146      * The name of the directory containing the images for our icons,
147      * relative to the page including this tag.
148      */

149     protected String JavaDoc images = DEFAULT_IMAGES;
150
151     public String JavaDoc getImages() {
152         return (this.images);
153     }
154
155     public void setImages(String JavaDoc images) {
156         this.images = images;
157     }
158
159     /**
160      * The name of the scope in which to search for the <code>tree</code>
161      * attribute. Must be "page", "request", "session", or "application"
162      * (or <code>null</code> for an ascending-visibility search).
163      */

164     protected String JavaDoc scope = null;
165
166     public String JavaDoc getScope() {
167         return (this.scope);
168     }
169
170     public void setScope(String JavaDoc scope) {
171         if (!"page".equals(scope) && !"request".equals(scope) && !"session".equals(scope)
172             && !"application".equals(scope)) {
173             throw new IllegalArgumentException JavaDoc("Invalid scope '" + scope + "'");
174         }
175         this.scope = scope;
176     }
177
178     /**
179      * The CSS style <code>class</code> to be applied to the entire tree.
180      */

181     protected String JavaDoc style = null;
182
183     public String JavaDoc getStyle() {
184         return (this.style);
185     }
186
187     public void setStyle(String JavaDoc style) {
188         this.style = style;
189     }
190
191     /**
192      * The CSS style <code>class</code> to be applied to the text
193      * of selected nodes.
194      */

195     protected String JavaDoc styleSelected = null;
196
197     public String JavaDoc getStyleSelected() {
198         return (this.styleSelected);
199     }
200
201     public void setStyleSelected(String JavaDoc styleSelected) {
202         this.styleSelected = styleSelected;
203     }
204
205     /**
206      * The CSS style <code>class</code> to be applied to the text
207      * of unselected nodes.
208      */

209     protected String JavaDoc styleUnselected = null;
210
211     public String JavaDoc getStyleUnselected() {
212         return (this.styleUnselected);
213     }
214
215     public void setStyleUnselected(String JavaDoc styleUnselected) {
216         this.styleUnselected = styleUnselected;
217     }
218
219     /**
220      * The name of the attribute (in the specified scope) under which our
221      * <code>TreeControl</code> instance is stored.
222      */

223     protected String JavaDoc tree = null;
224
225     public String JavaDoc getTree() {
226         return (this.tree);
227     }
228
229     public void setTree(String JavaDoc tree) {
230         this.tree = tree;
231     }
232
233 // --------------------------------------------------------- Public Methods
234

235     /**
236      * Render this tree control.
237      *
238      * @exception JspException if a processing error occurs
239      */

240     public int doEndTag()
241         throws JspException JavaDoc {
242
243         TreeControl treeControl = getTreeControl();
244         JspWriter JavaDoc out = pageContext.getOut();
245         try {
246             out.print("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"");
247             if (style != null) {
248                 out.print(" class=\"");
249                 out.print(style);
250                 out.print("\"");
251             }
252             out.println(">");
253             int level = 0;
254             TreeControlNode node = treeControl.getRoot();
255             render(out, node, level, treeControl.getWidth(), true);
256             out.println("</table>");
257         }
258         catch (IOException JavaDoc e) {
259             throw new JspException JavaDoc(e);
260         }
261
262         return (EVAL_PAGE);
263
264     }
265
266     /**
267      * Release all state information set by this tag.
268      */

269     public void release() {
270
271         this.action = null;
272         this.images = DEFAULT_IMAGES;
273         this.scope = null;
274         this.style = null;
275         this.styleSelected = null;
276         this.styleUnselected = null;
277         this.tree = null;
278
279     }
280
281 // ------------------------------------------------------ Protected Methods
282

283     /**
284      * Return the <code>TreeControl</code> instance for the tree control that
285      * we are rendering.
286      *
287      * @exception JspException if no TreeControl instance can be found
288      */

289     protected TreeControl getTreeControl()
290         throws JspException JavaDoc {
291
292         Object JavaDoc treeControl = null;
293         if (scope == null) {
294             treeControl = pageContext.findAttribute(tree);
295         }
296         else if ("page".equals(scope)) {
297             treeControl = pageContext.getAttribute(tree, PageContext.PAGE_SCOPE);
298         }
299         else if ("request".equals(scope)) {
300             treeControl = pageContext.getAttribute(tree, PageContext.REQUEST_SCOPE);
301         }
302         else if ("session".equals(scope)) {
303             treeControl = pageContext.getAttribute(tree, PageContext.SESSION_SCOPE);
304         }
305         else if ("application".equals(scope)) {
306             treeControl = pageContext.getAttribute(tree, PageContext.APPLICATION_SCOPE);
307         }
308         if (treeControl == null) {
309             throw new JspException JavaDoc("Cannot find tree control attribute '" + tree + "'");
310         }
311         else if (!(treeControl instanceof TreeControl)) {
312             throw new JspException JavaDoc("Invalid tree control attribute '" + tree + "'");
313         }
314         else {
315             return ((TreeControl) treeControl);
316         }
317
318     }
319
320     /**
321      * Render the specified node, as controlled by the specified parameters.
322      *
323      * @param out The <code>JspWriter</code> to which we are writing
324      * @param node The <code>TreeControlNode</code> we are currently
325      * rendering
326      * @param level The indentation level of this node in the tree
327      * @param width Total displayable width of the tree
328      * @param last Is this the last node in a list?
329      *
330      * @exception IOException if an input/output error occurs
331      */

332     protected void render(JspWriter JavaDoc out, TreeControlNode node, int level, int width, boolean last)
333         throws IOException JavaDoc {
334
335         HttpServletResponse JavaDoc response = (HttpServletResponse JavaDoc) pageContext.getResponse();
336
337         // if the node is root node and the label value is
338
// null, then do not render root node in the tree.
339

340         if ("ROOT-NODE".equalsIgnoreCase(node.getName()) && (node.getLabel() == null)) {
341             // Render the children of this node
342
TreeControlNode children[] = node.findChildren();
343             int lastIndex = children.length - 1;
344             int newLevel = level + 1;
345             for (int i = 0; i < children.length; i++) {
346                 render(out, children[i], newLevel, width, i == lastIndex);
347             }
348             return;
349         }
350
351         // Render the beginning of this node
352
out.println(" <tr valign=\"middle\">");
353
354         // Create the appropriate number of indents
355
for (int i = 0; i < level; i++) {
356             int levels = level - i;
357             TreeControlNode parent = node;
358             for (int j = 1; j <= levels; j++) {
359                 parent = parent.getParent();
360             }
361             if (parent.isLast()) {
362                 out.print(" <td></td>");
363             }
364             else {
365                 out.print(" <td><img SRC=\"");
366                 out.print(images);
367                 out.print("/");
368                 out.print(IMAGE_LINE_VERTICAL);
369                 out.print("\" border=\"0\"></td>");
370             }
371             out.println();
372         }
373
374         // Render the tree state image for this node
375

376         // HACK to take into account special characters like = and &
377
// in the node name, could remove this code if encode URL
378
// and later request.getParameter() could deal with = and &
379
// character in parameter values.
380
String JavaDoc encodedNodeName = URLEncoder.encode(node.getName(),"UTF-8");
381
382         String JavaDoc action = replace(getAction(), "${name}", encodedNodeName);
383
384         String JavaDoc updateTreeAction = replace(getAction(), "tree=${name}", "select=" + encodedNodeName);
385         updateTreeAction = ((HttpServletResponse JavaDoc) pageContext.getResponse()).encodeURL(
386             updateTreeAction);
387
388         out.print(" <td>");
389         if ((action != null) && !node.isLeaf()) {
390             out.print("<a HREF=\"");
391             out.print(response.encodeURL(action));
392             out.print("\">");
393         }
394         out.print("<img SRC=\"");
395         out.print(images);
396         out.print("/");
397         if (node.isLeaf()) {
398             if (node.isLast()) {
399                 out.print(IMAGE_LINE_LAST);
400             }
401             else {
402                 out.print(IMAGE_LINE_MIDDLE);
403             }
404         }
405         else if (node.isExpanded()) {
406             if (node.isLast()) {
407                 out.print(IMAGE_HANDLE_DOWN_LAST);
408             }
409             else {
410                 out.print(IMAGE_HANDLE_DOWN_MIDDLE);
411             }
412         }
413         else {
414             if (node.isLast()) {
415                 out.print(IMAGE_HANDLE_RIGHT_LAST);
416             }
417             else {
418                 out.print(IMAGE_HANDLE_RIGHT_MIDDLE);
419             }
420         }
421         out.print("\" border=\"0\">");
422         if ((action != null) && !node.isLeaf()) {
423             out.print("</a>");
424         }
425         out.println("</td>");
426
427         // Calculate the hyperlink for this node (if any)
428
String JavaDoc hyperlink = null;
429         if (node.getAction() != null) {
430             hyperlink = ((HttpServletResponse JavaDoc) pageContext.getResponse()).encodeURL(node.getAction());
431
432             // Render the icon for this node (if any)
433
}
434         out.print(" <td colspan=\"");
435         out.print(width - level + 1);
436         out.print("\">");
437         if (node.getIcon() != null) {
438             if (hyperlink != null) {
439                 out.print("<a HREF=\"");
440                 out.print(hyperlink);
441                 out.print("\"");
442                 String JavaDoc target = node.getTarget();
443                 if (target != null) {
444                     out.print(" target=\"");
445                     out.print(target);
446                     out.print("\"");
447                 }
448                 // to refresh the tree in the same 'self' frame
449
out.print(" onclick=\"");
450                 out.print("self.location.href='" + updateTreeAction + "'");
451                 out.print("\"");
452                 out.print(">");
453             }
454             out.print("<img SRC=\"");
455             out.print(images);
456             out.print("/");
457             out.print(node.getIcon());
458             out.print("\" border=\"0\">");
459             if (hyperlink != null) {
460                 out.print("</a>");
461             }
462         }
463
464         // Render the label for this node (if any)
465

466         if (node.getLabel() != null) {
467             String JavaDoc labelStyle = null;
468             if (node.isSelected() && (styleSelected != null)) {
469                 labelStyle = styleSelected;
470             }
471             else if (!node.isSelected() && (styleUnselected != null)) {
472                 labelStyle = styleUnselected;
473             }
474             if (hyperlink != null) {
475                 // Note the leading space so that the text has some space
476
// between it and any preceding images
477
out.print(" <a HREF=\"");
478                 out.print(hyperlink);
479                 out.print("\"");
480                 String JavaDoc target = node.getTarget();
481                 if (target != null) {
482                     out.print(" target=\"");
483                     out.print(target);
484                     out.print("\"");
485                 }
486                 if (labelStyle != null) {
487                     out.print(" class=\"");
488                     out.print(labelStyle);
489                     out.print("\"");
490                 }
491                 // to refresh the tree in the same 'self' frame
492
out.print(" onclick=\"");
493                 out.print("self.location.href='" + updateTreeAction + "'");
494                 out.print("\"");
495                 out.print(">");
496             }
497             else if (labelStyle != null) {
498                 out.print("<span class=\"");
499                 out.print(labelStyle);
500                 out.print("\">");
501             }
502             out.print(node.getLabel());
503             if (hyperlink != null) {
504                 out.print("</a>");
505             }
506             else if (labelStyle != null) {
507                 out.print("</span>");
508             }
509         }
510         out.println("</td>");
511
512         // Render the end of this node
513
out.println(" </tr>");
514
515         // Render the children of this node
516
if (node.isExpanded()) {
517             TreeControlNode children[] = node.findChildren();
518             int lastIndex = children.length - 1;
519             int newLevel = level + 1;
520             for (int i = 0; i < children.length; i++) {
521                 render(out, children[i], newLevel, width, i == lastIndex);
522             }
523         }
524
525     }
526
527     /**
528      * Replace any occurrence of the specified placeholder in the specified
529      * template string with the specified replacement value.
530      *
531      * @param template Pattern string possibly containing the placeholder
532      * @param placeholder Placeholder expression to be replaced
533      * @param value Replacement value for the placeholder
534      */

535     protected String JavaDoc replace(String JavaDoc template, String JavaDoc placeholder, String JavaDoc value) {
536
537         if (template == null) {
538             return (null);
539         }
540         if ((placeholder == null) || (value == null)) {
541             return (template);
542         }
543         while (true) {
544             int index = template.indexOf(placeholder);
545             if (index < 0) {
546                 break;
547             }
548             StringBuffer JavaDoc temp = new StringBuffer JavaDoc(template.substring(0, index));
549             temp.append(value);
550             temp.append(template.substring(index + placeholder.length()));
551             template = temp.toString();
552         }
553         return (template);
554
555     }
556
557 }
558
Popular Tags