source: other-projects/FileTransfer-WebSocketPair/testGXTWithGreenstone/src/org/greenstone/gatherer/metadata/MetadataXMLFileManager.java@ 33053

Last change on this file since 33053 was 33053, checked in by ak19, 5 years ago

I still had some stuff of Nathan Kelly's (FileTransfer-WebSocketPair) sitting on my USB. Had already commited the Themes folder at the time, 2 years back. Not sure if he wanted this additional folder commited. But I didn't want to delete it and decided it will be better off on SVN. When we use his project, if we find we didn't need this test folder, we can remove it from svn then.

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