source: trunk/gli/src/org/greenstone/gatherer/msm/GDMManager.java@ 6318

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

Changed JButtons for GLIButtons, which know whether they should paint their background depending on what platform they are run on, and finished keyboard shortcuts

  • Property svn:keywords set to Author Date Id Revision
File size: 25.8 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.msm;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.io.*;
42import java.util.*;
43import javax.swing.*;
44import javax.swing.event.*;
45import javax.swing.tree.*;
46import org.greenstone.gatherer.Gatherer;
47import org.greenstone.gatherer.file.FileNode;
48import org.greenstone.gatherer.gui.GLIButton;
49import org.greenstone.gatherer.gui.MetaEditPrompt;
50import org.greenstone.gatherer.msm.ElementWrapper;
51import org.greenstone.gatherer.msm.GDMDocument;
52import org.greenstone.gatherer.msm.GDMParser;
53import org.greenstone.gatherer.msm.Metadata;
54import org.greenstone.gatherer.msm.MSMEvent;
55import org.greenstone.gatherer.msm.MSMListener;
56import org.greenstone.gatherer.util.DOMTree;
57import org.greenstone.gatherer.util.HashMap3D;
58import org.greenstone.gatherer.util.StaticStrings;
59import org.greenstone.gatherer.util.Utility;
60import org.w3c.dom.*;
61
62/** This object manages the metadata attached to file records. By storing all of the metadata in one place you garner several advantages. Firstly only one copy of each metadata object is retained, all actual entries are converted to references. Next you can immediately determine what metadata is assigned to an entire directory, thus the metadata.xml files can be built more effeciently (whereas the current 'optimal' method uses recursion through the tree contents). Finally, and perhaps most importantly, it allows for dynamic 'on demand' lookup of metadata. This is especially necessary with large collections, where the raw, unconnected metadata files could range into the tens of megabytes of memory and require hundreds of megabytes to read by in using serialization. Dynamic loading allows you to connect the metadata objects on load, reducing value node paths (possibly of hundreds of characters) down to a single reference pointer! At the very worst this object uses far less memory than the current method, and given that the current method is completely incapable of handling large collections, is necessary. The trade off of course is in time needed to load metadata.xml on demand, the worst possible case being the user selecting the root node of the collection tree of a large collection immediately after opening the collection. The subsequent attempt to build the metadata table will result in the metadata being loaded for every single file. But since this process is sequential and a small cache of metadata.xml files is implemented, and given that the table will actually be build on a separate thread, the wait should not be too arduous.<BR>
63 As for the size of the GDMParser cache, I was at first tempted to put around five. However after analysis of cache usage, I determined that no gain occured because of caching (in fact if everythings working as it should there should only ever be one call for a certain metadata.xml).
64*/
65public class GDMManager
66 extends LinkedHashMap
67 implements MSMListener {
68 /** A list of the known metadata instances, thus we only store one of each unique metadata, and reference the rest. */
69 static public HashMap3D metadata_cache = null;
70 private DOMTree tree = null;
71 private JComboBox documents_in_cache_combobox = null;
72 /** The root file node. */
73 private TreeNode root = null;
74 /** The threaded object responsible for loading all of the existing metadata.xml files prior to any save action. This is necessary so that hierarchy indexes within the metadata.xml files stay fresh. */
75 //private GDMLoader gdm_loader = null;
76 /** The maximum number of GDMDocuments to load at any one time */
77 static final private int MAX_DOCUMENTS = 25;
78 /** Constructor. */
79 public GDMManager() {
80 super();
81 this.metadata_cache = new HashMap3D(Gatherer.c_man.getCollection().msm.getSize());
82 // Connect
83 Gatherer.c_man.getCollection().msm.addMSMListener(this);
84 // We also have a debug dialog
85 if(Gatherer.debug != null) {
86 display();
87 }
88 }
89
90 /** This may seem a little odd but this method doesn't add the given metadata directly, instead calling fireMetadataChanged in MetadataSetManager so as to recursively add metadata if necessary, and to ensure that all listeners who are interested in data change (such as the Metadata Table and Save listeners) can be up to date. */
91 public void addMetadata(FileNode node, ArrayList metadatum) {
92 for(int i = 0; i < metadatum.size(); i++) {
93 Metadata metadata = (Metadata) metadatum.get(i);
94 Gatherer.c_man.getCollection().msm.fireMetadataChanged(node, (Metadata)null, metadata);
95 }
96 }
97
98 /** Destructor necessary for clean exit, subsequent to saving of metadata.xml files.
99 * @see org.greenstone.gatherer.Gatherer
100 * @see org.greenstone.gatherer.collection.CollectionManager
101 * @see org.greenstone.gatherer.msm.GDMParser
102 * @see org.greenstone.gatherer.msm.MetadataSetManager
103 */
104 public void destroy() {
105 // Destroy all the cached documents.
106 /*
107 Iterator iterator = keySet().iterator();
108 while(iterator.hasNext()) {
109 File file = (File) iterator.next();
110 GDMDocument document = (GDMDocument) get(file);
111 document.destroy(file);
112 }
113 */
114 // Deregister as listener
115 Gatherer.c_man.getCollection().msm.removeMSMListener(this);
116 // Deallocate all data members
117 metadata_cache.clear();
118 metadata_cache = null;
119 // Finally clear self
120 clear();
121 // Done!
122 }
123
124 /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
125 public void display() {
126 JDialog dialog = new JDialog(Gatherer.g_man, "Greenstone Metadata Document Manager", false);
127 dialog.setSize(400,400);
128 JPanel content_pane = (JPanel) dialog.getContentPane();
129 GDMDocument metadata_xml = new GDMDocument();
130 tree = new DOMTree(metadata_xml.getDocument());
131 metadata_xml = null;
132 documents_in_cache_combobox = new JComboBox();
133 documents_in_cache_combobox.addItemListener(new DOMItemListener());
134 JButton refresh_button = new GLIButton("Refresh Tree");
135 refresh_button.setMnemonic(KeyEvent.VK_R);
136 refresh_button.addActionListener(new ActionListener() {
137 public void actionPerformed(ActionEvent event) {
138 File metadata_file = (File) documents_in_cache_combobox.getSelectedItem();
139 if(metadata_file != null) {
140 GDMDocument document = (GDMDocument) get(metadata_file);
141 tree.setDocument(document.getDocument());
142 document = null;
143 metadata_file = null;
144 }
145 }
146 });
147 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
148 content_pane.setLayout(new BorderLayout());
149 content_pane.add(documents_in_cache_combobox, BorderLayout.NORTH);
150 content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
151 content_pane.add(refresh_button, BorderLayout.SOUTH);
152 dialog.show();
153 }
154
155 private class DOMItemListener
156 implements ItemListener {
157
158 public void itemStateChanged(ItemEvent event) {
159 if(event.getStateChange() == ItemEvent.SELECTED) {
160 File metadata_file = (File) documents_in_cache_combobox.getSelectedItem();
161 if(metadata_file != null) {
162 GDMDocument document = (GDMDocument) get(metadata_file);
163 tree.setDocument(document.getDocument());
164 document = null;
165 metadata_file = null;
166 }
167 }
168 }
169 }
170
171 /** Method that is called whenever an element within a set is changed or modified. Ensure all cached GDMDocuments are marked as stale.
172 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
173 */
174 public void elementChanged(MSMEvent event) {
175 for(Iterator values = values().iterator(); values.hasNext(); ) {
176 GDMDocument document = (GDMDocument) values.next();
177 document.setUpToDate(false);
178 document = null;
179 }
180 }
181 /** Retrieve the GreenstoneMetadataDocument that is associated with a certain file. If the document is in cache returns it. If the document exists but isn't in cache loads, caches, then returns it. Otherwise it creates a brand new document, caches it, then returns it.
182 * @see org.greenstone.gatherer.msm.GDMParser
183 */
184 public GDMDocument getDocument(File file) {
185 ///ystem.err.println("Get the GDMDocument for " + file.getAbsolutePath());
186 GDMDocument metadata_xml = null;
187 // Determine the name of the target files metadata.xml file.
188 File metadata_file = null;
189 if(file.isFile()) {
190 metadata_file = new File(file.getParentFile(), StaticStrings.METADATA_XML);
191 }
192 else {
193 metadata_file = new File(file, StaticStrings.METADATA_XML);
194 }
195 // Then try to retrieve it from cache. First we consider the case of a cache hit.
196 if(containsKey(metadata_file)) {
197 metadata_xml = (GDMDocument) get(metadata_file);
198 ///ystem.err.println("Get the GDMDocument for " + metadata_file.getAbsolutePath());
199 }
200 else {
201 // Now the two potential cache misses. The first requires us to load an existing metadata.xml
202 if(metadata_file.exists()) {
203 ///ystem.err.println("Reload the GDMDocument for " + metadata_file.getAbsolutePath());
204 metadata_xml = new GDMDocument(metadata_file);
205 }
206 // The final case is where no current metadata.xml exists. Create a new one just by creating a new GDMDocument.
207 else {
208 ///ystem.err.println("Create a new GDMDocument for " + metadata_file.getAbsolutePath());
209 metadata_xml = new GDMDocument();
210 }
211 put(metadata_file, metadata_xml);
212 if(documents_in_cache_combobox != null) {
213 documents_in_cache_combobox.addItem(metadata_file);
214 }
215 //Gatherer.println("[0ms]\tCached " + metadata_file);
216 }
217 return metadata_xml;
218 }
219
220 /*
221 // returns metadata file from cache or creates a new one
222 public GDMDocument getDummyDocument(File file) {
223 ///ystem.err.println("Get the GDMDocument for " + file.getAbsolutePath());
224 GDMDocument metadata_xml = null;
225 // Determine the name of the target files metadata.xml file.
226 File metadata_file = null;
227 if(file.isFile()) {
228 metadata_file = new File(file.getParentFile(), StaticStrings.METADATA_XML);
229 }
230 else {
231 metadata_file = new File(file, StaticStrings.METADATA_XML);
232 }
233 // Then try to retrieve it from cache. First we consider the case of a cache hit.
234 if(containsKey(metadata_file)) {
235 metadata_xml = (GDMDocument) get(metadata_file);
236 }
237 else {
238 metadata_xml = new GDMDocument();
239 put(metadata_file, metadata_xml);
240 }
241 return metadata_xml;
242 }
243 */
244
245 /*
246 public synchronized void dummyGetMetadata(File file) {
247 String filename = null;
248 if(file.isFile()) {
249 filename = file.getName();
250 file = file.getParentFile();
251 }
252 GDMDocument document = getDummyDocument(file);
253 }
254 */
255
256 /** Recover the metadata associated with a particular file. Note that this call is synchronized, so that all of the data holders don't need to be. */
257 public synchronized ArrayList getMetadata(File file) {
258 return getMetadata(file, false, true);
259 }
260
261/** Recover the metadata associated with a particular file excluding folder level metadata. Note that this call is synchronized, so that all of the data holders don't need to be. */
262 public synchronized ArrayList getMetadataOnly(File file) {
263 return getMetadata(file, false, false);
264 }
265
266 public synchronized ArrayList getMetadata(File file, ElementWrapper element) {
267 ArrayList metadata = getMetadata(file, false, true);
268 ArrayList values = new ArrayList();
269 for(int i = 0; i < metadata.size(); i++) {
270 Metadata data = (Metadata) metadata.get(i);
271 if(element.equals(data.getElement())) {
272 values.add(data.getValue());
273 }
274 }
275 if(values.size() > 0) {
276 Collections.sort(values);
277 }
278 return values;
279 }
280
281 private ArrayList getMetadata(File file, boolean remove, boolean append_folder_level) {
282 ArrayList metadata = null;
283 String filename = null;
284 if(file.isFile()) {
285 filename = file.getName();
286 file = file.getParentFile();
287 }
288 GDMDocument document = getDocument(file);
289 if(file != null && document != null) {
290 metadata = document.getMetadata(filename, remove, metadata, file, append_folder_level);
291 document = null;
292 }
293 return metadata;
294 }
295
296 public synchronized ArrayList getAllMetadata(File file) { // boolean remove) {
297 ///ystem.err.println("getMetadata(" + file.getAbsolutePath() + ")");
298 ArrayList metadata = null;
299 // Build up a list of all the metadata xml files we have to check for metadata.
300 ArrayList search_files = new ArrayList();
301 String filename = null;
302 File start_file = file;
303 if(file.isFile()) {
304 filename = file.getName();
305 start_file = file.getParentFile();
306 }
307 File collection_dir = new File(Gatherer.c_man.getCollectionDirectory());
308 ///ystem.err.println("Collection directory = " + collection_dir.getAbsolutePath());
309 ///ystem.err.println("Start directory = " + start_file.getAbsolutePath());
310 while(!start_file.equals(collection_dir)) {
311 ///ystem.err.println("Blip!");
312 search_files.add(0, new MetadataXMLFileSearch(start_file, filename));
313 if(filename != null) {
314 filename = start_file.getName() + "/" + filename;
315 }
316 else {
317 filename = start_file.getName() + "/";
318 }
319 start_file = start_file.getParentFile();
320 ///ystem.err.println("Start directory = " + start_file.getAbsolutePath());
321 }
322 // Now search each of these metadata xml for metadata, remembering to accumulate or overwrite as we go along.
323 for(int i = 0; i < search_files.size(); i++) {
324 MetadataXMLFileSearch a_search = (MetadataXMLFileSearch) search_files.get(i);
325 ///ystem.err.println("Search " + a_search.file.getAbsolutePath() + File.separator + "metadata.xml for " + (a_search.filename != null ? a_search.filename : "directory metadata"));
326 // Retrieve the document
327 GDMDocument document = getDocument(a_search.file);
328 if(document != null) {
329 // There is one piece of slight of hand here. You can never remove metadata during a get all metadata.
330 metadata = document.getMetadata(a_search.filename, false, metadata, a_search.file, true);
331 ///ystem.err.println("Current metadata: " + toString(metadata));
332 document = null;
333 }
334 a_search = null;
335 }
336 start_file = null;
337 collection_dir = null;
338 filename = null;
339 search_files.clear();
340 search_files = null;
341 return metadata;
342 }
343
344 public String toString(ArrayList list) {
345 StringBuffer text = new StringBuffer("(");
346 for(int i = 0; list != null && i < list.size(); i++) {
347 text.append((list.get(i)).toString());
348 if(i < list.size() - 1) {
349 text.append(", ");
350 }
351 }
352 text.append(")");
353 return text.toString();
354 }
355
356 private class MetadataXMLFileSearch {
357 public File file;
358 public String filename;
359 public MetadataXMLFileSearch(File file, String filename) {
360 this.file = file;
361 this.filename = filename;
362 }
363 }
364
365 /** Called whenever the metadata value changes in some way, such as the addition of a new value. This is the only event type we care about, but we care about it a lot. It tells us what metadata to add, remove, etc from the cached metadata.xml files. Note that this method is synchronized so that the data objects don't need to be.
366 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
367 * @see org.greenstone.gatherer.msm.GDMDocument
368 * @see org.greenstone.gatherer.msm.Metadata
369 * @see org.greenstone.gatherer.util.HashMap3D
370 */
371 public synchronized void metadataChanged(MSMEvent event) {
372 ///ystem.err.println("Recieved Event: " + event.toString());
373 File file = event.getFile();
374 if(file == null) {
375 FileNode record = event.getRecord();
376 file = record.getFile();
377 }
378 Metadata new_metadata = event.getNewMetadata();
379 Metadata old_metadata = event.getOldMetadata();
380 // These metadata objects may be new instances of metadata objects that already exist. Replace them if they are.
381 new_metadata = checkCache(new_metadata);
382 old_metadata = checkCache(old_metadata);
383 // Now apply the change to the document in question.
384 GDMDocument metadata_xml = getDocument(file);
385 if(metadata_xml != null) {
386 if(old_metadata != null) {
387 // File level
388 if(file.isFile()) {
389 metadata_xml.removeMetadata(file.getName(), old_metadata);
390 }
391 // Folder level
392 else {
393 metadata_xml.removeMetadata(null, old_metadata);
394 }
395 }
396 if(new_metadata != null) {
397 // File level
398 if(file.isFile()) {
399 metadata_xml.addMetadata(file.getName(), new_metadata, event.getAction() == MetaEditPrompt.ACCUMULATE);
400 }
401 else {
402 metadata_xml.addMetadata(null, new_metadata, event.getAction() == MetaEditPrompt.ACCUMULATE);
403 }
404 }
405 }
406 }
407
408 public void removeExtractedMetadata() {
409 try {
410 // Remove all of the extracted metadata in the collection
411 removeExtractedMetadata(new File(Gatherer.c_man.getCollectionImport()));
412 }
413 catch (Exception exception) {
414 Gatherer.println("Exception in GDMManager.removeExtractedMetadata - unexpected");
415 Gatherer.printStackTrace(exception);
416 }
417 }
418
419 private void removeExtractedMetadata(File file) {
420 // Retrieve the gdm document for this file
421 GDMDocument metadata_xml_document = getDocument(file);
422 // Remove the extracted metadata
423 ///ystem.err.println("Removing the extracted metadata from the file: " + file);
424 metadata_xml_document.removeExtractedMetadata();
425 metadata_xml_document = null;
426 // Then recurse down the directory structure looking for other metadata.xml files
427 File child_files[] = file.listFiles();
428 for(int i = 0; i < child_files.length; i++) {
429 if(child_files[i].isDirectory()) {
430 removeExtractedMetadata(child_files[i]);
431 }
432 }
433 child_files = null;
434 }
435
436 public ArrayList removeMetadata(File file) {
437 return getMetadata(file, true, false);
438 }
439
440 /** Causes all currently loaded GDMDocuments to write themselves out.
441 * @see org.greenstone.gatherer.msm.GDMDocument
442 */
443 public void save() {
444 Iterator iterator = keySet().iterator();
445 while(iterator.hasNext()) {
446 File file = (File) iterator.next();
447 GDMDocument document = (GDMDocument) get(file);
448 if(!document.isUpToDate()) {
449 //ystem.err.println("Saving: " + file.getAbsolutePath());
450 // First purge any old references.
451 document.getMetadata(null, false, null, null, false, true);
452 // If there is no metadata in this document then don't write out a file. In fact delete any file that already exists.
453 int count = document.countMetadata();
454 if(count > 0) {
455 // Now write the xml
456 Utility.export(document.getDocument(), file);
457 document.setUpToDate(true);
458 }
459 else if(file.exists()) {
460 file.delete();
461 }
462 }
463 }
464 }
465 /** Used to cause the document associated with a particular file to write the latest copy of itself to disk. */
466 public void save(FileNode node) {
467 File file = node.getFile();
468 if(file != null && file.isFile()) {
469 GDMDocument document = getDocument(file);
470 File xml_file;
471 if(file.isFile()) {
472 xml_file = new File(file.getParentFile(), "metadata.xml");
473 }
474 else {
475 xml_file = new File(file, "metadata.xml");
476 }
477 if(document != null && !document.isUpToDate()) {
478 // First purge any old references.
479 document.getMetadata(null, false, null, null, true);
480 // Now write the xml
481 Utility.export(document.getDocument(), xml_file);
482 document.setUpToDate(true);
483 }
484 xml_file = null;
485 document = null;
486 }
487 file = null;
488 }
489
490 /** Write out the latest copy of a certain document. */
491 public void save(File file, GDMDocument document) {
492 if(!document.isUpToDate()) {
493 // First purge any old references.
494 document.getMetadata(null, false, null, null, true);
495 // Now write the xml
496 Utility.export(document.getDocument(), file);
497 document.setUpToDate(true);
498 }
499 }
500
501
502 /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets. If a set changes, mark all cached GDMDocuments as being stale.
503 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
504 */
505 public void setChanged(MSMEvent event) {
506 for(Iterator values = values().iterator(); values.hasNext(); ) {
507 GDMDocument document = (GDMDocument) values.next();
508 document.setUpToDate(false);
509 document = null;
510 }
511 }
512 /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value. --While the comments below are now obsolete, I'll keep them just to remind me of how easy it is to back yourself into a corner with issues such as caching and persisitant references--. Such an action would require us to painstakingly reload every metadata.xml file using the value model prior to the change, then painstakingly write out each metadata.xml file again using the modified model, but I'm a glutton for punishment so thats ok. The alternative is to not do this and watch in horror as heirarchy references quickly fall into disarray, pointing to the wrong place. This task gets even more complicated by three facts:<br>1. We want to do this is a seperate thread, as we don't want the program to come to a screaming halt while we're updating metadata.xml files.<br>2. We have to prevent any metadata.xml files being removed from cache while we're doing this, as if we encounter these more recently written files their heirarchy references will already be correct and that will balls up our little process. Note that this means the saving process may have to block while pending metadata heirarchy updates are in progress.<br>3. Regarding (2) we don't have to rewrite any metadata.xml files already in cache as they will be correctly written out whenever they happen to be dumped from cache.<br>4. We need the ability to pre-empt the general update to load a user demanded metadata.xml and store it in cache, using the old value tree model as per usual, and<br>5. We have to store a cue of these events, and process them one at a time. Perhaps one day when I'm feeling masacistic I'll figure out someway to merge several updates into one, but for now we have to change the tree one node at a time in order for references to remain correct.<br>Ok, so thats five facts, but you get the gist. Not an easy task, but crucial for accurate storage and recall of metadata heirarchies.
513 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
514 */
515 public void valueChanged(MSMEvent event) {}
516
517 public void waitUntilComplete() {
518 //if(gdm_loader != null) {
519 // gdm_loader.waitUntilComplete();
520 //}
521 }
522
523 private Metadata checkCache(Metadata metadata) {
524 if(metadata != null) {
525 ///ystem.err.println("Search for " + metadata.toString());
526 if(metadata_cache.contains(metadata.getElement(), metadata.getValueNode())) {
527 metadata = (Metadata) metadata_cache.get(metadata.getElement(), metadata.getValueNode());
528 }
529 }
530 return metadata;
531 }
532
533 /** A separately threaded class to load all of the current metadata.xml files. Note that files can still be loaded on demand if they're not already in the cache. Also provides the functionality to block any other thread until the loading is complete, such as is necessary when moving values about in the value tree hierarchy. */
534 /*
535 private class GDMLoader
536 extends Thread {
537 private boolean complete = false;
538 private boolean dummy_load = false;
539
540 GDMLoader(boolean dummy_load) {
541 super("blarg");
542 this.dummy_load = dummy_load;
543 }
544
545
546 public void run() {
547 // Can't open a collections metadata when the collection isn't open!
548 while(!Gatherer.c_man.ready()) {
549 try {
550 wait(100);
551 }
552 catch(Exception error) {
553 }
554 }
555 // Now for each non-file directory in the tree, ask it to load its metadata
556 ArrayList remaining = new ArrayList();
557 remaining.add((FileNode)Gatherer.c_man.getRecordSet().getRoot());
558 int remaining_size = 0;
559 while((remaining_size = remaining.size()) > 0) {
560 FileNode record = (FileNode) remaining.remove(remaining_size - 1);
561 if(!record.isLeaf()) {
562 ///atherer.println("Retrieving metadata.xml for " + record);
563 if (this.dummy_load) {
564 dummyGetMetadata(record.getFile());
565 } else {
566 getMetadata(record.getFile());
567 }
568 for(int i = 0; i < record.getChildCount(); i++) {
569 remaining.add(record.getChildAt(i));
570 }
571
572 ///atherer.println("Retrieving metadata.xml for " + record);
573 getMetadata(record.getFile());
574
575 record.unmap();
576 }
577 record = null;
578 }
579 remaining = null;
580 complete = true;
581 }
582 public void waitUntilComplete() {
583 try {
584 while(!complete) {
585 sleep(100); // 1 second hopefully.
586 }
587 }
588 catch(Exception error) {
589 Gatherer.printStackTrace(error);
590 }
591 }
592 }
593 */
594
595 protected boolean removeEldestEntry(Map.Entry eldest) {
596 if(size() > MAX_DOCUMENTS) {
597 // Save the oldest document before its dumped
598 File file = (File) eldest.getKey();
599 ///ystem.err.println("Dumping oldest Document: " + file.getAbsolutePath());
600 GDMDocument document = (GDMDocument) eldest.getValue();
601 save(file, document);
602
603 if(documents_in_cache_combobox != null) {
604 documents_in_cache_combobox.removeItem(file);
605 }
606 // And then dump it
607 return true;
608 }
609 else {
610 return false;
611 }
612 }
613}
Note: See TracBrowser for help on using the repository browser.