source: main/trunk/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFileManager.java

Last change on this file was 34264, checked in by ak19, 4 years ago
  1. Added moveMetaXMLToCSV 2. Both this and exportMetaAsCSV now also made to work for the remote case. 3. Bugfix to oversight in GUIManager that in the previous commit used to ignore user selected csvfile and always created a metdata.csv in import folder. 4. Tidied up MetaToCSV.java some more.
  • Property svn:keywords set to Author Date Id Revision
File size: 19.9 KB
Line 
1/**
2 *############################################################################
3 * A component of the Greenstone Librarian Interface, part of the Greenstone
4 * digital library suite from the New Zealand Digital Library Project at the
5 * University of Waikato, New Zealand.
6 *
7 * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
8 *
9 * Copyright (C) 2005 New Zealand Digital Library Project
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *############################################################################
25 */
26
27package org.greenstone.gatherer.metadata;
28
29
30import java.io.*;
31import java.util.*;
32import org.greenstone.gatherer.DebugStream;
33import org.greenstone.gatherer.Gatherer;
34import org.greenstone.gatherer.collection.CollectionManager;
35import org.greenstone.gatherer.collection.CollectionTreeNode;
36import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
37import org.greenstone.gatherer.util.XMLTools;
38
39import org.greenstone.gatherer.util.Utility;
40
41
42/** This class is a static class that manages the metadata.xml files */
43public class MetadataXMLFileManager
44{
45 static private ArrayList metadata_xml_files = new ArrayList();
46 /** The objects listening for MetadataChanged events. */
47 static private ArrayList metadata_changed_listeners = new ArrayList();
48 /** Keep track of which metadata.xml files have been modified so we can upload them to the server */
49 static private ArrayList modified_metadata_xml_files = new ArrayList();
50
51 /** For non-accumulating metadata (gs.FilenameEncoding), need the metadata.xml files
52 * sorted in top-down folder level order, which is achieved through this Comparator.
53 * By declaring a static class member here, we avoid recreating this object for every
54 * comparison, which would otherwise have resulted in a constructor call each time. */
55 static private MetadataXMLFileComparator metadataXMLFileComparator = new MetadataXMLFileComparator();
56
57
58 static public void addMetadata(CollectionTreeNode file_node, ArrayList metadata_values)
59 {
60 addMetadata(new CollectionTreeNode[] { file_node }, metadata_values);
61 }
62
63
64 static public void addMetadata(CollectionTreeNode[] file_nodes, MetadataValue metadata_value)
65 {
66 ArrayList metadata_values = new ArrayList();
67 metadata_values.add(metadata_value);
68 addMetadata(file_nodes, metadata_values);
69 }
70
71
72 static public void addMetadata(CollectionTreeNode[] file_nodes, ArrayList metadata_values)
73 {
74 // Check the list of metadata values is non-empty
75 if (metadata_values.isEmpty()) {
76 return;
77 }
78
79 // Add the metadata to each file node in turn
80 for (int i = 0; i < file_nodes.length; i++) {
81 File current_file = file_nodes[i].getFile();
82 DebugStream.println("Adding metadata to " + current_file.getAbsolutePath() + " - hex: " + Utility.debugUnicodeString(current_file.getAbsolutePath()));
83
84 // Find which metadata.xml file needs editing
85 boolean applicable_metadata_xml_file_found = false;
86 File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
87 String current_file_directory_path = current_file_directory.getAbsolutePath();
88 for (int j = 0; j < metadata_xml_files.size(); j++) {
89 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
90
91 // This metadata.xml file is only applicable if it is at the same level as the file
92 if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) {
93 applicable_metadata_xml_file_found = true;
94 metadata_xml_file.addMetadata(file_nodes[i], metadata_values);
95 if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
96 modified_metadata_xml_files.add(metadata_xml_file);
97 }
98 }
99 }
100
101 // If no applicable metadata.xml file exists, we have to create a new one
102 if (!applicable_metadata_xml_file_found) {
103 // Create a new (empty) metadata.xml file in the file's directory...
104 File new_metadata_xml_file_file = new File(current_file_directory, "metadata.xml");
105 XMLTools.writeXMLFile(new_metadata_xml_file_file, XMLTools.parseXMLFile("xml/metadata.xml", true));
106
107 // ...load it...
108 MetadataXMLFile new_metadata_xml_file = loadMetadataXMLFile(new_metadata_xml_file_file,true);
109
110 // ...and add the metadata
111 new_metadata_xml_file.addMetadata(file_nodes[i], metadata_values);
112 if (!modified_metadata_xml_files.contains(new_metadata_xml_file)) {
113 modified_metadata_xml_files.add(new_metadata_xml_file);
114 }
115 }
116 }
117
118 // Let any listeners know that the metadata has changed
119 fireMetadataChangedEvent(file_nodes);
120 }
121
122
123 static public void addMetadataChangedListener(MetadataChangedListener metadata_changed_listener)
124 {
125 metadata_changed_listeners.add(metadata_changed_listener);
126 }
127
128
129 static public void clearMetadataXMLFiles()
130 {
131 metadata_xml_files.clear();
132 }
133
134
135 static private void fireMetadataChangedEvent(CollectionTreeNode[] file_nodes)
136 {
137 // Send the event off to all the MetadataChangedListeners
138 for (int i = 0; i < metadata_changed_listeners.size(); i++) {
139 ((MetadataChangedListener) metadata_changed_listeners.get(i)).metadataChanged(file_nodes);
140 }
141 }
142
143
144 /** Returns the metadata assigned to a file outside the collection, excluding folder-level/inherited metadata. */
145 static public ArrayList getMetadataAssignedDirectlyToExternalFile(File file)
146 {
147 DebugStream.println("Getting metadata assigned directly to external file " + file + "...");
148
149 // Build up a list of applicable metadata.xml files
150 ArrayList applicable_metadata_xml_files = new ArrayList();
151
152 File directory = (file.isDirectory() ? file : file.getParentFile());
153 while (directory != null) {
154 File metadata_xml_file = new File(directory, "metadata.xml");
155 if (metadata_xml_file.exists() && !metadata_xml_file.isDirectory()) {
156 // It is very important that shallower files come before deeper ones
157 applicable_metadata_xml_files.add(0, new MetadataXMLFile(metadata_xml_file.getAbsolutePath()));
158 }
159
160 directory = directory.getParentFile();
161 }
162
163 // Get the metadata assigned to the specified file from the applicable metadata.xml files
164 ArrayList assigned_metadata = getMetadataAssignedToFile(file, applicable_metadata_xml_files, false);
165
166 // Remove any folder-level metadata
167 for (int i = assigned_metadata.size() - 1; i >= 0; i--) {
168 if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) {
169 assigned_metadata.remove(i);
170 }
171 }
172
173 return assigned_metadata;
174 }
175
176
177 /** Returns the metadata assigned to a file inside the collection, excluding folder-level/inherited metadata. */
178 static public ArrayList getMetadataAssignedDirectlyToFile(File file)
179 {
180 return getMetadataAssignedDirectlyToFile(file, false);
181 }
182
183 /** Returns the metadata assigned to a file inside the collection, excluding folder-level/inherited metadata. */
184 static public ArrayList getMetadataAssignedDirectlyToFile(File file, boolean filenameEncodingMetaOnly)
185 {
186
187 // Get all the metadata assigned to the specified file...
188 ArrayList assigned_metadata = getMetadataAssignedToFile(file, filenameEncodingMetaOnly);
189
190 // ...then remove any folder-level metadata
191 for (int i = assigned_metadata.size() - 1; i >= 0; i--) {
192 if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) {
193 assigned_metadata.remove(i);
194 }
195 }
196
197 return assigned_metadata;
198 /*
199 // Get all the metadata assigned to the specified file...
200 // Build up a list of applicable metadata.xml files - which in this case
201 // is exclusively the metadata file at this file/folder's own level.
202 ArrayList applicable_metadata_xml_files = new ArrayList();
203
204 // Find the metadata.xml file (if any) that is at the same level as the file
205 String file_directory_path = (file.isDirectory() ? file : file.getParentFile()).getAbsolutePath() + File.separator;
206 for (int i = 0; i < metadata_xml_files.size(); i++) {
207 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i);
208
209 if (file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath() + File.separator)) {
210 //System.err.println("Found metadata_xml_file: " + metadata_xml_file);
211 applicable_metadata_xml_files.add(metadata_xml_file);
212 }
213 }
214
215 if(applicable_metadata_xml_files.size() == 0) {
216 return new ArrayList(0);
217 }
218
219 // Return the metadata assigned to the specified file from the applicable metadata.xml files
220 return getMetadataAssignedToFile(file, applicable_metadata_xml_files, filenameEncodingMetaOnly);
221 */
222 }
223
224
225 /** Returns all the metadata assigned to a file inside the collection. */
226 static public ArrayList getMetadataAssignedToFile(File file)
227 {
228 return getMetadataAssignedToFile(file, false);
229 }
230
231 /** Returns all the metadata assigned to a file inside the collection (or
232 * just gs.filenameEncoding if parameter filenameEncodingMetaOnly is true),
233 * including folder-level/inherited metadata.
234 */
235 static public ArrayList getMetadataAssignedToFile(File file, boolean filenameEncodingMetaOnly)
236 {
237 // Build up a list of applicable metadata.xml files
238 ArrayList applicable_metadata_xml_files = new ArrayList();
239
240 // Look at each loaded metadata.xml file to see if it is potentially applicable
241 String file_directory_path = (file.isDirectory() ? file : file.getParentFile()).getAbsolutePath() + File.separator;
242 for (int i = 0; i < metadata_xml_files.size(); i++) {
243 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i);
244
245 // This metadata.xml file is only potentially applicable if it is above or at the same level as the file
246 if (file_directory_path.startsWith(metadata_xml_file.getParentFile().getAbsolutePath() + File.separator)) {
247 applicable_metadata_xml_files.add(metadata_xml_file);
248 }
249 }
250
251 // Sort the metadataxml files in order starting from those in the
252 // topmost folders down to the one in the lowest level folder.
253 Collections.sort(applicable_metadata_xml_files, metadataXMLFileComparator);
254 // Return the metadata assigned to the specified file from the applicable metadata.xml files
255 return getMetadataAssignedToFile(file, applicable_metadata_xml_files, filenameEncodingMetaOnly);
256 }
257
258 // package access method
259 static ArrayList getMetadataAssignedToFile(File file, ArrayList applicable_metadata_xml_files,
260 boolean filenameEncodingMetaOnly)
261 {
262 // Build up a list of metadata values assigned to this file
263 ArrayList metadata_values_all = new ArrayList();
264
265 // Look at each applicable metadata.xml file to see if it assigns metadata to this file
266 for (int i = 0; i < applicable_metadata_xml_files.size(); i++) {
267 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) applicable_metadata_xml_files.get(i);
268 DebugStream.println("Applicable metadata.xml file: " + metadata_xml_file);
269
270 ArrayList metadata_values = metadata_xml_file.getMetadataAssignedToFile(file, filenameEncodingMetaOnly);
271 for (int j = 0; j < metadata_values.size(); j++) {
272 MetadataValue metadata_value = (MetadataValue) metadata_values.get(j);
273
274 // Overriding metadata: remove any values with this metadata element
275 if (metadata_value.isAccumulatingMetadata() == false) {
276 for (int k = metadata_values_all.size() - 1; k >= 0; k--) {
277 if (((MetadataValue) metadata_values_all.get(k)).getMetadataElement().equals(metadata_value.getMetadataElement())) {
278 metadata_values_all.remove(k);
279 }
280 }
281 }
282
283 metadata_values_all.add(metadata_value);
284 }
285 }
286
287 return metadata_values_all;
288 }
289
290
291 static public void loadMetadataXMLFiles(File directory, boolean skimfile)
292 {
293 // Make sure the directory (import) exists
294 if (directory.exists() == false) {
295 return;
296 }
297
298 // Look recursively at each subfile of the directory for metadata.xml files
299 File[] directory_files = directory.listFiles();
300 for (int i = 0; i < directory_files.length; i++) {
301 File child_file = directory_files[i];
302 if (child_file.isDirectory()) {
303 loadMetadataXMLFiles(child_file,skimfile);
304 }
305 else if (child_file.getName().equals("metadata.xml")) {
306 loadMetadataXMLFile(child_file,skimfile);
307 }
308 }
309 }
310
311
312 static private MetadataXMLFile loadMetadataXMLFile(File metadata_xml_file_file, boolean skimfile)
313 {
314 MetadataXMLFile metadata_xml_file = new MetadataXMLFile(metadata_xml_file_file.getAbsolutePath());
315 if (metadata_xml_files.contains(metadata_xml_file)) {
316 // This metadata.xml file has already been loaded, so return the loaded object
317 return (MetadataXMLFile) metadata_xml_files.get(metadata_xml_files.indexOf(metadata_xml_file));
318 }
319 if(skimfile){
320 metadata_xml_file.skimFile();
321 }
322 metadata_xml_files.add(metadata_xml_file);
323 return metadata_xml_file;
324 }
325
326
327 static public void removeMetadata(CollectionTreeNode file_node, ArrayList metadata_values)
328 {
329 removeMetadata(new CollectionTreeNode[] { file_node }, metadata_values);
330 }
331
332
333 static public void removeMetadata(CollectionTreeNode[] file_nodes, MetadataValue metadata_value)
334 {
335 ArrayList metadata_values = new ArrayList();
336 metadata_values.add(metadata_value);
337 removeMetadata(file_nodes, metadata_values);
338 }
339
340
341 static public void removeMetadata(CollectionTreeNode[] file_nodes, ArrayList metadata_values)
342 {
343 // Check the list of metadata values is non-empty
344 if (metadata_values.isEmpty()) {
345 return;
346 }
347
348 // Remove the metadata from each file node in turn
349 for (int i = 0; i < file_nodes.length; i++) {
350 File current_file = file_nodes[i].getFile();
351 DebugStream.println("Removing metadata from " + current_file.getAbsolutePath());
352
353 // Find which metadata.xml file needs editing
354 File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
355 String current_file_directory_path = current_file_directory.getAbsolutePath();
356 for (int j = 0; j < metadata_xml_files.size(); j++) {
357 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
358
359 // This metadata.xml file is only potentially applicable if it is above or at the same level as the file
360 if (current_file_directory_path.startsWith(metadata_xml_file.getParentFile().getAbsolutePath())) {
361 metadata_xml_file.removeMetadata(file_nodes[i], metadata_values);
362 if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
363 modified_metadata_xml_files.add(metadata_xml_file);
364 }
365 }
366 }
367 }
368
369 // Let any listeners know that the metadata has changed
370 fireMetadataChangedEvent(file_nodes);
371 }
372
373
374 static public void removeMetadataChangedListener(MetadataChangedListener metadata_changed_listener)
375 {
376 metadata_changed_listeners.remove(metadata_changed_listener);
377 }
378
379
380 static public void replaceMetadata(CollectionTreeNode[] file_nodes, MetadataValue old_metadata_value, MetadataValue new_metadata_value)
381 {
382 // Replace the metadata in each file node in turn
383 for (int i = 0; i < file_nodes.length; i++) {
384 File current_file = file_nodes[i].getFile();
385 DebugStream.println("Replacing metadata in " + current_file.getAbsolutePath());
386
387 // Find which metadata.xml file needs editing
388 File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
389 String current_file_directory_path = current_file_directory.getAbsolutePath();
390 for (int j = 0; j < metadata_xml_files.size(); j++) {
391 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
392
393 // This metadata.xml file is only applicable if it is at the same level as the file
394 if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) {
395 metadata_xml_file.replaceMetadata(file_nodes[i], old_metadata_value, new_metadata_value);
396 if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
397 modified_metadata_xml_files.add(metadata_xml_file);
398 }
399 }
400 }
401 }
402
403 // Let any listeners know that the metadata has changed
404 fireMetadataChangedEvent(file_nodes);
405 }
406
407
408 /** Ensures that all the metadata is written to metadata.xml files. */
409 static public void saveMetadataXMLFiles()
410 {
411 // Save the file currently loaded into memory out to disk
412 MetadataXMLFile.saveLoadedFile();
413
414 // If the collection is stored on a remote server, upload all the modified files now
415 if (Gatherer.isGsdlRemote) {
416 if (modified_metadata_xml_files.isEmpty()) {
417 DebugStream.println("No modified metadata.xml files to upload.");
418 return;
419 }
420
421 // Upload the files modified since last time, then reset the list
422 Gatherer.remoteGreenstoneServer.uploadCollectionFiles(
423 CollectionManager.getLoadedCollectionName(), (File[]) modified_metadata_xml_files.toArray(new File[0]));
424 modified_metadata_xml_files.clear();
425 }
426 }
427
428
429 static public void unloadMetadataXMLFile(File metadata_xml_file_file)
430 {
431 DebugStream.println("Unloading metadata.xml file " + metadata_xml_file_file);
432
433 // Find the metadata.xml file in the list of loaded files, and remove it
434 for (int i = 0; i < metadata_xml_files.size(); i++) {
435 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i);
436 if (metadata_xml_file_file.getAbsolutePath().equals(metadata_xml_file.getAbsolutePath())) {
437 metadata_xml_files.remove(i);
438 break;
439 }
440 }
441 }
442
443 static public void clearAllMetadataInCollection() {
444 for (int j = 0; j < metadata_xml_files.size(); j++) {
445 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
446 metadata_xml_file.clearAllMetadataInFile();
447
448 // Let any listeners know that the metadata has changed
449 //fireMetadataChangedEvent(file_nodes); // sadly don't have file_nodes needed to do this
450
451 // all are modified
452 if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
453 modified_metadata_xml_files.add(metadata_xml_file);
454 }
455 saveMetadataXMLFiles(); // saves final modified metaXML and then takes care of uploading all modified metaXML files to remote gsdl
456 }
457 }
458
459 /**
460 * Comparator to order MetadataXMLFiles in ascending order from
461 * those in a higher level folder to those in a lower level folder
462 * It is based on the assumption that all MetadataXMLFiles sent to
463 * it to compare will be linear descendants of one toplevel folder
464 * E.g. /A/metadata.xml, /A/B/metadata.xml, /A/B/C/D/metadata.xml.
465 * In other words, that each is a substring of one of the others until
466 * the toplevel folder is reached.
467 */
468 private static class MetadataXMLFileComparator implements Comparator {
469
470 public int compare(Object o1, Object o2) {
471 if(!(o1 instanceof MetadataXMLFile)) {
472 return -1;
473 } else if (!(o2 instanceof MetadataXMLFile)) {
474 return 1;
475 }
476
477 // Both are MetadataXMLFiles objects. Remove the terminating
478 // "metadata.xml" from their filenames to get their containing folder
479 String filename1 = ((MetadataXMLFile)o1).getParentFile().getAbsolutePath();
480 String filename2 = ((MetadataXMLFile)o2).getParentFile().getAbsolutePath();
481
482 // if 1 is a prefix of 2, then 1 < 2 in the ordering (1 comes before 2)
483 if(filename2.startsWith(filename1)) {
484 return -1;
485 } else if(filename1.startsWith(filename2)) {
486 return 1;
487 } else {
488 // unlikely that the metadata.xml files will be the same
489 // or that neither is a prefix of the other
490 return filename1.compareTo(filename2); // sorts in ascending order
491 }
492
493 }
494
495 public boolean equals(Object obj) {
496 if(!(obj instanceof MetadataXMLFileComparator)) {
497 return false;
498 }
499
500 // else it is the same sort of comparator
501 return true;
502 }
503
504 }
505
506}
Note: See TracBrowser for help on using the repository browser.