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

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

tidied up the getXXXDir methods in Utility. Utility.getCollectionDir (which returns the path to the collect directory) has been renamed to getCollectDir, and a new Utility.getCollectionDir is provided which returns the path to an individual collection's base dir

  • Property svn:keywords set to Author Date Id Revision
File size: 12.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.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 // System.err.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 if (child == null) {
222 return;
223 }
224 try {
225 children.add(index, child);
226 // Set parent and model.
227 FileNode new_child = (FileNode) child;
228 new_child.setModel(model);
229 new_child.setParent(this);
230 new_child.setReadOnly(readonly);
231 }
232 catch(Exception error) {
233 error.printStackTrace();
234 }
235 }
236
237 /** Is this file node within the currently open collection? */
238 public boolean isInCurrentCollection() {
239 if(current_collection) {
240 return true;
241 }
242 else {
243 FileNode parent = (FileNode) getParent();
244 if(parent != null) {
245 return parent.isInCurrentCollection();
246 }
247 }
248 return false;
249 }
250
251 /** Returns true if the receiver is a leaf. */
252 public boolean isLeaf() {
253 return !getAllowsChildren();
254 }
255
256 public boolean isReadOnly() {
257 return readonly;
258 }
259
260 public boolean isFileSystemRoot() {
261 boolean result = false;
262 if(file != null) {
263 result = FileSystemView.getFileSystemView().isFileSystemRoot(file);
264 }
265 return result;
266 }
267
268 public void map() {
269 if(children == null) {
270 children = new ArrayList();
271 // 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.
272 if(file == null && title.equals(Dictionary.get("Tree.World"))) {
273 ///atherer.println("Map the 'Greenstone Collections' node.");
274 // For each of the children directories, which are collections...
275 File start = new File(Utility.getCollectDir(Gatherer.config.gsdl_path));
276 File cols[] = start.listFiles();
277 ArrayTools.sort(cols);
278 // We add their import directories, except for the model collection
279 for(int i = 0; cols != null && i < cols.length; i++) {
280 if (!cols[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
281 File dirs[] = cols[i].listFiles();
282 ArrayTools.sort(dirs);
283 File import_dir = new File(cols[i], StaticStrings.IMPORT_FOLDER);
284 if(import_dir.exists()) {
285 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(new File(cols[i], Utility.CONFIG_DIR));
286 FileNode collection_root = new FileNode(import_dir, collect_cfg.toString(), true);
287 collection_root.setParent(this);
288 collection_root.setModel(model);
289 // One last piece of magic so we can determine the current collection
290 Collection collection = Gatherer.c_man.getCollection();
291 if(collection != null) {
292 collection_root.setCurrentCollection(cols[i].getName().equals(collection.getName()));
293 }
294 children.add(collection_root);
295 collection_root = null;
296 }
297 import_dir = null;
298 dirs = null;
299 }
300 }
301 cols = null;
302 model.nodeStructureChanged(this);
303 }
304 // General case: Only map if there are no children.
305 else if(file != null && getAllowsChildren()) {
306 File[] files = file.listFiles();
307 if(files != null && files.length > 0) {
308 // Sort the remaining files.
309 Gatherer.println("Number of files to sort: " + files.length);
310 ArrayTools.sort(files);
311 Gatherer.println("Files sorted.");
312 // Now add them to children.
313 raw_children = new ArrayList();
314 for(int i = 0; i < files.length; i++) {
315 FileNode child = new FileNode(files[i], model, children_readonly);
316 child.setParent(this);
317 raw_children.add(child);
318 }
319
320 // Apply the filters set in the model.
321 //if(model != null) {
322 FileFilter[] filters = model.getFilters();
323 for(int i = 0; filters != null && i < filters.length; i++) {
324 files = ArrayTools.filter(files, filters[i].filter, filters[i].exclude);
325 }
326 //}
327
328 // Now add them to children.
329 for(int i = 0; i < files.length; i++) {
330 FileNode child = new FileNode(files[i], model, children_readonly);
331 int index = -1;
332 if((index = raw_children.indexOf(child)) != -1) {
333 children.add(raw_children.get(index));
334 }
335 else {
336 child.setParent(this);
337 children.add(child);
338 }
339 }
340 }
341 model.nodeStructureChanged(this);
342 }
343 }
344 }
345
346 /** Removes the child at index from the receiver. */
347 public void remove(int index) {
348 if(0 <= index && index < children.size()) {
349 children.remove(index);
350 }
351 }
352
353 /** Removes node from the receiver. */
354 public void remove(MutableTreeNode node){
355 int index = getIndex(node);
356 if(index != -1) {
357 children.remove(index);
358 }
359 }
360
361 /** Removes the receiver from its parent. */
362 public void removeFromParent() {
363 parent.remove(this);
364 parent = null;
365 }
366
367 public void setCurrentCollection(boolean current_collection) {
368 this.current_collection = current_collection;
369 }
370
371 /* private void setChildrenReadOnly(boolean children_readonly) {
372 this.children_readonly = children_readonly;
373 } */
374
375 public void setFile(File file) {
376 this.file = file;
377 }
378
379 public void setModel(FileSystemModel model) {
380 this.model = model;
381 }
382
383 public void setParent(MutableTreeNode parent) {
384 this.parent = parent;
385 }
386
387 public void setReadOnly(boolean readonly) {
388 this.readonly = readonly;
389 }
390
391 /** Resets the user object of the receiver to object. */
392 public void setUserObject(Object object) {
393 try {
394 file = (File) object;
395 title = null;
396 }
397 catch(Exception error) {
398 error.printStackTrace();
399 }
400 }
401
402 /** Retrieve the total number of child files for the file this node represents, irrespective of filters set
403 * @return int
404 */
405 public int size() {
406 if(raw_children != null) {
407 return raw_children.size();
408 }
409 return 0;
410 }
411
412 public String toString() {
413 if(title == null) {
414 if(isFileSystemRoot()) {
415 title = file.getAbsolutePath();
416 }
417 else {
418 title = file.getName();
419 }
420 }
421 return title;
422 }
423
424 /** Unmap this nodes children. */
425 public void unmap() {
426 // You cannot unmap nodes that have no file basis.
427 if(file != null || title.equals(Dictionary.get("Tree.World"))) {
428 ///atherer.println("Unmap: " + this);
429 children = null;
430 raw_children = null;
431 }
432 else {
433 ///ystem.err.println("No file for " + this + " - can't unmap.");
434 }
435 }
436
437 private class FileEnumeration
438 implements Enumeration {
439 private int index = 0;
440 /** Tests if this enumeration contains more elements. */
441 public boolean hasMoreElements() {
442 return (index < children.size());
443 }
444 /** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
445 public Object nextElement() {
446 Object result = null;
447 if(index < children.size()) {
448 result = children.get(index);
449 index++;
450 }
451 return result;
452 }
453 }
454}
Note: See TracBrowser for help on using the repository browser.