KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > nextime > ion > backoffice > tree > TreeControlTag


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

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

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

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

133
134     /**
135      * The hyperlink to be used for submitting requests to expand and
136      * contract tree nodes. The placeholder "<code>${name}</code>" will
137      * be replaced by the <code>name</code> property of the current
138      * tree node.
139      */

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

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

171     protected String JavaDoc scope = null;
172
173     public String JavaDoc getScope() {
174         return (this.scope);
175     }
176
177     public void setScope(String JavaDoc scope) {
178         if (!"page".equals(scope) &&
179             !"request".equals(scope) &&
180             !"session".equals(scope) &&
181             !"application".equals(scope))
182             throw new IllegalArgumentException JavaDoc("Invalid scope '" +
183                                                scope + "'");
184         this.scope = scope;
185     }
186
187
188     /**
189      * The CSS style <code>class</code> to be applied to the entire tree.
190      */

191     protected String JavaDoc style = null;
192
193     public String JavaDoc getStyle() {
194         return (this.style);
195     }
196
197     public void setStyle(String JavaDoc style) {
198         this.style = style;
199     }
200
201
202     /**
203      * The CSS style <code>class</code> to be applied to the text
204      * of selected nodes.
205      */

206     protected String JavaDoc styleSelected = null;
207
208     public String JavaDoc getStyleSelected() {
209         return (this.styleSelected);
210     }
211
212     public void setStyleSelected(String JavaDoc styleSelected) {
213         this.styleSelected = styleSelected;
214     }
215
216
217     /**
218      * The CSS style <code>class</code> to be applied to the text
219      * of unselected nodes.
220      */

221     protected String JavaDoc styleUnselected = null;
222
223     public String JavaDoc getStyleUnselected() {
224         return (this.styleUnselected);
225     }
226
227     public void setStyleUnselected(String JavaDoc styleUnselected) {
228         this.styleUnselected = styleUnselected;
229     }
230
231
232     /**
233      * The name of the attribute (in the specified scope) under which our
234      * <code>TreeControl</code> instance is stored.
235      */

236     protected String JavaDoc tree = null;
237
238     public String JavaDoc getTree() {
239         return (this.tree);
240     }
241
242     public void setTree(String JavaDoc tree) {
243         this.tree = tree;
244     }
245
246
247     // --------------------------------------------------------- Public Methods
248

249
250     /**
251      * Render this tree control.
252      *
253      * @exception JspException if a processing error occurs
254      */

255     public int doEndTag() throws JspException JavaDoc {
256
257         TreeControl treeControl = getTreeControl();
258         JspWriter JavaDoc out = pageContext.getOut();
259         try {
260             out.print
261                 ("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"");
262             if (style != null) {
263                 out.print(" class=\"");
264                 out.print(style);
265                 out.print("\"");
266             }
267             out.println(">");
268             int level = 0;
269             TreeControlNode node = treeControl.getRoot();
270             render(out, node, level, treeControl.getWidth(), true);
271             out.println("</table>");
272         } catch (IOException JavaDoc e) {
273             throw new JspException JavaDoc(e);
274         }
275
276         return (EVAL_PAGE);
277
278     }
279
280
281     /**
282      * Release all state information set by this tag.
283      */

284     public void release() {
285
286         this.action = null;
287         this.images = DEFAULT_IMAGES;
288         this.scope = null;
289         this.style = null;
290         this.styleSelected = null;
291         this.styleUnselected = null;
292         this.tree = null;
293
294     }
295
296
297     // ------------------------------------------------------ Protected Methods
298

299
300     /**
301      * Return the <code>TreeControl</code> instance for the tree control that
302      * we are rendering.
303      *
304      * @exception JspException if no TreeControl instance can be found
305      */

306     protected TreeControl getTreeControl() throws JspException JavaDoc {
307
308         Object JavaDoc treeControl = null;
309         if (scope == null)
310             treeControl = pageContext.findAttribute(tree);
311         else if ("page".equals(scope))
312             treeControl =
313                 pageContext.getAttribute(tree, PageContext.PAGE_SCOPE);
314         else if ("request".equals(scope))
315             treeControl =
316                 pageContext.getAttribute(tree, PageContext.REQUEST_SCOPE);
317         else if ("session".equals(scope))
318             treeControl =
319                 pageContext.getAttribute(tree, PageContext.SESSION_SCOPE);
320         else if ("application".equals(scope))
321             treeControl =
322                 pageContext.getAttribute(tree, PageContext.APPLICATION_SCOPE);
323         if (treeControl == null)
324             throw new JspException JavaDoc("Cannot find tree control attribute '" +
325                                    tree + "'");
326         else if (!(treeControl instanceof TreeControl))
327             throw new JspException JavaDoc("Invalid tree control attribute '" +
328                                    tree + "'");
329         else
330             return ((TreeControl) treeControl);
331
332     }
333
334
335     /**
336      * Render the specified node, as controlled by the specified parameters.
337      *
338      * @param out The <code>JspWriter</code> to which we are writing
339      * @param node The <code>TreeControlNode</code> we are currently
340      * rendering
341      * @param level The indentation level of this node in the tree
342      * @param width Total displayable width of the tree
343      * @param last Is this the last node in a list?
344      *
345      * @exception IOException if an input/output error occurs
346      */

347     protected void render(JspWriter JavaDoc out, TreeControlNode node,
348                           int level, int width, boolean last)
349         throws IOException JavaDoc {
350
351         HttpServletResponse JavaDoc response =
352             (HttpServletResponse JavaDoc) pageContext.getResponse();
353     
354         // if the node is root node and the label value is
355
// null, then do not render root node in the tree.
356

357         if ("ROOT-NODE".equalsIgnoreCase(node.getName()) &&
358         (node.getLabel() == null)) {
359             // Render the children of this node
360
TreeControlNode children[] = node.findChildren();
361             int lastIndex = children.length - 1;
362             int newLevel = level + 1;
363             for (int i = 0; i < children.length; i++) {
364                 render(out, children[i], newLevel, width, i == lastIndex);
365             }
366             return;
367         }
368         
369         // Render the beginning of this node
370
out.println(" <tr valign=\"middle\">");
371
372         // Create the appropriate number of indents
373
for (int i = 0; i < level; i++) {
374             int levels = level - i;
375             TreeControlNode parent = node;
376             for (int j = 1; j <= levels; j++)
377                 parent = parent.getParent();
378             if (parent.isLast())
379                 out.print(" <td></td>");
380             else {
381                 out.print(" <td><img SRC=\"");
382                 out.print(images);
383                 out.print("/");
384                 out.print(IMAGE_LINE_VERTICAL);
385                 out.print("\" border=\"0\"></td>");
386             }
387             out.println();
388         }
389
390         // Render the tree state image for this node
391

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

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

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