KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > jcr > util > TraversingItemVisitor


1 /*
2  * $Id: TraversingItemVisitor.java,v 1.2 2004/07/24 00:16:24 benjmestrallet Exp $
3  *
4  * Copyright 2002-2004 Day Management AG, Switzerland.
5  *
6  * Licensed under the Day RI License, Version 2.0 (the "License"),
7  * as a reference implementation of the following specification:
8  *
9  * Content Repository API for Java Technology, revision 0.12
10  * <http://www.jcp.org/en/jsr/detail?id=170>
11  *
12  * You may not use this file except in compliance with the License.
13  * You may obtain a copy of the License files at
14  *
15  * http://www.day.com/content/en/licenses/day-ri-license-2.0
16  * http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */

24 package javax.jcr.util;
25
26 import javax.jcr.*;
27 import java.util.LinkedList JavaDoc;
28
29 /**
30  * An implementaion of <code>ItemVisitor</code>.
31  * <p/>
32  * <b>Level 1 and 2</b>
33  * <p/>
34  * <code>TraversingItemVisitor</code> is an abstract utility class
35  * which allows to easily traverse an <code>Item</code> hierarchy.
36  * <p/>
37  * <p><code>TraversingItemVisitor</code> makes use of the Visitor Pattern
38  * as described in the book 'Design Patterns' by the Gang Of Four
39  * (Gamma et al.).
40  * <p/>
41  * <p>Tree traversal is done observing the left-to-right order of
42  * child <code>Item</code>s if such an order is supported and exists.
43  *
44  * @author Stefan Guggisberg
45  */

