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

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

Forgot to set model when adding children nodes during a collection root mapping.

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