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

Last change on this file since 6622 was 6622, checked in by jmt12, 20 years ago

More modifications to mirroring including testing for a valid version of Wget (and complaining if its missing or it is old) and rearranging buttons on the GProgressBar

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