46 public abstract class TraversingItemVisitor implements ItemVisitor {
47
48   /**
49    * indicates if traversal should be done in a breadth-first
50    * manner rather than depth-first (which is the default)
51    */

52   final protected boolean breadthFirst;
53
54   /**
55    * the 0-based level up to which the hierarchy should be traversed
56    * (if it's -1, the hierarchy will be traversed until there are no
57    * more children of the current item)
58    */

59   final protected int maxLevel;
60
61   /**
62    * queues used to implement breadth-first traversal
63    */

64   private LinkedList JavaDoc currentQueue;
65   private LinkedList JavaDoc nextQueue;
66
67   /**
68    * used to track hierarchy level of item currently being processed
69    */

70   private int currentLevel;
71
72   /**
73    * Constructs a new instance of this class.
74    * <p/>
75    * The tree of <code>Item</code>s will be traversed in a
76    * depth-first manner (default behaviour).
77    */

78   public TraversingItemVisitor() {
79     this(false, -1);
80   }
81
82   /**
83    * Constructs a new instance of this class.
84    *
85    * @param breadthFirst if <code>breadthFirst</code> is true then traversal
86    * is done in a breadth-first manner; otherwise it is done in a
87    * depth-first manner (which is the default behaviour).
88    */

89   public TraversingItemVisitor(boolean breadthFirst) {
90     this(breadthFirst, -1);
91   }
92
93   /**
94    * Constructs a new instance of this class.
95    *
96    * @param breadthFirst if <code>breadthFirst</code> is true then traversal
97    * is done in a breadth-first manner; otherwise it is
98    * done in a depth-first manner (which is the default
99    * behaviour).
100    * @param maxLevel the 0-based level up to which the hierarchy should be
101    * traversed (if it's -1, the hierarchy will be traversed
102    * until there are no more children of the current item)
103    */

104   public TraversingItemVisitor(boolean breadthFirst, int maxLevel) {
105     this.breadthFirst = breadthFirst;
106     if (breadthFirst) {
107       currentQueue = new LinkedList JavaDoc();
108       nextQueue = new LinkedList JavaDoc();
109     }
110     currentLevel = 0;
111     this.maxLevel = maxLevel;
112   }
113
114   /**
115    * Implement this method to add behaviour performed before a
116    * <code>Property</code> is visited.
117    *
118    * @param property the <code>Property</code> that is accepting this visitor.
119    * @param level hierarchy level of this property (the root node starts at level 0)
120    * @throws RepositoryException if an error occurrs
121    */

122   protected abstract void entering(Property property, int level)
123       throws RepositoryException;
124
125   /**
126    * Implement this method to add behaviour performed before a
127    * <code>Node</code> is visited.
128    *
129    * @param node the <code>Node</code> that is accepting this visitor.
130    * @param level hierarchy level of this node (the root node starts at level 0)
131    * @throws RepositoryException if an error occurrs
132    */

133   protected abstract void entering(Node node, int level)
134       throws RepositoryException;
135
136   /**
137    * Implement this method to add behaviour performed after a
138    * <code>Property</code> is visited.
139    *
140    * @param property the <code>Property</code> that is accepting this visitor.
141    * @param level hierarchy level of this property (the root node starts at level 0)
142    * @throws RepositoryException if an error occurrs
143    */

144   protected abstract void leaving(Property property, int level)
145       throws RepositoryException;
146
147   /**
148    * Implement this method to add behaviour performed after a
149    * <code>Node</code> is visited.
150    *
151    * @param node the <code>Node</code> that is accepting this visitor.
152    * @param level hierarchy level of this node (the root node starts at level 0)
153    * @throws RepositoryException if an error occurrs
154    */

155   protected abstract void leaving(Node node, int level)
156       throws RepositoryException;
157
158   /**
159    * Called when the Visitor is passed to a <code>Property</code>.
160    * <p/>
161    * It calls <code>TraversingItemVisitor.entering(Property, int)</code> followed by
162    * <code>TraversingItemVisitor.leaving(Property, int)</code>. Implement these abstract methods to
163    * specify behaviour on 'arrival at' and 'after leaving' the <code>Property</code>.
164    * <p/>
165    * <p/>
166    * If this method throws, the visiting process is aborted.
167    *
168    * @param property the <code>Property</code> that is accepting this visitor.
169    * @throws RepositoryException if an error occurrs
170    */

171   public void visit(Property property) throws RepositoryException {
172     entering(property, currentLevel);
173     leaving(property, currentLevel);
174   }
175
176   /**
177    * Called when the Visitor is passed to a <code>Node</code>.
178    * <p/>
179    * It calls <code>TraversingItemVisitor.entering(Node, int)</code> followed by
180    * <code>TraversingItemVisitor.leaving(Node, int)</code>. Implement these abstract methods to
181    * specify behaviour on 'arrival at' and 'after leaving' the <code>Node</code>.
182    * <p/>
183    * If this method throws, the visiting process is aborted.
184    *
185    * @param node the <code>Node</code> that is accepting this visitor.
186    * @throws RepositoryException if an error occurrs
187    */

188   public void visit(Node node)
189       throws RepositoryException {
190     try {
191       if (!breadthFirst) {
192         // depth-first traversal
193
entering(node, currentLevel);
194         if (maxLevel == -1 || currentLevel < maxLevel) {
195           currentLevel++;
196           NodeIterator nodeIter = node.getNodes();
197           while (nodeIter.hasNext()) {
198             nodeIter.nextNode().accept(this);
199           }
200           PropertyIterator propIter = node.getProperties();
201           while (propIter.hasNext()) {
202             propIter.nextProperty().accept(this);
203           }
204           currentLevel--;
205         }
206         leaving(node, currentLevel);
207       } else {
208         // breadth-first traversal
209
entering(node, currentLevel);
210         leaving(node, currentLevel);
211
212         if (maxLevel == -1 || currentLevel < maxLevel) {
213           NodeIterator nodeIter = node.getNodes();
214           while (nodeIter.hasNext()) {
215             nextQueue.addLast(nodeIter.nextNode());
216           }
217           PropertyIterator propIter = node.getProperties();
218           while (propIter.hasNext()) {
219             nextQueue.addLast(propIter.nextProperty());
220           }
221         }
222
223         while (!currentQueue.isEmpty() || !nextQueue.isEmpty()) {
224           if (currentQueue.isEmpty()) {
225             currentLevel++;
226             currentQueue = nextQueue;
227             nextQueue = new LinkedList JavaDoc();
228           }
229           Item e = (Item) currentQueue.removeFirst();
230           e.accept(this);
231         }
232         currentLevel = 0;
233       }
234     } catch (RepositoryException re) {
235       currentLevel = 0;
236       throw re;
237     }
238   }
239
240   /**
241    * Convenience class providing default implementations of the abstract methods
242    * of <code>TraversingItemVisitor</code>.
243    */

244   public static class Default extends TraversingItemVisitor {
245
246     /**
247      * @see TraversingItemVisitor#TraversingItemVisitor()
248      */

249     public Default() {
250     }
251
252     /**
253      * @see TraversingItemVisitor#TraversingItemVisitor()
254      */

255     public Default(boolean breadthFirst) {
256       super(breadthFirst);
257     }
258
259     /**
260      * @see TraversingItemVisitor#TraversingItemVisitor(boolean, int)
261      */

262     public Default(boolean breadthFirst, int maxLevel) {
263       super(breadthFirst, maxLevel);
264     }
265
266     /**
267      * @see TraversingItemVisitor#entering(Node, int)
268      */

269     protected void entering(Node node, int level)
270         throws RepositoryException {
271     }
272
273     /**
274      * @see TraversingItemVisitor#entering(Property, int)
275      */

276     protected void entering(Property property, int level)
277         throws RepositoryException {
278     }
279
280     /**
281      * @see TraversingItemVisitor#leaving(Node, int)
282      */

283     protected void leaving(Node node, int level)
284         throws RepositoryException {
285     }
286
287     /**
288      * @see TraversingItemVisitor#leaving(Property, int)
289      */

290     protected void leaving(Property property, int level)
291         throws RepositoryException {
292     }
293   }
294 }
295
Popular Tags