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

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

Fixed NPE when a file in a folder was selected and the folder was closed.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 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 FileNode child_node = this.addChildNode(files[i]);
278 for (int j = 0; j < child_nodes_unfiltered.size(); j++) {
279 if (((FileNode) child_nodes_unfiltered.get(j)).equals(child_node)) {
280 child_nodes.add(child_nodes_unfiltered.get(j));
281 }
282 }
283 }
284 }
285
286 model.nodeStructureChanged(this);
287 }
288 }
289
290
291 public void refresh()
292 {
293 unmap();
294 map();
295 }
296
297
298 public void setModel(FileSystemModel model) {
299 this.model = model;
300 }
301
302 public void setParent(MutableTreeNode parent) {
303 this.parent = parent;
304 }
305
306
307 /** Return the total number of child files for the file this node represents, irrespective of filters set. */
308 public int size() {
309 if (child_nodes_unfiltered != null) {
310 return child_nodes_unfiltered.size();
311 }
312 return 0;
313 }
314
315
316 public String toString()
317 {
318 if (isFileSystemRoot()) {
319 return file.getAbsolutePath();
320 }
321 else {
322 return file.getName();
323 }
324 }
325
326
327 /** Unmap this node's children. */
328 public void unmap()
329 {
330 DebugStream.println("Unmapping " + this + "...");
331 child_nodes_unfiltered = null;
332 child_nodes = null;
333 }
334
335
336 private class FileEnumeration
337 implements Enumeration
338 {
339 private int index = 0;
340
341 /** Tests if this enumeration contains more elements. */
342 public boolean hasMoreElements() {
343 return (index < child_nodes.size());
344 }
345
346 /** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
347 public Object nextElement() {
348 Object result = null;
349 if (index < child_nodes.size()) {
350 result = child_nodes.get(index);
351 index++;
352 }
353 return result;
354 }
355 }
356}
Note: See TracBrowser for help on using the repository browser.