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

Last change on this file since 8505 was 8243, checked in by mdewsnip, 20 years ago

Removed all occurrences of classes explicitly importing other classes in the same package.

  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 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.Configuration;
10import org.greenstone.gatherer.DebugStream;
11import org.greenstone.gatherer.Dictionary;
12import org.greenstone.gatherer.Gatherer;
13import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
14import org.greenstone.gatherer.collection.Collection;
15import org.greenstone.gatherer.util.ArrayTools;
16import org.greenstone.gatherer.util.StaticStrings;
17import org.greenstone.gatherer.util.Utility;
18
19public class FileNode
20 implements MutableTreeNode {
21
22 static final private int FALSE = 0;
23 static final private int TRUE = 1;
24 static final private int UNKNOWN = 2;
25
26 private ArrayList children;
27 private ArrayList raw_children;
28 private boolean children_readonly = true;
29 private boolean current_collection = false;
30 private boolean readonly = true;
31 private File file;
32 private FileSystemModel model;
33 private int allows_children = UNKNOWN;
34 private MutableTreeNode parent;
35 private String title;
36 private boolean gs3_site = false;
37
38 public FileNode(File file) {
39 // System.err.println("New FileNode(" + file.getAbsolutePath() + ")");
40 this.file = file;
41 }
42
43 public FileNode(File file, boolean readonly) {
44 this(file);
45 this.children_readonly = readonly;
46 this.readonly = readonly;
47 }
48
49 public FileNode(File file, FileSystemModel model) {
50 this(file);
51 this.model = model;
52 }
53
54 public FileNode(File file, FileSystemModel model, boolean readonly) {
55 this(file, readonly);
56 this.model = model;
57 }
58
59 public FileNode(File file, FileSystemModel model, String title) {
60 this(file, model);
61 this.title = title;
62 }
63
64 public FileNode(File file, String title) {
65 this(file);
66 this.title = title;
67 }
68
69 public FileNode(File file, String title, boolean readonly) {
70 this(file, readonly);
71 this.title = title;
72 }
73
74 public FileNode(File file, FileSystemModel model, String title, boolean readonly) {
75 this(file, model, readonly);
76 this.title = title;
77 }
78
79 /** The special 'dummy' root node, that is not based on a particular file, but instead holds several special directory mappings. */
80 public FileNode(String title) {
81 this.children = new ArrayList();
82 this.title = title;
83 }
84
85 /** Returns the children of the receiver as an Enumeration. */
86 public Enumeration children() {
87 return new FileEnumeration();
88 }
89
90 /** Compare two filenodes for equality. */
91 public boolean equals(FileNode node) {
92 boolean result = false;
93 if(node != null) {
94 if(file != null) {
95 result = (file.equals(node.getFile()));
96 }
97 else {
98 result = toString().equals(node.toString());
99 }
100 }
101 return result;
102 }
103
104 /** Retrieve the filenode at the given index, regardless of filters set.
105 * @param index int
106 */
107 public FileNode get(int index) {
108 if(0 <= index && index < size() && file != null) {
109 return (FileNode) raw_children.get(index);
110 }
111 return null;
112 }
113
114 /** 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. */
115 public boolean getAllowsChildren() {
116 if(readonly) {
117 if(allows_children == UNKNOWN) {
118 // If the file is non-null but doesn't exist (as is the case for removable media), return true anyway.
119 if(file != null) {
120 if(isFileSystemRoot()) {
121 allows_children = TRUE;
122 }
123 else if(file.exists() && file.isDirectory()) {
124 allows_children = TRUE;
125 }
126 // Any mapped directories always allow children.
127 else if(getParent() != null && getParent().getParent() == null) {
128 allows_children = TRUE;
129 }
130 else {
131 allows_children = FALSE;
132 }
133 }
134 // Allows children is always true for dummy nodes.
135 else {
136 allows_children = TRUE;
137 }
138 }
139 return (allows_children == TRUE);
140 }
141 else {
142 return (file == null || file.isDirectory());
143 }
144 }
145
146 /** Returns the child TreeNode at index childIndex. */
147 public TreeNode getChildAt(int index) {
148 TreeNode result = null;
149 map();
150 if(0 <= index && index < children.size()) {
151 result = (TreeNode) children.get(index);
152 }
153 else {
154 result = new DefaultMutableTreeNode("Error");
155 }
156 ///ystem.err.println(this + ".getChildAt(" + index + ") = " + result);
157 return result;
158 }
159
160 /** Returns the number of children TreeNodes the receiver contains. */
161 public int getChildCount() {
162 int size = 0;
163 // We don't automatically map if this is a system root, or we risk the 50,000 Disk not found error messages of death.
164 if(isFileSystemRoot()) {
165 size = 1; // Size is always non-zero for a system root
166 }
167 else {
168 map();
169 }
170 if(children != null) {
171 size = children.size();
172 }
173 ///ystem.err.println(this + ".getChildCount() = " + size);
174 return size;
175 }
176
177 public File getFile() {
178 return file;
179 }
180
181 /** Returns the index of node in the receivers children. */
182 public int getIndex(TreeNode node) {
183 map();
184 return children.indexOf(node);
185 }
186
187 /** Returns the parent TreeNode of the receiver. */
188 public TreeNode getParent() {
189 return parent;
190 }
191
192 /** Retrieves the tree path from the root node to this node. */
193 public TreeNode[] getPath() {
194 int count = 0;
195 TreeNode current = this;
196 while(current != null) {
197 count++;
198 current = current.getParent();
199 }
200 TreeNode[] path = new TreeNode[count];
201 current = this;
202 while(current != null) {
203 path[count - 1] = current;
204 count--;
205 current = current.getParent();
206 }
207 return path;
208 }
209
210 public void insert(MutableTreeNode child) {
211 insert(child, children.size());
212 }
213
214 /** Adds child to the receiver at index. */
215 public void insert(MutableTreeNode child, int index) {
216 DebugStream.println("Insert " + child + " in " + this + " at index " + index + " [Model: " + model + "]");
217 if (child == null) {
218 return;
219 }
220 try {
221 children.add(index, child);
222 // Set parent and model.
223 FileNode new_child = (FileNode) child;
224 new_child.setModel(model);
225 new_child.setParent(this);
226 new_child.setReadOnly(readonly);
227 }
228 catch(Exception error) {
229 error.printStackTrace();
230 }
231 }
232
233 /** Is this file node within the currently open collection? */
234 public boolean isInCurrentCollection() {
235 if(current_collection) {
236 return true;
237 }
238 else {
239 FileNode parent = (FileNode) getParent();
240 if(parent != null) {
241 return parent.isInCurrentCollection();
242 }
243 }
244 return false;
245 }
246
247 /** Returns true if the receiver is a leaf. */
248 public boolean isLeaf() {
249 return !getAllowsChildren();
250 }
251
252 public boolean isReadOnly() {
253 return readonly;
254 }
255
256 public boolean isFileSystemRoot() {
257 boolean result = false;
258 if(file != null) {
259 result = FileSystemView.getFileSystemView().isFileSystemRoot(file);
260 }
261 return result;
262 }
263
264 public void map() {
265 if(children != null) {
266 return;
267 }
268 children = new ArrayList();
269 // Super Special Case: if the name of this node is the Tree.World string, then we actually map the collections installed in greenstone. The file in this case will actually be the collect directory of greenstone.
270 if(file == null) { // a special mapping folder
271 if (title.equals(Dictionary.get("Tree.World")) && Gatherer.GS3) {
272 // the Greenstone collections folder for GS3 - this contains a
273 // folder for each site
274 File start = new File(Utility.getSitesDir(Configuration.gsdl3_path));
275 File sites[] = start.listFiles();
276 ArrayTools.sort(sites);
277 for (int i=0; sites != null && i < sites.length; i++) {
278 //File site = sites[i];
279 File collect_dir = new File(sites[i], Utility.COL_DIR);
280 if(!collect_dir.exists()) {
281 continue;
282 }
283
284 FileNode child = new FileNode(sites[i].getName());
285 child.setGS3Site(true);
286 child.unmap();
287 child.setParent(this);
288 child.setModel(model);
289 child.map();
290 children.add(child);
291 }
292
293 } else if (title.equals(Dictionary.get("Tree.World")) || gs3_site) {
294 // the collect dir for gs2 or a site dir for gs3
295 ///atherer.println("Map the 'Greenstone Collections' node.");
296 // For each of the children directories, which are collections...
297 File start;
298 if (gs3_site) {
299 start = new File(Utility.getCollectDir(Configuration.gsdl3_path, title));
300 } else {
301 start = new File(Utility.getCollectDir(Configuration.gsdl_path));
302 }
303 File cols[] = start.listFiles();
304 ArrayTools.sort(cols);
305 // We add their import directories, except for the model collection
306 for(int i = 0; cols != null && i < cols.length; i++) {
307 if (!cols[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
308 //File dirs[] = cols[i].listFiles();
309 //ArrayTools.sort(dirs);
310 File import_dir = new File(cols[i], StaticStrings.IMPORT_FOLDER);
311 if(!import_dir.exists()) {
312 continue;
313 }
314 // we don't care if there is no config file
315 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(new File(cols[i], Utility.CONFIG_FILE));
316 FileNode collection_root = new FileNode(import_dir, collect_cfg.toString(), true);
317 collection_root.setParent(this);
318 collection_root.setModel(model);
319 // One last piece of magic so we can determine the current collection
320 Collection collection = Gatherer.c_man.getCollection();
321 if(collection != null) {
322 collection_root.setCurrentCollection(cols[i].getName().equals(collection.getName()));
323 }
324 children.add(collection_root);
325 collection_root = null;
326 import_dir = null;
327 //dirs = null;
328 }
329 } // for each coll
330 cols = null;
331 model.nodeStructureChanged(this);
332 }
333 } // if file == null
334 // General case: Only map if there are no children.
335 else { // file !=null
336 if(getAllowsChildren()) {
337 File[] files = file.listFiles();
338 if(files != null && files.length > 0) {
339 // Sort the remaining files.
340 DebugStream.println("Number of files to sort: " + files.length);
341 ArrayTools.sort(files);
342 DebugStream.println("Files sorted.");
343 // Now add them to children.
344 raw_children = new ArrayList();
345 for(int i = 0; i < files.length; i++) {
346 FileNode child = new FileNode(files[i], model, children_readonly);
347 child.setParent(this);
348 raw_children.add(child);
349 }
350
351 // Apply the filters set in the model.
352 //if(model != null) {
353 FileFilter[] filters = model.getFilters();
354 for(int i = 0; filters != null && i < filters.length; i++) {
355 files = ArrayTools.filter(files, filters[i].filter, filters[i].exclude);
356 }
357 //}
358
359 // Now add them to children.
360 for(int i = 0; i < files.length; i++) {
361 FileNode child = new FileNode(files[i], model, children_readonly);
362 int index = -1;
363 if((index = raw_children.indexOf(child)) != -1) {
364 children.add(raw_children.get(index));
365 }
366 else {
367 child.setParent(this);
368 children.add(child);
369 }
370 }
371 }
372 model.nodeStructureChanged(this);
373 }
374 }
375
376 }
377
378 /** Removes the child at index from the receiver. */
379 public void remove(int index) {
380 if(0 <= index && index < children.size()) {
381 children.remove(index);
382 }
383 }
384
385 /** Removes node from the receiver. */
386 public void remove(MutableTreeNode node){
387 int index = getIndex(node);
388 if(index != -1) {
389 children.remove(index);
390 }
391 }
392
393 /** Removes the receiver from its parent. */
394 public void removeFromParent() {
395 parent.remove(this);
396 parent = null;
397 }
398
399 public void setCurrentCollection(boolean current_collection) {
400 this.current_collection = current_collection;
401 }
402
403 public void setFile(File file) {
404 this.file = file;
405 }
406
407 public void setGS3Site(boolean is_site) {
408 this.gs3_site = is_site;
409 }
410
411 public void setModel(FileSystemModel model) {
412 this.model = model;
413 }
414
415 public void setParent(MutableTreeNode parent) {
416 this.parent = parent;
417 }
418
419 public void setReadOnly(boolean readonly) {
420 this.readonly = readonly;
421 }
422
423 /** Resets the user object of the receiver to object. */
424 public void setUserObject(Object object) {
425 try {
426 file = (File) object;
427 title = null;
428 }
429 catch(Exception error) {
430 error.printStackTrace();
431 }
432 }
433
434 /** Retrieve the total number of child files for the file this node represents, irrespective of filters set
435 * @return int
436 */
437 public int size() {
438 if(raw_children != null) {
439 return raw_children.size();
440 }
441 return 0;
442 }
443
444 public String toString() {
445 if(title == null) {
446 if(isFileSystemRoot()) {
447 title = file.getAbsolutePath();
448 }
449 else {
450 title = file.getName();
451 }
452 }
453 return title;
454 }
455
456 /** Unmap this nodes children. */
457 public void unmap() {
458 // You cannot unmap nodes that have no file basis.
459 if(file != null || title.equals(Dictionary.get("Tree.World")) || gs3_site) {
460 ///atherer.println("Unmap: " + this);
461 children = null;
462 raw_children = null;
463 }
464 else {
465 ///ystem.err.println("No file for " + this + " - can't unmap.");
466 }
467 }
468
469
470 public void refresh()
471 {
472 unmap();
473 map();
474 }
475
476
477 private class FileEnumeration
478 implements Enumeration {
479 private int index = 0;
480 /** Tests if this enumeration contains more elements. */
481 public boolean hasMoreElements() {
482 return (index < children.size());
483 }
484 /** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
485 public Object nextElement() {
486 Object result = null;
487 if(index < children.size()) {
488 result = children.get(index);
489 index++;
490 }
491 return result;
492 }
493 }
494}
Note: See TracBrowser for help on using the repository browser.