KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ivata > groupware > web > tag > webgui > tree > TreeTag


1 /*
2  * Copyright (c) 2001 - 2005 ivata limited.
3  * All rights reserved.
4  * -----------------------------------------------------------------------------
5  * ivata groupware may be redistributed under the GNU General Public
6  * License as published by the Free Software Foundation;
7  * version 2 of the License.
8  *
9  * These programs are free software; you can redistribute them and/or
10  * modify them under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; version 2 of the License.
12  *
13  * These programs are distributed in the hope that they will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License in the file LICENSE.txt for more
18  * details.
19  *
20  * If you would like a copy of the GNU General Public License write to
21  *
22  * Free Software Foundation, Inc.
23  * 59 Temple Place - Suite 330
24  * Boston, MA 02111-1307, USA.
25  *
26  *
27  * To arrange commercial support and licensing, contact ivata at
28  * http://www.ivata.com/contact.jsp
29  * -----------------------------------------------------------------------------
30  * $Log: TreeTag.java,v $
31  * Revision 1.3 2005/04/10 18:47:36 colinmacleod
32  * Changed i tag to em and b tag to strong.
33  *
34  * Revision 1.2 2005/04/09 17:19:10 colinmacleod
35  * Changed copyright text to GPL v2 explicitly.
36  *
37  * Revision 1.1.1.1 2005/03/10 17:50:36 colinmacleod
38  * Restructured ivata op around Hibernate/PicoContainer.
39  * Renamed ivata groupware.
40  *
41  * Revision 1.2 2004/11/03 16:10:12 colinmacleod
42  * Changed todo comments to TODO: all caps.
43  *
44  * Revision 1.1 2004/09/30 15:16:03 colinmacleod
45  * Split off addressbook elements into security subproject.
46  *
47  * Revision 1.3 2004/07/13 19:41:15 colinmacleod
48  * Moved project to POJOs from EJBs.
49  * Applied PicoContainer to services layer (replacing session EJBs).
50  * Applied Hibernate to persistence layer (replacing entity EJBs).
51  *
52  * Revision 1.2 2004/03/21 21:16:18 colinmacleod
53  * Shortened name to ivata op.
54  *
55  * Revision 1.1.1.1 2004/01/27 20:57:58 colinmacleod
56  * Moved ivata openportal to SourceForge..
57  *
58  * Revision 1.2 2003/10/17 12:36:13 jano
59  * fixing problems with building
60  * converting intranet -> portal
61  * Eclipse building
62  *
63  * Revision 1.1.1.1 2003/10/13 20:50:14 colin
64  * Restructured portal into subprojects
65  *
66  * Revision 1.1 2003/02/24 19:33:33 colin
67  * moved to jsp
68  *
69  * Revision 1.10 2003/02/04 17:43:51 colin
70  * copyright notice
71  *
72  * Revision 1.9 2003/02/01 12:48:11 colin
73  * improved error handling
74  *
75  * Revision 1.8 2003/01/28 12:57:59 colin
76  * made TreeTag a subclass of ControlTag (rather than WebGuiTag)
77  *
78  * Revision 1.7 2003/01/24 19:31:19 peter
79  * the renderer initialise method was changed...
80  *
81  * Revision 1.6 2002/09/16 14:34:20 jano
82  * added new field formName
83  *
84  * Revision 1.5 2002/08/28 12:54:12 jano
85  * method createChildren changed
86  *
87  * Revision 1.4 2002/08/11 11:57:12 colin
88  * Structural changes to make the design more flexible, for implementing comment trees.
89  *
90  * Revision 1.3 2002/06/21 12:11:13 colin
91  * restructured com.ivata.groupware.web and split into separate
92  * subcategories
93  *
94  * Revision 1.2 2002/06/13 15:45:15 peter
95  * brought over to peter, fixed bugs in webgui property-settings
96  *
97  * Revision 1.1 2002/06/13 07:44:07 colin
98  * first version of rose model: code tidied up/added javadoc
99  *
100  * Revision 1.5 2002/02/03 15:24:08 colin
101  * changed classname for User to PersonUser
102  *
103  * Revision 1.4 2002/02/02 21:23:01 colin
104  * major restructuring to make the Settings class more generic
105  * all default settings are now taken from the database rather than
106  * being hard coded in the settings class
107  * settings are stored in a HashMap in settings
108  *
109  * Revision 1.3 2002/01/27 19:55:48 colin
110  * updated the themes by removing the multiple section tags and
111  * replacing them with one tag and a Properties instance in
112  * com.ivata.groupware.web.theme.Theme
113  *
114  * Revision 1.2 2002/01/24 13:19:40 colin
115  * consolidated hanlding of theme and properties tags acoss webgui tag
116  * library
117  *
118  * Revision 1.1 2002/01/20 19:28:25 colin
119  * added tab and tree tags
120  * implemented address book functionality
121  * -----------------------------------------------------------------------------
122  */

