KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > dtree > DataTree


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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.dtree;
12
13 import org.eclipse.core.runtime.IPath;
14
15 /**
16  * A <code>DataTree</code> represents the complete information of a source tree.
17  * The tree contains all information within its branches, and has no relation to any
18  * other source trees (no parent and no children).
19  */

20 public class DataTree extends AbstractDataTree {
21
22     /**
23      * the root node of the tree
24      */

25     private DataTreeNode rootNode;
26
27     /**
28      * Creates a new empty tree
29      */

30     public DataTree() {
31         this.empty();
32     }
33
34     /**
35      * Returns a copy of the node subtree rooted at the given key.
36      *
37      * @param key
38      * Key of subtree to copy
39      */

40     public AbstractDataTreeNode copyCompleteSubtree(IPath key) {
41         DataTreeNode node = findNodeAt(key);
42         if (node == null) {
43             handleNotFound(key);
44         }
45         return copyHierarchy(node);
46     }
47
48     /**
49      * Returns a deep copy of a node and all its children.
50      *
51      * @param node
52      * Node to be copied.
53      */

54     DataTreeNode copyHierarchy(DataTreeNode node) {
55         DataTreeNode newNode;
56         int size = node.size();
57         if (size == 0) {
58             newNode = new DataTreeNode(node.getName(), node.getData());
59         } else {
60             AbstractDataTreeNode[] children = node.getChildren();
61             DataTreeNode[] newChildren = new DataTreeNode[size];
62             for (int i = size; --i >= 0;) {
63                 newChildren[i] = this.copyHierarchy((DataTreeNode) children[i]);
64             }
65             newNode = new DataTreeNode(node.getName(), node.getData(), newChildren);
66         }
67
68         return newNode;
69     }
70
71     /**
72      * Creates a new child in the tree.
73      * @see AbstractDataTree#createChild(IPath, String)
74      */

75     public void createChild(IPath parentKey, String JavaDoc localName) {
76         createChild(parentKey, localName, null);
77     }
78
79     /**
80      * Creates a new child in the tree.
81      * @see AbstractDataTree#createChild(IPath, String, Object)
82      */

83     public void createChild(IPath parentKey, String JavaDoc localName, Object JavaDoc data) {
84         DataTreeNode node = findNodeAt(parentKey);
85         if (node == null)
86             handleNotFound(parentKey);
87         if (this.isImmutable())
88             handleImmutableTree();
89         /* If node already exists, replace */
90         if (node.includesChild(localName)) {
91             node.replaceChild(localName, new DataTreeNode(localName, data));
92         } else {
93             this.replaceNode(parentKey, node.copyWithNewChild(localName, new DataTreeNode(localName, data)));
94         }
95     }
96
97     /**
98      * Creates and returns an instance of the receiver. This is an
99      * implementation of the factory method creational pattern for allowing
100      * abstract methods to create instances
101      */

102     protected AbstractDataTree createInstance() {
103         return new DataTree();
104     }
105
106     /**
107      * Creates or replaces a subtree in the tree. The parent node must exist.
108      *
109      * @param key
110      * Key of parent node whose subtree we want to create/replace.
111      * @param subtree
112      * New node to insert into tree.
113      */

114     public void createSubtree(IPath key, AbstractDataTreeNode subtree) {
115
116         // Copy it since destructive mods are allowed on the original
117
// and shouldn't affect this tree.
118
DataTreeNode newNode = copyHierarchy((DataTreeNode) subtree);
119
120         if (this.isImmutable()) {
121             handleImmutableTree();
122         }
123
124         if (key.isRoot()) {
125             setRootNode(newNode);
126         } else {
127             String JavaDoc localName = key.lastSegment();
128             newNode.setName(localName); // Another mod, but it's OK we've already copied
129

130             IPath parentKey = key.removeLastSegments(1);
131
132             DataTreeNode node = findNodeAt(parentKey);
133             if (node == null) {
134                 handleNotFound(parentKey);
135             }
136
137             /* If node already exists, replace */
138             if (node.includesChild(localName)) {
139                 node.replaceChild(localName, newNode);
140             }
141
142             this.replaceNode(parentKey, node.copyWithNewChild(localName, newNode));
143         }
144     }
145
146     /**
147      * Deletes a child of the tree.
148      * @see AbstractDataTree#deleteChild(IPath, String)
149      */

150     public void deleteChild(IPath parentKey, String JavaDoc localName) {
151         if (this.isImmutable())
152             handleImmutableTree();
153         DataTreeNode node = findNodeAt(parentKey);
154         if (node == null || (!node.includesChild(localName))) {
155             handleNotFound(node == null ? parentKey : parentKey.append(localName));
156         } else {
157             this.replaceNode(parentKey, node.copyWithoutChild(localName));
158         }
159     }
160
161     /**
162      * Initializes the receiver.
163      * @see AbstractDataTree#empty()
164      */

165     public void empty() {
166         this.setRootNode(new DataTreeNode(null, null));
167     }
168
169     /**
170      * Returns the specified node if it is present, otherwise returns null.
171      *
172      * @param key
173      * Key of node to return
174      */

175     public DataTreeNode findNodeAt(IPath key) {
176         AbstractDataTreeNode node = this.getRootNode();
177         int keyLength = key.segmentCount();
178         for (int i = 0; i < keyLength; i++) {
179             try {
180                 node = node.childAt(key.segment(i));
181             } catch (ObjectNotFoundException notFound) {
182                 return null;
183             }
184         }
185         return (DataTreeNode) node;
186     }
187
188     /**
189      * Returns the data at the specified node.
190      *
191      * @param key
192      * Node whose data to return.
193      */

194     public Object JavaDoc getData(IPath key) {
195         DataTreeNode node = findNodeAt(key);
196         if (node == null) {
197             handleNotFound(key);
198             return null;
199         }
200         return node.getData();
201     }
202
203     /**
204      * Returns the names of the children of a node.
205      * @see AbstractDataTree#getNamesOfChildren(IPath)
206      */

207     public String JavaDoc[] getNamesOfChildren(IPath parentKey) {
208         DataTreeNode parentNode;
209         parentNode = findNodeAt(parentKey);
210         if (parentNode == null) {
211             handleNotFound(parentKey);
212             return null;
213         }
214         return parentNode.namesOfChildren();
215     }
216
217     /**
218      * Returns the root node of the tree
219      */

220     AbstractDataTreeNode getRootNode() {
221         return rootNode;
222     }
223
224     /**
225      * Returns true if the receiver includes a node with
226      * the given key, false otherwise.
227      */

228     public boolean includes(IPath key) {
229         return (findNodeAt(key) != null);
230     }
231
232     /**
233      * Returns an object containing:
234      * - a flag indicating whether the specified node was found
235      * - the data for the node, if it was found
236      * @param key
237      * key of node for which we want to retrieve data.
238      */

239     public DataTreeLookup lookup(IPath key) {
240         DataTreeNode node = this.findNodeAt(key);
241         if (node == null)
242             return DataTreeLookup.newLookup(key, false, null);
243         return DataTreeLookup.newLookup(key, true, node.getData());
244     }
245
246     /**
247      * Replaces the node at the specified key with the given node
248      */

249     protected void replaceNode(IPath key, DataTreeNode node) {
250         DataTreeNode found;
251         if (key.isRoot()) {
252             this.setRootNode(node);
253         } else {
254             found = this.findNodeAt(key.removeLastSegments(1));
255             found.replaceChild(key.lastSegment(), node);
256         }
257     }
258
259     /**
260      * Sets the data at the specified node.
261      * @see AbstractDataTree#setData(IPath, Object)
262      */

263     public void setData(IPath key, Object JavaDoc data) {
264         DataTreeNode node = this.findNodeAt(key);
265         if (this.isImmutable())
266             handleImmutableTree();
267         if (node == null) {
268             handleNotFound(key);
269         } else {
270             node.setData(data);
271         }
272     }
273
274     /**
275      * Sets the root node of the tree
276      * @see AbstractDataTree#setRootNode(AbstractDataTreeNode)
277      */

278     void setRootNode(DataTreeNode aNode) {
279         rootNode = aNode;
280     }
281 }
282
Popular Tags