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

Last change on this file since 7326 was 7326, checked in by kjdon, 20 years ago

the intial stage of making gli work with gs3 - still uses gs2 building, but uses colls in gs3 setup

  • Property svn:keywords set to Author Date Id Revision
File size: 13.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.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 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 /** Retrieve the icon the system thinks should be assigned to this node. If this node has no file then the icon will be null. */
182 public ImageIcon getIcon() {
183 return null;
184 }
185
186 /** Returns the index of node in the receivers children. */
187 public int getIndex(TreeNode node) {
188 map();
189 return children.indexOf(node);
190 }
191
192 /** Returns the parent TreeNode of the receiver. */
193 public TreeNode getParent() {
194 return parent;
195 }
196
197 /** Retrieves the tree path from the root node to this node. */
198 public TreeNode[] getPath() {
199 int count = 0;
200 TreeNode current = this;
201 while(current != null) {
202 count++;
203 current = current.getParent();
204 }
205 TreeNode[] path = new TreeNode[count];
206 current = this;
207 while(current != null) {
208 path[count - 1] = current;
209 count--;
210 current = current.getParent();
211 }
212 return path;
213 }
214
215 public void insert(MutableTreeNode child) {
216 insert(child, children.size());
217 }
218
219 /** Adds child to the receiver at index. */
220 public void insert(MutableTreeNode child, int index) {
221 Gatherer.println("Insert " + child + " in " + this + " at index " + index + " [Model: " + model + "]");
222 if (child == null) {
223 return;
224 }
225 try {
226 children.add(index, child);
227 // Set parent and model.
228 FileNode new_child = (FileNode) child;
229 new_child.setModel(model);
230 new_child.setParent(this);
231 new_child.setReadOnly(readonly);
232 }
233 catch(Exception error) {
234 error.printStackTrace();
235 }
236 }
237
238 /** Is this file node within the currently open collection? */
239 public boolean isInCurrentCollection() {
240 if(current_collection) {
241 return true;
242 }
243 else {
244 FileNode parent = (FileNode) getParent();
245 if(parent != null) {
246 return parent.isInCurrentCollection();
247 }
248 }
249 return false;
250 }
251
252 /** Returns true if the receiver is a leaf. */
253 public boolean isLeaf() {
254 return !getAllowsChildren();
255 }
256
257 public boolean isReadOnly() {
258 return readonly;
259 }
260
261 public boolean isFileSystemRoot() {
262 boolean result = false;
263 if(file != null) {
264 result = FileSystemView.getFileSystemView().isFileSystemRoot(file);
265 }
266 return result;
267 }
268
269 public void map() {
270 if(children != null) {
271 return;
272 }
273 children = new ArrayList();
274 // 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.
275 if(file == null) { // a special mapping folder
276 if (title.equals(Dictionary.get("Tree.World")) && Gatherer.GS3) {
277 // the Greenstone collections folder for GS3 - this contains a
278 // folder for each site
279 File start = new File(Utility.getSitesDir(Gatherer.config.gsdl3_path));
280 File sites[] = start.listFiles();
281 ArrayTools.sort(sites);
282 for (int i=0; sites != null && i < sites.length; i++) {
283 //File site = sites[i];
284 File collect_dir = new File(sites[i], Utility.COL_DIR);
285 if(!collect_dir.exists()) {
286 continue;
287 }
288
289 FileNode child = new FileNode(sites[i].getName());
290 child.setGS3Site(true);
291 child.unmap();
292 child.setParent(this);
293 child.setModel(model);
294 child.map();
295 children.add(child);
296 }
297
298 } else if (title.equals(Dictionary.get("Tree.World")) || gs3_site) {
299 // the collect dir for gs2 or a site dir for gs3
300 ///atherer.println("Map the 'Greenstone Collections' node.");
301 // For each of the children directories, which are collections...
302 File start;
303 if (gs3_site) {
304 start = new File(Utility.getCollectDir(Gatherer.config.gsdl3_path, title));
305 } else {
306 start = new File(Utility.getCollectDir(Gatherer.config.gsdl_path));
307 }
308 File cols[] = start.listFiles();
309 ArrayTools.sort(cols);
310 // We add their import directories, except for the model collection
311 for(int i = 0; cols != null && i < cols.length; i++) {
312 if (!cols[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
313 //File dirs[] = cols[i].listFiles();
314 //ArrayTools.sort(dirs);
315 File import_dir = new File(cols[i], StaticStrings.IMPORT_FOLDER);
316 if(!import_dir.exists()) {
317 continue;
318 }
319 // we don't care if there is no config file
320 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(new File(cols[i], Utility.CONFIG_FILE));
321 FileNode collection_root = new FileNode(import_dir, collect_cfg.toString(), true);
322 collection_root.setParent(this);
323 collection_root.setModel(model);
324 // One last piece of magic so we can determine the current collection
325 Collection collection = Gatherer.c_man.getCollection();
326 if(collection != null) {
327 collection_root.setCurrentCollection(cols[i].getName().equals(collection.getName()));
328 }
329 children.add(collection_root);
330 collection_root = null;
331 import_dir = null;
332 //dirs = null;
333 }
334 } // for each coll
335 cols = null;
336 model.nodeStructureChanged(this);
337 }
338 } // if file == null
339 // General case: Only map if there are no children.
340 else { // file !=null
341 if(getAllowsChildren()) {
342 File[] files = file.listFiles();
343 if(files != null && files.length > 0) {
344 // Sort the remaining files.
345 Gatherer.println("Number of files to sort: " + files.length);
346 ArrayTools.sort(files);
347 Gatherer.println("Files sorted.");
348 // Now add them to children.
349 raw_children = new ArrayList();
350 for(int i = 0; i < files.length; i++) {
351 FileNode child = new FileNode(files[i], model, children_readonly);
352 child.setParent(this);
353 raw_children.add(child);
354 }
355
356 // Apply the filters set in the model.
357 //if(model != null) {
358 FileFilter[] filters = model.getFilters();
359 for(int i = 0; filters != null && i < filters.length; i++) {
360 files = ArrayTools.filter(files, filters[i].filter, filters[i].exclude);
361 }
362 //}
363
364 // Now add them to children.
365 for(int i = 0; i < files.length; i++) {
366 FileNode child = new FileNode(files[i], model, children_readonly);
367 int index = -1;
368 if((index = raw_children.indexOf(child)) != -1) {
369 children.add(raw_children.get(index));
370 }
371 else {
372 child.setParent(this);
373 children.add(child);
374 }
375 }
376 }
377 model.nodeStructureChanged(this);
378 }
379 }
380
381 }
382
383 /** Removes the child at index from the receiver. */
384 public void remove(int index) {
385 if(0 <= index && index < children.size()) {
386 children.remove(index);
387 }
388 }
389
390 /** Removes node from the receiver. */
391 public void remove(MutableTreeNode node){
392 int index = getIndex(node);
393 if(index != -1) {
394 children.remove(index);
395 }
396 }
397
398 /** Removes the receiver from its parent. */
399 public void removeFromParent() {
400 parent.remove(this);
401 parent = null;
402 }
403
404 public void setCurrentCollection(boolean current_collection) {
405 this.current_collection = current_collection;
406 }
407
408 /* private void setChildrenReadOnly(boolean children_readonly) {
409 this.children_readonly = children_readonly;
410 } */
411
412 public void setFile(File file) {
413 this.file = file;
414 }
415
416 public void setGS3Site(boolean is_site) {
417 this.gs3_site = is_site;
418 }
419
420 public void setModel(FileSystemModel model) {
421 this.model = model;
422 }
423
424 public void setParent(MutableTreeNode parent) {
425 this.parent = parent;
426 }
427
428 public void setReadOnly(boolean readonly) {
429 this.readonly = readonly;
430 }
431
432 /** Resets the user object of the receiver to object. */
433 public void setUserObject(Object object) {
434 try {
435 file = (File) object;
436 title = null;
437 }
438 catch(Exception error) {
439 error.printStackTrace();
440 }
441 }
442
443 /** Retrieve the total number of child files for the file this node represents, irrespective of filters set
444 * @return int
445 */
446 public int size() {
447 if(raw_children != null) {
448 return raw_children.size();
449 }
450 return 0;
451 }
452
453 public String toString() {
454 if(title == null) {
455 if(isFileSystemRoot()) {
456 title = file.getAbsolutePath();
457 }
458 else {
459 title = file.getName();
460 }
461 }
462 return title;
463 }
464
465 /** Unmap this nodes children. */
466 public void unmap() {
467 // You cannot unmap nodes that have no file basis.
468 if(file != null || title.equals(Dictionary.get("Tree.World")) || gs3_site) {
469 ///atherer.println("Unmap: " + this);
470 children = null;
471 raw_children = null;
472 }
473 else {
474 ///ystem.err.println("No file for " + this + " - can't unmap.");
475 }
476 }
477
478 private class FileEnumeration
479 implements Enumeration {
480 private int index = 0;
481 /** Tests if this enumeration contains more elements. */
482 public boolean hasMoreElements() {
483 return (index < children.size());
484 }
485 /** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
486 public Object nextElement() {
487 Object result = null;
488 if(index < children.size()) {
489 result = children.get(index);
490 index++;
491 }
492 return result;
493 }
494 }
495}
Note: See TracBrowser for help on using the repository browser.