123 package com.ivata.groupware.web.tag.webgui.tree;
124
125 import java.io.IOException JavaDoc;
126 import java.util.Properties JavaDoc;
127
128 import javax.servlet.jsp.JspException JavaDoc;
129 import javax.servlet.jsp.JspWriter JavaDoc;
130 import javax.swing.tree.TreeModel JavaDoc;
131
132 import com.ivata.groupware.web.tree.DefaultTreeNodeRenderer;
133 import com.ivata.groupware.web.tree.TreeNode;
134 import com.ivata.groupware.web.tree.TreeNodeRenderer;
135 import com.ivata.mask.util.CollectionHandling;
136 import com.ivata.mask.web.tag.webgui.ControlTag;
137 import com.ivata.mask.web.theme.ThemeUnsupportedException;
138
139
140 /**
141  * <p>Create a tree from a {@link javax.swing.tree.TreeModel TreeModel}.</p>
142  * <p>This tree can be displayed is displayed as an HTML table with links on
143  * each
144  * node.</p>
145  * <p><strong>Tag attributes:</strong><br/>
146  * <table cellpadding='2' cellspacing='5' border='0' align='center'
147  * width='85%'>
148  * <tr class='TableHeadingColor'>
149  * <th>attribute</th>
150  * <th>reqd.</th>
151  * <th>param. class</th>
152  * <th width='100%'>description</th>
153  * </tr>
154  * <tr class='TableRowColor'>
155  * <td>defaultOpen</td>
156  * <td>true</td>
157  * <td>boolean</td>
158  * <td>Set to <code>true</code> if you want tree nodes to be open by
159  * default. Otherwise they will be closed.</td>
160  * </tr>
161  * <tr class='TableRowColor'>
162  * <td>model</td>
163  * <td>true</td>
164  * <td>{@link javax.swing.tree.TreeModel javax.swing.tree.TreeModel}</td>
165  * <td>This model contains the data source for the tree. To use any
166  * datasource
167  * with this tree control, you should first create a class which implements
168  * {@link javax.swing.tree,TreeModel TreeModel}.</td>
169  * </tr>
170  * <tr class='TableRowColor'>
171  * <td>renderer</td>
172  * <td>false</td>
173  * <td>{@link com.ivata.groupware.web.tree.TreeNodeRenderer
174  * com.ivata.groupware.web.tree.TreeNodeRenderer}</td>
175  * <td>This object controls the appearance of each node in the tree,
176  * usually by parsing sections from the {@link
177  * com.ivata.groupware.web.theme.Theme
178  * Theme}.<br/>
179  * If you do not use this attribute, an instance of {@link
180  * com.ivata.groupware.web.DefaultTreeNodeRenderer
181  * DefaultTreeNodeRenderer} is created and applied.</td>
182  * </tr>
183  * <tr class='TableRowColor'>
184  * <td>treeName</td>
185  * <td>true</td>
186  * <td><code>String</code></td>
187  * <td>Specifies a unique identifier for this tree, which is used to store
188  * the state of each foler (open/closed).</td>
189  * </tr>
190  * <tr class='TableRowColor'>
191  * <td>userName</td>
192  * <td>true</td>
193  * <td><code>String</code></td>
194  * <td>Name of the user for whom to draw the tree. The state of each node is
195  * stored for this user and the appearance in recalled the next time the tree is
196  * drawn.</td>
197  * </tr>
198  * </table>
199  * </p>
200  *
201  * @since 2001-12-15
202  * @author Colin MacLeod
203  * <a HREF='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
204  * @version $Revision: 1.3 $
205  */

