KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > watson > ElementTreeIterator


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.watson;
12
13 import org.eclipse.core.internal.dtree.AbstractDataTreeNode;
14 import org.eclipse.core.internal.dtree.DataTreeNode;
15 import org.eclipse.core.runtime.IPath;
16 import org.eclipse.core.runtime.Path;
17
18 /**
19  * A class for performing operations on each element in an element tree.
20  * For example, this can be used to print the contents of a tree.
21  * <p>
22  * When creating an ElementTree iterator, an element tree and root path must be
23  * supplied. When the <code>iterate()</code> method is called, a visitor object
24  * must be provided. The visitor is called once for each node of the tree. For
25  * each node, the visitor is passed the entire tree, the object in the tree at
26  * that node, and a callback for requesting the full path of that node.
27  * <p>
28  * <b>Example:</b>
29  <code><pre>
30  // printing a crude representation of the poster child
31  IElementContentVisitor visitor=
32  new IElementContentVisitor() {
33  public void visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) {
34  System.out.println(requestor.requestPath() + " -> " + elementContent);
35  }
36  });
37  ElementTreeIterator iterator = new ElementTreeIterator(tree, Path.ROOT);
38  iterator.iterate(visitor);
39  </pre></code>
40  */

41 public class ElementTreeIterator implements IPathRequestor {
42     //for path requestor
43
private String JavaDoc[] segments = new String JavaDoc[10];
44     private int nextFreeSegment;
45
46     /* the tree being visited */
47     private ElementTree tree;
48
49     /* the root of the subtree to visit */
50     private IPath path;
51
52     /* the immutable data tree being visited */
53     private DataTreeNode treeRoot;
54
55     /**
56      * Creates a new element tree iterator for visiting the given tree starting
57      * at the given path.
58      */

59     public ElementTreeIterator(ElementTree tree, IPath path) {
60         this.tree = tree;
61         this.path = path;
62         //treeRoot can be null if deleted concurrently
63
//must copy the tree while owning the tree's monitor to prevent concurrent deletion while creating visitor's copy
64
synchronized (tree) {
65             treeRoot = (DataTreeNode) tree.getDataTree().safeCopyCompleteSubtree(path);
66         }
67     }
68
69     /**
70      * Iterates through the given element tree and visit each element (node)
71      * passing in the element's ID and element object.
72      */

73     private void doIteration(DataTreeNode node, IElementContentVisitor visitor) {
74         //push the name of this node to the requestor stack
75
if (nextFreeSegment >= segments.length) {
76             grow();
77         }
78         segments[nextFreeSegment++] = node.getName();
79
80         //do the visit
81
if (visitor.visitElement(tree, this, node.getData())) {
82             //recurse
83
AbstractDataTreeNode[] children = node.getChildren();
84             for (int i = children.length; --i >= 0;) {
85                 doIteration((DataTreeNode) children[i], visitor);
86             }
87         }
88
89         //pop the segment from the requestor stack
90
nextFreeSegment--;
91         if (nextFreeSegment < 0)
92             nextFreeSegment = 0;
93     }
94
95     /**
96      * Method grow.
97      */

98     private void grow() {
99         //grow the segments array
100
int oldLen = segments.length;
101         String JavaDoc[] newPaths = new String JavaDoc[oldLen * 2];
102         System.arraycopy(segments, 0, newPaths, 0, oldLen);
103         segments = newPaths;
104     }
105
106     /**
107      * Iterates through this iterator's tree and visits each element in the
108      * subtree rooted at the given path. The visitor is passed each element's
109      * data and a request callback for obtaining the path.
110      */

111     public void iterate(IElementContentVisitor visitor) {
112         if (path.isRoot()) {
113             //special visit for root element to use special treeData
114
if (visitor.visitElement(tree, this, tree.getTreeData())) {
115                 if (treeRoot == null)
116                     return;
117                 AbstractDataTreeNode[] children = treeRoot.getChildren();
118                 for (int i = children.length; --i >= 0;) {
119                     doIteration((DataTreeNode) children[i], visitor);
120                 }
121             }
122         } else {
123             if (treeRoot == null)
124                 return;
125             push(path, path.segmentCount() - 1);
126             doIteration(treeRoot, visitor);
127         }
128     }
129
130     /**
131      * Push the first "toPush" segments of this path.
132      */

133     private void push(IPath pathToPush, int toPush) {
134         if (toPush <= 0)
135             return;
136         for (int i = 0; i < toPush; i++) {
137             if (nextFreeSegment >= segments.length) {
138                 grow();
139             }
140             segments[nextFreeSegment++] = pathToPush.segment(i);
141         }
142     }
143
144     public String JavaDoc requestName() {
145         if (nextFreeSegment == 0)
146             return ""; //$NON-NLS-1$
147
return segments[nextFreeSegment - 1];
148     }
149
150     public IPath requestPath() {
151         if (nextFreeSegment == 0)
152             return Path.ROOT;
153         int length = nextFreeSegment;
154         for (int i = 0; i < nextFreeSegment; i++) {
155             length += segments[i].length();
156         }
157         StringBuffer JavaDoc pathBuf = new StringBuffer JavaDoc(length);
158         for (int i = 0; i < nextFreeSegment; i++) {
159             pathBuf.append('/');
160             pathBuf.append(segments[i]);
161         }
162         return new Path(null, pathBuf.toString());
163     }
164 }
165
Popular Tags