View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.custom.tree2;
21  
22  import org.apache.commons.lang.StringUtils;
23  import java.util.Stack;
24  
25  /**
26   * A base implementation of the {@link TreeWalker} interface.  Uses a simple node naming
27   * scheme of "0" for the root node, "0:0" for the first child, "0:1" for the second child, etc.
28   */
29  public class TreeWalkerBase implements TreeWalker
30  {
31      private String ROOT_NODE_ID = "0";
32      private String TREE_NODE_SEPARATOR = ":";
33  
34      private Tree tree;
35      private Stack nodeStack = new Stack();
36      private Stack idStack = new Stack();
37      private boolean checkState = true;
38      private boolean startedWalking = false;
39  
40      // see interface
41      public void setTree(Tree tree)
42      {
43          this.tree = tree;
44      }
45  
46      // see interface
47      public boolean isCheckState()
48      {
49          return checkState;
50      }
51  
52      // see interface
53      public void setCheckState(boolean checkState)
54      {
55          this.checkState = checkState;
56      }
57  
58      // see interface
59      public boolean next()
60      {
61          if (!startedWalking)
62          {
63              // the first next() call just needs to set the root node and push it onto the stack
64              idStack.push(ROOT_NODE_ID);
65              tree.setNodeId(ROOT_NODE_ID);
66              nodeStack.push(tree.getNode());
67  
68              startedWalking = true;
69              return true;
70          }
71  
72          if (nodeStack.isEmpty())
73          {
74              return false;
75          }
76  
77          TreeNode prevNode = (TreeNode)nodeStack.peek();
78          String prevNodeId = (String)idStack.peek();
79  
80          if (prevNode.isLeaf())
81          {
82              nodeStack.pop();
83              idStack.pop();
84  
85              return next();
86          }
87          else
88          {
89              TreeNode nextNode = null;
90              String nextNodeId = null;
91  
92              if (prevNodeId.equals(tree.getNodeId()))
93              {
94                  /**
95                   * We know there is at least one child b/c otherwise we would have popped the node after
96                   * checking isLeaf.  Basically we need to keep drilling down until we reach the deepest
97                   * node that is available for "walking."  Then we'll return to the parent and render its
98                   * siblings and walk back up the tree.
99                   */
100                 nextNodeId = prevNodeId + TREE_NODE_SEPARATOR + "0";
101 
102                 // don't render any children if the node is not expanded
103                 if (checkState)
104                 {
105                     if (!tree.getDataModel().getTreeState().isNodeExpanded(prevNodeId))
106                     {
107                         nodeStack.pop();
108                         idStack.pop();
109 
110                         return next();
111                     }
112                 }
113             }
114             else
115             {
116                 // get the parent node
117                 String currentNodeId = tree.getNodeId();
118                 String parentNodeId = StringUtils.substringBeforeLast(currentNodeId, TREE_NODE_SEPARATOR);
119                 tree.setNodeId(parentNodeId);
120                 TreeNode parentNode = tree.getNode();
121 
122                 int siblingCount = Integer.parseInt(currentNodeId.substring(parentNodeId.length()+1));
123                 siblingCount++;
124 
125                 if (siblingCount == parentNode.getChildCount())
126                 {
127                     // no more siblings
128                     nodeStack.pop();
129                     idStack.pop();
130 
131                     return next();
132                 }
133 
134                 nextNodeId = parentNodeId + TREE_NODE_SEPARATOR + siblingCount;
135             }
136 
137             tree.setNodeId(nextNodeId);
138             nextNode = tree.getNode();
139 
140             nodeStack.push(nextNode);
141             idStack.push(nextNodeId);
142 
143             return true;
144         }
145     }
146 
147     // see interface
148     public String getRootNodeId()
149     {
150         return ROOT_NODE_ID;
151     }
152 
153     // see interface
154     public void reset()
155     {
156         nodeStack.empty();
157         idStack.empty();
158         startedWalking = false;
159     }
160 }