206 public class TreeTag extends ControlTag {
207     /**
208      * <p>This is the special property used to identify the location
209      * of the children in the open tag.</p>
210      *
211      * <p><strong>Note</strong> that this has to be specified exactly, with <u>no
212      * spaces</u>.</p>
213      */

214     static final String JavaDoc childrenProperty = "treeChildren";
215     /**
216      * <p>Property declaration for tag attribute: treeName.</p>
217      */

218     private String JavaDoc treeName = null;
219     /**
220      * <p>Specifies the id of a folder you wish to open.</p>
221      */

222     private Integer JavaDoc openFolder = null;
223     /**
224      * <p>Specifies the id of a folder you wish to open.</p>
225      */

226     private Integer JavaDoc closeFolder = null;
227     /**
228      * <p>Decides whether folders should be open or closed by default.</p>
229      */

230     private boolean defaultOpen = false;
231     /**
232      * <p>if you set up name of form it will submit this form when you
233      * open or close folder, otherwise it will make link to same page with
234      * parameters.</p>
235      */

236     private String JavaDoc formName = null;
237     /**
238      * <p>Property declaration for tag attribute: model.</p>
239      */

240     private TreeModel JavaDoc model = null;
241     /**
242      * <p>This renderer actually draws each node of the tree. If you do
243      * not set a
244      * renderer, then a <code>DefaultTreeNodeRenderer</code> is created
245      * and
246      * applied.</p>
247      */

248     private TreeNodeRenderer renderer;
249
250     /**
251      * <p>Default constructor.</p>
252
253      */

254     public TreeTag() {
255         super();
256     }
257
258     /**
259      * <p>This method is called when the JSP engine encounters the start
260      * tag,
261      * after the attributes are processed.<p>
262      *
263      * <p>Scripting variables (if any) have their values set here.</p>
264      *
265      * @return <code>SKIP_BODY</code> if this tag has no body or it
266      * should be skipped, otherwise <code>EVAL_BODY_BUFFERED</code>
267      * @throws JspException if there is an error retrieving the
268      * navigation
269      * object.
270      * @throws JspException if there is no settings object in the
271      * session.
272      * @throws JspException if there is an error wrting to
273      * <code>out.print(
274      * )</code>
275      * @throws ThemeUnsupportedException if theme elements are missing.
276      */

277     public int doStartTag() throws JspException JavaDoc,ThemeUnsupportedException {
278         super.doStartTag();
279         try {
280             // now do we have a valid renderer specified? if not, use the default
281
if (renderer == null) {
282                 renderer = new DefaultTreeNodeRenderer();
283             }
284             renderer.setTreeTag(this);
285             JspWriter JavaDoc out = pageContext.getOut();
286
287             renderer.initialize(pageContext.getSession(),
288                 (javax.servlet.http.HttpServletRequest JavaDoc) pageContext.getRequest(),
289                 out, pageContext);
290             // see if the selected string contains an array representation
291
// TODO: see if we can't make two attributes - one a list and the other a string
292
int nSelectedStringLength;
293
294             // create the full tree ( null parent )
295
out.println(createChildren(model.getRoot(), 0));
296             renderer.finalize(pageContext.getSession(),
297                 (javax.servlet.http.HttpServletRequest JavaDoc) pageContext.getRequest(),
298                 out);
299         } catch (IOException JavaDoc ioException) {
300             throw new JspException JavaDoc(
301             "Error in TreeTag: IOException whilst printing select: "
302             + ioException.getMessage(),
303             ioException);
304         } catch (Exception JavaDoc e) {
305             throw new JspException JavaDoc(e);
306         }
307         // this tag has no body
308
return SKIP_BODY;
309     }
310
311     /**
312      * <p>This is the method which performs the clever stuff and actually
313      * creates the tree by recursing on itself, for a table mode
314      * tree.</p>
315      *
316      * @param parent the node for which to display all the children.
317      * @param level the depth of this node within the tree, with 0 being
318      * root.
319      * @return the parsed HTML tree as
320      * @throws ThemeUnsupportedException when the theme sections required
321      * by the
322      * renderer were not set.
323      * @throws JspException if there is any RemoteException or
324      * IOException
325      * .
326      */

327     private String JavaDoc createChildren(final Object JavaDoc parent,
328             final int level) throws ThemeUnsupportedException,JspException JavaDoc {
329         String JavaDoc returnString = "";
330         int totalNodes = model.getChildCount(parent);
331
332         for (int nodeNumber = 0; nodeNumber < totalNodes; ++nodeNumber) {
333             // make a fresh copy of the properties for each node
334
Properties JavaDoc nodeProperties = CollectionHandling.splice(getProperties(), new Properties JavaDoc());
335             TreeNode node = (TreeNode) model.getChild(parent, nodeNumber);
336             // find out if this folder is open or closed
337
Boolean JavaDoc isOpenObject = Boolean.TRUE;
338             boolean isOpen;
339
340             // if the folder state is still not set, default
341
if (isOpenObject == null) {
342                 isOpen = defaultOpen;
343             } else {
344                 // use the last setting from the user
345
isOpen = isOpenObject.booleanValue();
346             }
347             // if this node has children and is open and is not leaf, then we have to parse the children
348
// first so we can set the property for the children
349
if ((model.getChildCount(node) > 0) && isOpen && !model.isLeaf(node)) {
350                 nodeProperties.setProperty(childrenProperty, createChildren(node,
351                         level + 1));
352             }
353             // now we just use the renderer and return whatever that gives us
354
boolean isLeaf = model.isLeaf(node);
355             try {
356                 returnString += renderer.render(model, node, isOpen,
357                             isLeaf,
358                             level,
359                             (nodeNumber == (totalNodes - 1)),
360                             getTheme(), nodeProperties);
361             } catch(JspException JavaDoc e) {
362                 // catch it to throw it again :-)
363
throw e;
364             } catch(Exception JavaDoc e) {
365                 throw new JspException JavaDoc(e);
366             }
367         }
368         return returnString;
369     }
370
371     /**
372      * <p>Get the value supplied to the attribute 'model'.</p>
373      *
374      * <p>This model contains the data source for the tree. To use any
375      * datasource
376      * with this tree control, you should first create a class which
377      * implements
378      * {@link javax.swing.tree,TreeModel TreeModel}.</p>
379      *
380      * @return the value supplied to the tag attribute 'model'.
381      *
382      */

383     public final TreeModel JavaDoc getModel() {
384         return model;
385     }
386
387     /**
388      * <p>Set the value supplied to the attribute 'model'.</p>
389      *
390      * <p>This model contains the data source for the tree. To use any
391      * datasource
392      * with this tree control, you should first create a class which
393      * implements
394      * {@link javax.swing.tree,TreeModel TreeModel}.</p>
395      *
396      * @param model the new value supplied to the tag attribute 'model'.
397      *
398      */

399     public final void setModel(final TreeModel JavaDoc model) {
400         this.model = model;
401     }
402
403     /**
404      * <p>Get the value supplied to the attribute 'renderer'.</p>
405      *
406      * <p>This object controls the appearance of each node in the tree,
407      * usually
408      * by
409      * parsing sections from the {@link
410      * com.ivata.groupware.web.theme.Theme
411      * Theme}.<br/>
412      * If you do not use this attribute, an instance of {@link
413      * com.ivata.groupware.web.DefaultTreeNodeRenderer
414      * DefaultTreeNodeRenderer} is created and applied.</p>
415      *
416      * @return the value supplied to the tag attribute 'renderer'.
417      *
418      */

419     public final TreeNodeRenderer getRenderer() {
420         return renderer;
421     }
422
423     /**
424      * <p>Set the value supplied to the attribute 'renderer'.</p>
425      *
426      * <p>This object controls the appearance of each node in the tree,
427      * usually
428      * by
429      * parsing sections from the {@link
430      * com.ivata.groupware.web.theme.Theme
431      * Theme}.<br/>
432      * If you do not use this attribute, an instance of {@link
433      * com.ivata.groupware.web.DefaultTreeNodeRenderer
434      * DefaultTreeNodeRenderer} is created and applied.</p>
435      *
436      * @param renderer the new value supplied to the tag attribute
437      * 'renderer'.
438      *
439      */

440     public final void setRenderer(final TreeNodeRenderer renderer) {
441         this.renderer = renderer;
442     }
443
444     /**
445      * <p>Get the value supplied to the attribute 'treeName'.</p>
446      *
447      * <p>This attribute specifies a unique identifier for this tree,
448      * which is
449      * used to store the state of each foler (open/closed).</p>
450      *
451      * @return the value supplied to the tag attribute 'treeName'.
452      *
453      */

454     public final String JavaDoc getTreeName() {
455         return treeName;
456     }
457
458     /**
459      * <p>Set the value supplied to the attribute 'treeName'.</p>
460      *
461      * <p>This attribute specifies a unique identifier for this tree,
462      * which is
463      * used to store the state of each foler (open/closed).</p>
464      *
465      * @param treeName the new value supplied to the tag attribute
466      * 'treeName'.
467      *
468      */

469     public final void setTreeName(final String JavaDoc treeName) {
470         this.treeName = treeName;
471     }
472
473     /**
474      * <p>Specifies the id of a folder you wish to open.</p>
475      *
476      * @return the current value of the folder which will be opened, or
477      * <code>null</code> if no folder will be opened.
478      */

479     public final Integer JavaDoc getOpenFolder() {
480         return openFolder;
481     }
482
483     /**
484      * <p>Specifies the id of a folder you wish to open.</p>
485      *
486      * @param openFolder the new value of the folder you wish to open. Not
487      * setting
488      * or setting to <code>null</code> results in no folder being opened.
489      */

490     public final void setOpenFolder(final Integer JavaDoc openFolder) {
491         this.openFolder = openFolder;
492     }
493
494     /**
495      * <p>Specifies the id of a folder you wish to close.</p>
496      *
497      * @return the current value of the folder which will be closed, or
498      * <code>null</code> if no folder will be closed.
499      */

500     public final Integer JavaDoc getCloseFolder() {
501         return closeFolder;
502     }
503
504     /**
505      * <p>Specifies the id of a folder you wish to close.</p>
506      *
507      * @param openFolder the new value of the folder you wish to open. Not
508      * setting
509      * or setting to <code>null</code> results in no folder being opened.
510      */

511     public final void setCloseFolder(final Integer JavaDoc closeFolder) {
512         this.closeFolder = closeFolder;
513     }
514
515     /**
516      * <p>Decides whether folders should be open or closed by default.</p>
517      *
518      * @return <code>true</code> if folders should be opened by default,
519      * otherwise
520      * <code>false>.
521      */

522     public final boolean getDefaultOpen() {
523         return defaultOpen;
524     }
525
526     /**
527      * <p>Decides whether folders should be open or closed by default.</p>
528      *
529      * @param defaultOpen set to <code>true</code> if folders should be
530      * opened by
531      * default, otherwise <code>false>.
532      */

533     public final void setDefaultOpen(final boolean defaultOpen) {
534         this.defaultOpen = defaultOpen;
535     }
536
537     /**
538      * <p>returning name of form which will submit when you open or close
539      * folder</p>
540      *
541      * @return <code>String</code> name of form
542      */

543     public final String JavaDoc getFormName() {
544         return this.formName;
545     }
546
547     /**
548      * <p>set up the name of form form submit when you open or close
549      * folder</p>
550      *
551      * @param <code>String formName</ocde> name of form
552      */

553     public final void setFormName(final String JavaDoc formName) {
554         this.formName = formName;
555     }
556 }
557
Popular Tags