source: trunk/gli/src/org/greenstone/gatherer/file/FileNode.java@ 10007

Last change on this file since 10007 was 8856, checked in by mdewsnip, 19 years ago

Now only creates one FileNode for each child, rather than having one for each unfiltered child and another for each filtered child.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1package org.greenstone.gatherer.file;
2
3import java.io.*;
4import java.util.ArrayList;
5import java.util.Enumeration;
6import javax.swing.*;
7import javax.swing.filechooser.*;
8import javax.swing.tree.*;
9import org.greenstone.gatherer.DebugStream;
10import org.greenstone.gatherer.util.ArrayTools;
11
12
13public abstract class FileNode
14 implements MutableTreeNode
15{
16 protected boolean allows_children = true;
17 protected ArrayList child_nodes = null;
18 protected ArrayList child_nodes_unfiltered = null;
19 protected File file = null;
20 protected FileSystemModel model = null;
21 protected MutableTreeNode parent = null;
22
23
24 public FileNode(File file)
25 {
26 this.file = file;
27
28 // Files cannot have children
29 if (file != null && file.isFile()) {
30 // Cache this result to prevent unceasing missing disk messages being thrown if the
31 // removable media was, um, removed after directory mapped
32 this.allows_children = false;
33 }
34 }
35
36
37 /** Returns the children of the node as an Enumeration. */
38 public Enumeration children()
39 {
40 return new FileEnumeration();
41 }
42
43
44 /** Returns true if the receiver allows children. */
45 public boolean getAllowsChildren()
46 {
47 return allows_children;
48 }
49
50
51 /** Returns the child TreeNode at index childIndex. */
52 public TreeNode getChildAt(int index)
53 {
54 return (TreeNode) child_nodes.get(index);
55 }
56
57
58 /** Returns the number of children TreeNodes the receiver contains. */
59 public int getChildCount()
60 {
61 int size = 0;
62
63 // We don't map if this is a system root, or we risk the 50,000 Disk not found error messages of death
64 if (isFileSystemRoot()) {
65 size = 1; // Size is always non-zero for a system root
66 }
67 else {
68 map();
69 }
70
71 // Use the number of (filtered) child nodes
72 if (child_nodes != null) {
73 size = child_nodes.size();
74 }
75
76 return size;
77 }
78
79
80 /** Returns the index of node in the receivers children. */
81 public int getIndex(TreeNode node)
82 {
83 if (child_nodes != null) {
84 return child_nodes.indexOf(node);
85 }
86
87 return -1;
88 }
89
90
91 /** Returns the parent TreeNode of the receiver. */
92 public TreeNode getParent()
93 {
94 return parent;
95 }
96
97
98 /** Adds child to the receiver at index. */
99 public void insert(MutableTreeNode child, int index)
100 {
101 DebugStream.println("Insert " + child + " in " + this + " at index " + index + " [Model: " + model + "]");
102 if (child == null) {
103 return;
104 }
105
106 try {
107 FileNode child_node = (FileNode) child;
108 child_nodes.add(index, child_node);
109 child_node.model = model;
110 child_node.parent = this;
111 }
112 catch (Exception exception) {
113 DebugStream.printStackTrace(exception);
114 }
115 }
116
117
118 /** Returns true if the receiver is a leaf. */
119 public boolean isLeaf()
120 {
121 return (allows_children == false);
122 }
123
124
125 /** Removes the child at index from the receiver. */
126 public void remove(int index)
127 {
128 if (index >= 0 && index < child_nodes.size()) {
129 child_nodes.remove(index);
130 }
131 }
132
133
134 /** Removes node from the receiver. */
135 public void remove(MutableTreeNode node)
136 {
137 remove(getIndex(node));
138 }
139
140
141 /** Removes the receiver from its parent. */
142 public void removeFromParent()
143 {
144 parent.remove(this);
145 parent = null;
146 }
147
148
149 /** Resets the user object of the receiver to object. */
150 public void setUserObject(Object object) {
151 try {
152 file = (File) object;
153 }
154 catch (Exception exception) {
155 DebugStream.printStackTrace(exception);
156 }
157 }
158
159
160 // -------------------------------------------------------------------------------
161
162
163 public void add(MutableTreeNode child)
164 {
165 insert(child, child_nodes.size());
166 }
167
168
169 protected abstract FileNode addChildNode(File file);
170
171
172 /** Compare two FileNodes for equality. */
173 public boolean equals(FileNode node)
174 {
175 if (node == null) {
176 // Definitely not a match
177 return false;
178 }
179
180 if (file != null) {
181 return file.equals(node.getFile());
182 }
183 else {
184 return toString().equals(node.toString());
185 }
186 }
187
188
189 /** Retrieve the file node at the given index, regardless of filters set. */
190 public FileNode getChildAtUnfiltered(int index)
191 {
192 if (index >= 0 && index < size()) {
193 return (FileNode) child_nodes_unfiltered.get(index);
194 }
195 return null;
196 }
197
198
199 public File getFile() {
200 return file;
201 }
202
203
204 /** Retrieves the tree path from the root node to this node. */
205 public TreeNode[] getPath() {
206 int count = 0;
207 TreeNode current = this;
208 while(current != null) {
209 count++;
210 current = current.getParent();
211 }
212 TreeNode[] path = new TreeNode[count];
213 current = this;
214 while(current != null) {
215 path[count - 1] = current;
216 count--;
217 current = current.getParent();
218 }
219 return path;
220 }
221
222
223 public boolean isFileSystemRoot() {
224 if (file != null) {
225 return FileSystemView.getFileSystemView().isFileSystemRoot(file);
226 }
227 else {
228 return false;
229 }
230 }
231
232
233 /** Overridden if necessary by subclasses. */
234 public boolean isInLoadedCollection()
235 {
236 return false;
237 }
238
239
240 /** Overridden if necessary by subclasses. */
241 public boolean isReadOnly()
242 {
243 return false;
244 }
245
246
247 public void map()
248 {
249 // If this node has already been mapped, don't bother doing it again
250 if (child_nodes != null) {
251 return;
252 }
253 child_nodes = new ArrayList();
254
255 // General case, only map if children are allowed
256 if (file != null && getAllowsChildren()) {
257 File[] files = file.listFiles();
258 if (files != null && files.length > 0) {
259 // Sort the child files
260 ArrayTools.sort(files);
261
262 // Now add them to child_nodes_unfiltered
263 child_nodes_unfiltered = new ArrayList();
264 for (int i = 0; i < files.length; i++) {
265 FileNode child_node = this.addChildNode(files[i]);
266 child_nodes_unfiltered.add(child_node);
267 }
268
269 // Apply the filters set in the model
270 FileFilter[] filters = model.getFilters();
271 for (int i = 0; filters != null && i < filters.length; i++) {
272 files = ArrayTools.filter(files, filters[i].filter, filters[i].exclude);
273 }
274
275 // Add the files left after filtering to child_nodes
276 for (int i = 0; i < files.length; i++) {
277 // Use the FileNode object in child_nodes_unfiltered rather than creating another
278 for (int j = 0; j < child_nodes_unfiltered.size(); j++) {
279 if (((FileNode) child_nodes_unfiltered.get(j)).getFile().equals(files[i])) {
280 child_nodes.add(child_nodes_unfiltered.get(j));
281 break;
282 }
283 }
284 }
285 }
286
287 model.nodeStructureChanged(this);
288 }
289 }
290
291
292 public void refresh()
293 {
294 unmap();
295 map();
296 }
297
298
299 public void setModel(FileSystemModel model) {
300 this.model = model;
301 }
302
303 public void setParent(MutableTreeNode parent) {
304 this.parent = parent;
305 }
306
307
308 /** Return the total number of child files for the file this node represents, irrespective of filters set. */
309 public int size() {
310 if (child_nodes_unfiltered != null) {
311 return child_nodes_unfiltered.size();
312 }
313 return 0;
314 }
315
316
317 public String toString()
318 {
319 if (isFileSystemRoot()) {
320 return file.getAbsolutePath();
321 }
322 else {
323 return file.getName();
324 }
325 }
326
327
328 /** Unmap this node's children. */
329 public void unmap()
330 {
331 DebugStream.println("Unmapping " + this + "...");
332 child_nodes_unfiltered = null;
333 child_nodes = null;
334 }
335
336
337 private class FileEnumeration
338 implements Enumeration
339 {
340 private int index = 0;
341
342 /** Tests if this enumeration contains more elements. */
343 public boolean hasMoreElements() {
344 return (index < child_nodes.size());
345 }
346
347 /** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
348 public Object nextElement() {
349 Object result = null;
350 if (index < child_nodes.size()) {
351 result = child_nodes.get(index);
352 index++;
353 }
354 return result;
355 }
356 }
357}
Note: See TracBrowser for help on using the repository browser.