KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > forms > formmodel > tree > TreeWalker


1 /*
2  * Copyright 1999-2005 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 package org.apache.cocoon.forms.formmodel.tree;
17
18 import java.util.Collections JavaDoc;
19 import java.util.Iterator JavaDoc;
20
21 import org.apache.commons.collections.ArrayStack;
22
23 /**
24  * A helper to crawl a tree and quickly access important node-related information.
25  * <p>
26  * It's an <code>Iterator</code> on the "current level" of the tree. This level starts
27  * at the root node (and therefore obviously contains only one element), and can then
28  * be changed to children of the current node using {@link #enterChildren()} or popped
29  * back to the parent level using {@link #leave()}.
30  * <p>
31  * The {@link #next()} method will return the next node in the iteration,
32  * and set the current node used by many convenience methods giving information about
33  * that node.
34  * <p>
35  * This class was primarily written for page templates containing {@link Tree}s (see
36  * <code>org/apache/cocoon/forms/generation/jx-macros.xml</code>) but can of course be
37  * used in other places as well.
38  *
39  * @version $Id: TreeWalker.java 190962 2005-06-16 17:17:00Z sylvain $
40  */

41 public class TreeWalker implements Iterator JavaDoc {
42     ArrayStack stack = new ArrayStack();
43     Tree tree;
44     Object JavaDoc node;
45     TreePath path;
46     Iterator JavaDoc iter;
47
48     public TreeWalker(Tree tree) {
49         // Root node has no siblings
50
this.iter = Collections.EMPTY_LIST.iterator();
51         this.tree = tree;
52         this.node = tree.getModel().getRoot();
53         this.path = TreePath.ROOT_PATH;
54         
55         stack.push(this.iter);
56         stack.push(this.node);
57     }
58     
59     /**
60      * Starts iterating the children of the current node. The current iterator is pushed
61      * on a stack and will be restored on {@link #leave()}.
62      * <p>
63      * Right after calling this method, there is no current node. Calling {@link #next()}
64      * will move to the first child, if any.
65      *
66      * @return the current tree walker (i.e. <code>this</code>).
67      */

68     public TreeWalker enterChildren() {
69         Iterator JavaDoc newIter;
70         if (isLeaf()) {
71             newIter = Collections.EMPTY_LIST.iterator();
72         } else {
73             newIter = tree.getModel().getChildren(node).iterator();
74         }
75         this.stack.push(this.iter);
76         this.stack.push(this.path);
77         this.stack.push(this.node);
78         this.iter = newIter;
79         this.node = null;
80         this.path = null;
81         
82         return this;
83     }
84     
85     /**
86      * Go back to the parent node, restoring the iterator at this node.
87      */

88     public void leave() {
89         this.node = this.stack.pop();
90         this.path = (TreePath)this.stack.pop();
91         this.iter = (Iterator JavaDoc)this.stack.pop();
92         this.path = this.path.getParentPath();
93     }
94     
95     /**
96      * Are there more nodes to iterate on at this level?
97      */

98     public boolean hasNext() {
99         return this.iter.hasNext();
100     }
101     
102     /**
103      * Get the next node in the current iteration level.
104      */

105     public Object JavaDoc next() {
106         this.node = iter.next();
107         
108         this.path = new TreePath(
109              (TreePath)this.stack.peek(1),
110              tree.getModel().getChildKey(stack.peek(), this.node));
111         return this.node;
112     }
113     
114     /**
115      * Required by the <code>Iterator</code> interface, but not supported here.
116      *
117      * @throws UnsupportedOperationException whenever called.
118      */

119     public void remove() {
120         throw new UnsupportedOperationException JavaDoc();
121     }
122     
123     /**
124      * Get the current depth of this walker (can be used e.g. to compute indentation margins
125      * or CSS styles). If root node is visible (see {@link Tree#isRootVisible()), depth 0 is
126      * for the root. Otherwise, children of the root node are at depth 0.
127      *
128      * @return the current depth
129      */

130     public int getDepth() {
131         return path.getPathCount() - (this.tree.isRootVisible() ? 1 : 2);
132     }
133     
134     /**
135      * Get the current node, which is the result of the last call to {@link #next()} (except if
136      * {@link #enterChildren()} or {@link #leave()} where called inbetween.
137      *
138      * @return the current node.
139      */

140     public Object JavaDoc getNode() {
141         return this.node;
142     }
143     
144     /**
145      * Get the path of the current node.
146      *
147      * @return the path
148      */

149     public TreePath getPath() {
150         return this.path;
151     }
152     
153     /**
154      * Is the current node a leaf?
155      */

156     public boolean isLeaf() {
157         return this.tree.getModel().isLeaf(this.node);
158     }
159     
160     /**
161      * Is the current node expanded?
162      */

163     public boolean isExpanded() {
164         return this.tree.isExpanded(this.path);
165     }
166     
167     /**
168      * Is the current node collapsed?
169      */

170     public boolean isCollapsed() {
171         return this.tree.isCollapsed(this.path);
172     }
173     
174     /**
175      * Is the current node visible (i.e. its parent is expanded)?
176      */

177     public boolean isVisible() {
178         return this.tree.isVisible(this.path);
179     }
180     
181     /**
182      * Is the current node selected?
183      */

184     public boolean isSelected() {
185         return this.tree.isPathSelected(this.path);
186     }
187     
188     /**
189      * Get the "icon type" that should be used for this node, according to the common
190      * visual paradigms used to render trees:
191      * <ul>
192      * <li>"<code>leaf</code>" for leaf nodes (will be e.g. a file icon),</li>
193      * <li>"<code>expanded</code>" for non-leaf expanded nodes (will be e.g. a "minus" icon)</li>
194      * <li>"<code>collapsed</code>" for non-leaf collapsed nodes (will be e.g. a "plus" icon)</li>
195      * </ul>
196      *
197      * @return the icon type
198      */

199     public String JavaDoc getIconType() {
200         if (isLeaf()) {
201             return "leaf";
202         } else if (isExpanded()) {
203             return "expanded";
204         } else {
205             return "collapsed";
206         }
207     }
208     
209     /**
210      * Get the "selection type" that should be used for this node, that can be used e.g. as
211      * a CSS class name:
212      * <ul>
213      * <li>"<code>selected</code>" for selected nodes,</li>
214      * <li>"<code>unselected</code>" for unselected nodes.</li>
215      * </ul>
216      *
217      * @return the selection type
218      */

219     public String JavaDoc getSelectionType() {
220         return this.tree.isPathSelected(this.path) ? "selected" : "unselected";
221     }
222 }
223
Popular Tags