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

Last change on this file since 4377 was 4377, checked in by jmt12, 21 years ago

Added isFileSystemRoot() method - John

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