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

Last change on this file since 10511 was 10511, checked in by mdewsnip, 19 years ago

Changed the names of some functions in RemoteGreenstoneServer and made almost all of the functions take the collection name as an argument (needed for authentication).

  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 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.CollectionTreeNode;
35import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
36import org.greenstone.gatherer.util.XMLTools;
37
38
39/** This class is a static class that manages the metadata.xml files */
40public class MetadataXMLFileManager
41{
42 static private ArrayList metadata_xml_files = new ArrayList();
43 /** The objects listening for MetadataChanged events. */
44 static private ArrayList metadata_changed_listeners = new ArrayList();
45 /** Keep track of which metadata.xml files have been modified so we can upload them to the server */
46 static private ArrayList modified_metadata_xml_files = new ArrayList();
47
48
49 static public void addMetadata(CollectionTreeNode file_node, ArrayList metadata_values)
50 {
51 addMetadata(new CollectionTreeNode[] { file_node }, metadata_values);
52 }
53
54
55 static public void addMetadata(CollectionTreeNode[] file_nodes, MetadataValue metadata_value)
56 {
57 ArrayList metadata_values = new ArrayList();
58 metadata_values.add(metadata_value);
59 addMetadata(file_nodes, metadata_values);
60 }
61
62
63 static public void addMetadata(CollectionTreeNode[] file_nodes, ArrayList metadata_values)
64 {
65 // Check the list of metadata values is non-empty
66 if (metadata_values.isEmpty()) {
67 return;
68 }
69
70 // Add the metadata to each file node in turn
71 for (int i = 0; i < file_nodes.length; i++) {
72 File current_file = file_nodes[i].getFile();
73 DebugStream.println("Adding metadata to " + current_file.getAbsolutePath());
74
75 // Find which metadata.xml file needs editing
76 boolean applicable_metadata_xml_file_found = false;
77 File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
78 String current_file_directory_path = current_file_directory.getAbsolutePath();
79 for (int j = 0; j < metadata_xml_files.size(); j++) {
80 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
81
82 // This metadata.xml file is only applicable if it is at the same level as the file
83 if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) {
84 applicable_metadata_xml_file_found = true;
85 metadata_xml_file.addMetadata(current_file, metadata_values);
86 if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
87 modified_metadata_xml_files.add(metadata_xml_file);
88 }
89 }
90 }
91
92 // If no applicable metadata.xml file exists, we have to create a new one
93 if (!applicable_metadata_xml_file_found) {
94 // Create a new (empty) metadata.xml file in the file's directory...
95 File new_metadata_xml_file_file = new File(current_file_directory, "metadata.xml");
96 XMLTools.writeXMLFile(new_metadata_xml_file_file, XMLTools.parseXMLFile("xml/metadata.xml", true));
97
98 // ...load it...
99 MetadataXMLFile new_metadata_xml_file = loadMetadataXMLFile(new_metadata_xml_file_file);
100
101 // ...and add the metadata
102 new_metadata_xml_file.addMetadata(current_file, metadata_values);
103 if (!modified_metadata_xml_files.contains(new_metadata_xml_file)) {
104 modified_metadata_xml_files.add(new_metadata_xml_file);
105 }
106 }
107 }
108
109 // Let any listeners know that the metadata has changed
110 fireMetadataChangedEvent(file_nodes);
111
112 // Upload the modified metadata.xml files to the server, if we're using one
113 uploadModifiedMetadataXMLFiles();
114 }
115
116
117 static public void addMetadataChangedListener(MetadataChangedListener metadata_changed_listener)
118 {
119 metadata_changed_listeners.add(metadata_changed_listener);
120 }
121
122
123 static public void clearMetadataXMLFiles()
124 {
125 metadata_xml_files.clear();
126 }
127
128
129 static private void fireMetadataChangedEvent(CollectionTreeNode[] file_nodes)
130 {
131 // Send the event off to all the MetadataChangedListeners
132 for (int i = 0; i < metadata_changed_listeners.size(); i++) {
133 ((MetadataChangedListener) metadata_changed_listeners.get(i)).metadataChanged(file_nodes);
134 }
135 }
136
137
138 /** Returns the metadata assigned to a file outside the collection, excluding folder-level/inherited metadata. */
139 static public ArrayList getMetadataAssignedDirectlyToExternalFile(File file)
140 {
141 DebugStream.println("Getting metadata assigned directly to external file " + file + "...");
142
143 // Build up a list of applicable metadata.xml files
144 ArrayList applicable_metadata_xml_files = new ArrayList();
145
146 File directory = (file.isDirectory() ? file : file.getParentFile());
147 while (directory != null) {
148 File[] directory_files = directory.listFiles();
149 for (int i = 0; i < directory_files.length; i++) {
150 File child_file = directory_files[i];
151 if (!child_file.isDirectory() && child_file.getName().equals("metadata.xml")) {
152 // It is very important that shallower files come before deeper ones
153 applicable_metadata_xml_files.add(0, new MetadataXMLFile(child_file.getAbsolutePath()));
154 }
155 }
156
157 directory = directory.getParentFile();
158 }
159
160 // Get the metadata assigned to the specified file from the applicable metadata.xml files
161 ArrayList assigned_metadata = getMetadataAssignedToFile(file, applicable_metadata_xml_files);
162
163 // Remove any folder-level metadata
164 for (int i = assigned_metadata.size() - 1; i >= 0; i--) {
165 if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) {
166 assigned_metadata.remove(i);
167 }
168 }
169
170 return assigned_metadata;
171 }
172
173
174 /** Returns the metadata assigned to a file inside the collection, excluding folder-level/inherited metadata. */
175 static public ArrayList getMetadataAssignedDirectlyToFile(File file)
176 {
177 // Get all the metadata assigned to the specified file...
178 ArrayList assigned_metadata = getMetadataAssignedToFile(file);
179
180 // ...then remove any folder-level metadata
181 for (int i = assigned_metadata.size() - 1; i >= 0; i--) {
182 if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) {
183 assigned_metadata.remove(i);
184 }
185 }
186
187 return assigned_metadata;
188 }
189
190
191 /** Returns all the metadata assigned to a file inside the collection. */
192 static public ArrayList getMetadataAssignedToFile(File file)
193 {
194 // Build up a list of applicable metadata.xml files
195 ArrayList applicable_metadata_xml_files = new ArrayList();
196
197 // Look at each loaded metadata.xml file to see if it is potentially applicable
198 String file_directory_path = (file.isDirectory() ? file : file.getParentFile()).getAbsolutePath() + File.separator;
199 for (int i = 0; i < metadata_xml_files.size(); i++) {
200 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i);
201
202 // This metadata.xml file is only potentially applicable if it is above or at the same level as the file
203 if (file_directory_path.startsWith(metadata_xml_file.getParentFile().getAbsolutePath() + File.separator)) {
204 applicable_metadata_xml_files.add(metadata_xml_file);
205 }
206 }
207
208 // Return the metadata assigned to the specified file from the applicable metadata.xml files
209 return getMetadataAssignedToFile(file, applicable_metadata_xml_files);
210 }
211
212
213 static private ArrayList getMetadataAssignedToFile(File file, ArrayList applicable_metadata_xml_files)
214 {
215 // Build up a list of metadata values assigned to this file
216 ArrayList metadata_values_all = new ArrayList();
217
218 // Look at each applicable metadata.xml file to see if it assigns metadata to this file
219 for (int i = 0; i < applicable_metadata_xml_files.size(); i++) {
220 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) applicable_metadata_xml_files.get(i);
221 DebugStream.println("Applicable metadata.xml file: " + metadata_xml_file);
222
223 ArrayList metadata_values = metadata_xml_file.getMetadataAssignedToFile(file);
224 for (int j = 0; j < metadata_values.size(); j++) {
225 MetadataValue metadata_value = (MetadataValue) metadata_values.get(j);
226
227 // Overriding metadata: remove any values with this metadata element
228 if (metadata_value.isAccumulatingMetadata() == false) {
229 for (int k = metadata_values_all.size() - 1; k >= 0; k--) {
230 if (((MetadataValue) metadata_values_all.get(k)).getMetadataElement().equals(metadata_value.getMetadataElement())) {
231 metadata_values_all.remove(k);
232 }
233 }
234 }
235
236 metadata_values_all.add(metadata_value);
237 }
238 }
239
240 return metadata_values_all;
241 }
242
243
244 static public void loadMetadataXMLFiles(File directory)
245 {
246 // Make sure the directory (import) exists
247 if (directory.exists() == false) {
248 return;
249 }
250
251 // Look recursively at each subfile of the directory for metadata.xml files
252 File[] directory_files = directory.listFiles();
253 for (int i = 0; i < directory_files.length; i++) {
254 File child_file = directory_files[i];
255 if (child_file.isDirectory()) {
256 loadMetadataXMLFiles(child_file);
257 }
258 else if (child_file.getName().equals("metadata.xml")) {
259 loadMetadataXMLFile(child_file);
260 }
261 }
262 }
263
264
265 static private MetadataXMLFile loadMetadataXMLFile(File metadata_xml_file_file)
266 {
267 MetadataXMLFile metadata_xml_file = new MetadataXMLFile(metadata_xml_file_file.getAbsolutePath());
268 metadata_xml_file.skimFile();
269 metadata_xml_files.add(metadata_xml_file);
270 return metadata_xml_file;
271 }
272
273
274 static public void removeMetadata(CollectionTreeNode file_node, ArrayList metadata_values)
275 {
276 removeMetadata(new CollectionTreeNode[] { file_node }, metadata_values);
277 }
278
279
280 static public void removeMetadata(CollectionTreeNode[] file_nodes, MetadataValue metadata_value)
281 {
282 ArrayList metadata_values = new ArrayList();
283 metadata_values.add(metadata_value);
284 removeMetadata(file_nodes, metadata_values);
285 }
286
287
288 static public void removeMetadata(CollectionTreeNode[] file_nodes, ArrayList metadata_values)
289 {
290 // Check the list of metadata values is non-empty
291 if (metadata_values.isEmpty()) {
292 return;
293 }
294
295 // Remove the metadata from each file node in turn
296 for (int i = 0; i < file_nodes.length; i++) {
297 File current_file = file_nodes[i].getFile();
298 DebugStream.println("Removing metadata from " + current_file.getAbsolutePath());
299
300 // Find which metadata.xml file needs editing
301 File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
302 String current_file_directory_path = current_file_directory.getAbsolutePath();
303 for (int j = 0; j < metadata_xml_files.size(); j++) {
304 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
305
306 // This metadata.xml file is only potentially applicable if it is above or at the same level as the file
307 if (current_file_directory_path.startsWith(metadata_xml_file.getParentFile().getAbsolutePath())) {
308 metadata_xml_file.removeMetadata(current_file, metadata_values);
309 if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
310 modified_metadata_xml_files.add(metadata_xml_file);
311 }
312 }
313 }
314 }
315
316 // Let any listeners know that the metadata has changed
317 fireMetadataChangedEvent(file_nodes);
318
319 // Upload the modified metadata.xml files to the server, if we're using one
320 uploadModifiedMetadataXMLFiles();
321 }
322
323
324 static public void removeMetadataChangedListener(MetadataChangedListener metadata_changed_listener)
325 {
326 metadata_changed_listeners.remove(metadata_changed_listener);
327 }
328
329
330 static public void replaceMetadata(CollectionTreeNode[] file_nodes, MetadataValue old_metadata_value, MetadataValue new_metadata_value)
331 {
332 // Replace the metadata in each file node in turn
333 for (int i = 0; i < file_nodes.length; i++) {
334 File current_file = file_nodes[i].getFile();
335 DebugStream.println("Replacing metadata in " + current_file.getAbsolutePath());
336
337 // Find which metadata.xml file needs editing
338 File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
339 String current_file_directory_path = current_file_directory.getAbsolutePath();
340 for (int j = 0; j < metadata_xml_files.size(); j++) {
341 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
342
343 // This metadata.xml file is only applicable if it is at the same level as the file
344 if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) {
345 metadata_xml_file.replaceMetadata(current_file, old_metadata_value, new_metadata_value);
346 if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
347 modified_metadata_xml_files.add(metadata_xml_file);
348 }
349 }
350 }
351 }
352
353 // Let any listeners know that the metadata has changed
354 fireMetadataChangedEvent(file_nodes);
355
356 // Upload the modified metadata.xml files to the server, if we're using one
357 uploadModifiedMetadataXMLFiles();
358 }
359
360
361 static public void unloadMetadataXMLFile(File metadata_xml_file_file)
362 {
363 DebugStream.println("Unloading metadata.xml file " + metadata_xml_file_file);
364
365 // Find the metadata.xml file in the list of loaded files, and remove it
366 for (int i = 0; i < metadata_xml_files.size(); i++) {
367 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i);
368 if (metadata_xml_file_file.getAbsolutePath().equals(metadata_xml_file.getAbsolutePath())) {
369 metadata_xml_files.remove(i);
370 break;
371 }
372 }
373 }
374
375
376 static private void uploadModifiedMetadataXMLFiles()
377 {
378 // This is only necessary when the collection is stored on a remote server
379 if (Gatherer.isGsdlRemote) {
380 if (modified_metadata_xml_files.isEmpty()) {
381 DebugStream.println("No modified metadata.xml files to upload.");
382 return;
383 }
384
385 // Upload the files modified since last time, then reset the list
386 RemoteGreenstoneServer.uploadCollectionFiles(Gatherer.c_man.getCollection().getName(), (File[]) modified_metadata_xml_files.toArray(new File[0]));
387 modified_metadata_xml_files.clear();
388 }
389 }
390}
Note: See TracBrowser for help on using the repository browser.