source: trunk/gli/src/org/greenstone/gatherer/msm/MetadataXMLFile.java@ 6879

Last change on this file since 6879 was 6879, checked in by mdewsnip, 20 years ago

Renamed GDM* classes to MetadataXMLFile*, for our sanity.

  • Property svn:keywords set to Author Date Id Revision
File size: 29.6 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 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.msm;
28
29import java.io.*;
30import java.util.*;
31import org.greenstone.gatherer.Gatherer;
32import org.greenstone.gatherer.msm.MetadataXMLFileManager;
33import org.greenstone.gatherer.msm.MSMUtils;
34import org.greenstone.gatherer.util.Codec;
35import org.greenstone.gatherer.util.HashMap3D;
36import org.greenstone.gatherer.util.StaticStrings;
37import org.greenstone.gatherer.util.Utility;
38import org.greenstone.gatherer.valuetree.GValueModel;
39import org.greenstone.gatherer.valuetree.GValueNode;
40import org.w3c.dom.*;
41
42/** This class wraps around a DOM Document providing methods for accessing the data within. In this case the DOM represents a Greenstone Directory metadata file. It provides the necessary functionality to create a new metadata.xml file.
43 * @author John Thompson, Greenstone Digital Library, University of Waikato
44 * @version 2.3b
45 */
46public class MetadataXMLFile {
47 /** Record if the document this object is based on is up to date. */
48 private boolean up_to_date = true;
49 /** The document this class sources its data from. */
50 private Document base_document;
51 static final private String ACCUMULATE = "accumulate";
52 /** The pattern to match when searching for directory level assignments. */
53 static final private String DIRECTORY_FILENAME = ".*";
54 static final private String DESCRIPTION_ELEMENT = "Description";
55 static final private String FILENAME_ELEMENT = "FileName";
56 static final private String FILESET_ELEMENT = "FileSet";
57 static final private String HVALUE_ATTRIBUTE = "hvalue";
58 static final private String MODE_ATTRIBUTE = "mode";
59 static final private String OVERWRITE = "overwrite";
60 static final private String[] ALL_METADATA_TYPES = {StaticStrings.METADATA_ELEMENT, StaticStrings.EXTRACTED_METADATA_ELEMENT};
61
62 /** Constructor which creates a brand new metadata.xml document. */
63 public MetadataXMLFile() {
64 // Create new document. We do this by loading a copy of the template. */
65 this.base_document = Utility.parse(Utility.GREENSTONEDIRECTORYMETADATA_TEMPLATE, true);
66 }
67
68 /** Constructor which parses an existing metadata.xml document. */
69 public MetadataXMLFile(File file) {
70 try {
71 this.base_document = Utility.parse(file.getAbsolutePath(), false);
72 }
73 catch (Exception error) {
74 // Poorly formed, or completely invalid metadata.xml file!
75 }
76 }
77
78 /** Constructor which wraps around an existing metadata.xml document. */
79 public MetadataXMLFile(Document base_document) {
80 this.base_document = base_document;
81 }
82
83 /** Add this metadata to the named file. There is one tricky thing to consider. Whenever a metadata entry is added it is taken to be accumulating except if it is the first added, in which case it overwrites! Actually this gets worse, as we could have been told to append this metadata to a document which already inherits metadata. Thus we need a new argument to determine whether this add was triggered by an append or a replace. */
84 public void addMetadata(String filename, Metadata metadata, boolean force_accumulate)
85 {
86 System.err.println("Add '" + metadata + "' to " + (filename != null ? filename : "directory."));
87 try {
88 // Retrieve the document element.
89 Element directorymetadata_element = base_document.getDocumentElement();
90 // Iterate through the filesets looking for one that matches the given filename.
91 Element fileset_element = null;
92 boolean found = false;
93 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
94 for(int i = 0; !found && i < fileset_elements.getLength(); i++) {
95 fileset_element = (Element) fileset_elements.item(i);
96 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
97 for(int j = 0; !found && j < filename_elements.getLength(); j++) {
98 Element filename_element = (Element) filename_elements.item(j);
99 String filename_pattern = MSMUtils.getValue(filename_element);
100 System.err.println("Checking " + filename + " against " + filename_pattern + "|");
101 // Have we found a match. If so break out of for loop.
102 if (filename != null && filename.matches(filename_pattern) && !filename_pattern.equals(DIRECTORY_FILENAME)) {
103 System.err.println("Adding to existing file fileset!");
104 found = true;
105 }
106 else if (filename == null && filename_pattern.equals(DIRECTORY_FILENAME)) {
107 System.err.println("Adding to existing folder fileset!");
108 found = true;
109 }
110 // No match. On to the next one.
111 else {
112 System.err.println("No match at all!");
113 }
114 filename_pattern = null;
115 filename_element = null;
116 }
117 }
118 fileset_elements = null;
119 // If we still haven't found an existing fileset, then its time to create one.
120 if (fileset_element == null) {
121 System.err.println("Creating a new fileset.");
122 fileset_element = base_document.createElement(FILESET_ELEMENT);
123 Element filename_element = base_document.createElement(FILENAME_ELEMENT);
124 Element description_element = base_document.createElement(DESCRIPTION_ELEMENT);
125 fileset_element.appendChild(filename_element);
126 fileset_element.appendChild(description_element);
127 Text filename_text = null;
128 // If the filename is null then we add a directory metadata set as directorymetadata_element's first child
129 if (filename == null) {
130 filename_text = base_document.createTextNode(DIRECTORY_FILENAME);
131 if (directorymetadata_element.hasChildNodes()) {
132 directorymetadata_element.insertBefore(fileset_element, directorymetadata_element.getFirstChild());
133 }
134 else {
135 directorymetadata_element.appendChild(fileset_element);
136 }
137 }
138 // Otherwise we append the new fileset to directorymetadata_element's children
139 else {
140 System.err.println("New fileset for " + filename);
141 filename = Codec.transform(filename, Codec.TEXT_TO_REGEXP);
142 System.err.println("After transform: " + filename);
143 filename_text = base_document.createTextNode(filename);
144 directorymetadata_element.appendChild(fileset_element);
145 }
146 filename_element.appendChild(filename_text);
147 filename_text = null;
148 description_element = null;
149 filename_element = null;
150 }
151 // Now, finally, we can add the metadata.
152 Element metadata_element = null;
153 String name = metadata.getElement().getName();
154 // If this is extracted metadata, we use a special element name that won't be recognized by greenstone
155 if(name.startsWith(Utility.EXTRACTED_METADATA_NAMESPACE)) {
156 metadata_element = base_document.createElement(ALL_METADATA_TYPES[1]);
157 name = name.substring(Utility.EXTRACTED_METADATA_NAMESPACE.length() + 1);
158 }
159 else {
160 metadata_element = base_document.createElement(ALL_METADATA_TYPES[0]);
161 }
162 metadata_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
163
164 // To determine if this metadata entry should overwrite or accumulate we check if there are other entries with the same element in this fileset.
165 boolean will_accumulate = false;
166 NodeList sibling_description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
167 for(int k = 0; !will_accumulate && k < sibling_description_elements.getLength(); k++) {
168 Element sibling_description_element = (Element) sibling_description_elements.item(k);
169 // We have to do this for each type of metadata
170 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
171 NodeList sibling_metadata_elements = sibling_description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
172 for(int l = 0; !will_accumulate && l < sibling_metadata_elements.getLength(); l++) {
173 Element sibling_metadata_element = (Element) sibling_metadata_elements.item(l);
174 // It appears that its possible that we can be asked to add the same metadata twice (especially after a copy action is cancelled then repeated). So we check if we have been asked to add exactly the same value twice.
175 if(sibling_metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE))) {
176 // Check the values and return if they are the same.
177 if(metadata.getAbsoluteValue().equals(MSMUtils.getValue(sibling_metadata_element))) {
178 return;
179 }
180 will_accumulate = true;
181 }
182 sibling_metadata_element = null;
183 }
184 sibling_metadata_elements = null;
185 }
186 sibling_description_element = null;
187 }
188 sibling_description_elements = null;
189 if(will_accumulate || force_accumulate) { //mode.equals(ACCUMULATE)) {
190 metadata_element.setAttribute(MODE_ATTRIBUTE, ACCUMULATE);
191 }
192 // As we can't possibly store all the metadata in memory, nor can we ensure that the indexes written to file remain the same until the new time we look at this file, and to avoid having to open a rewrite every collection document whenever any value tree changes, I'm writing the value out as a full path string
193 GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(metadata.getElement());
194 String node_value = null;
195 if(model != null && model.isHierarchy()) {
196 //node_value = /odec.transform(metadata.getValueNode().getFullPath(false), /odec.TEXT_TO_DOM);
197 node_value = metadata.getValueNode().getFullPath(false);
198 }
199 else {
200 node_value = metadata.getAbsoluteValue();
201 }
202 ///ystem.err.println("Creating node in MetadataXMLFile: '" + node_value + "'");
203 metadata_element.appendChild(base_document.createTextNode(node_value));
204 // Retrieve the first description element for this fileset (there should only be one, but I'll play it safe).
205 NodeList description_elements = fileset_element.getElementsByTagName("Description");
206 Element description_element = (Element) description_elements.item(0);
207 description_element.appendChild(metadata_element);
208 description_element = null;
209 metadata_element = null;
210 //mode = null;
211 fileset_element = null;
212 directorymetadata_element = null;
213 up_to_date = false;
214 }
215 catch (Exception error) {
216 Gatherer.printStackTrace(error);
217 }
218 }
219
220 public int countMetadata() {
221 int count = 0;
222 try {
223 // Retrieve the document element.
224 Element directorymetadata_element = base_document.getDocumentElement();
225 // Iterate through the filesets, checking the FileName child element against the target file's name using regular expression matching.
226 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
227 for(int i = 0; i < fileset_elements.getLength(); i++) {
228 Element fileset_element = (Element) fileset_elements.item(i);
229 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
230 for(int k = 0; k < description_elements.getLength(); k++) {
231 Element description_element = (Element) description_elements.item(k);
232 // We have to do this for each type of metadata
233 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
234 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
235 count = count + metadata_elements.getLength();
236 metadata_elements = null;
237 }
238 description_element = null;
239 }
240 description_elements = null;
241 fileset_element = null;
242 }
243 fileset_elements = null;
244 directorymetadata_element = null;
245 }
246 catch (Exception error) {
247 Gatherer.printStackTrace(error);
248 }
249 return count;
250 }
251
252 /** Retrieve the document this class is wrapping. */
253 public Document getDocument() {
254 return base_document;
255 }
256
257 /** Get all of the metadata, including directory level, associated with this file. */
258 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file, boolean append_folder_level) {
259 return getMetadata(filename, remove, metadatum_so_far, file, append_folder_level, false);
260 }
261 /** Retrieve the metadata associated with the given filename. Keep track of what metadata should be overwritten and what should be accumulated. Also make note of the source file, and remove the metadata if required. Finally if purge is set retrieve every piece of metadata in this file. */
262 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file, boolean append_folder_level, boolean purge) {
263 Gatherer.println("Get metadata for " + filename);
264 Gatherer.println("remove = " + remove + ", metadata_so_far = " + (metadatum_so_far != null ? String.valueOf(metadatum_so_far.size()) : "null") + ", file = " + file + ", append_folder_level = " + append_folder_level + ", purge = " + purge);
265 // Of course null is not an acceptable filename
266 //if(filename == null) {
267 // return metadatum_so_far;
268 //}
269 ArrayList metadatum = null;
270 ArrayList queued_for_removal = new ArrayList();
271 if(metadatum_so_far == null) {
272 metadatum = new ArrayList();
273 }
274 else {
275 metadatum = metadatum_so_far;
276 }
277 try {
278 // Retrieve the document element.
279 Element directorymetadata_element = base_document.getDocumentElement();
280 // Iterate through the filesets, checking the FileName child element against the target file's name using regular expression matching.
281 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
282 for(int i = 0; i < fileset_elements.getLength(); i++) {
283 Element fileset_element = (Element) fileset_elements.item(i);
284 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
285 for(int j = 0; j < filename_elements.getLength(); j++) {
286 Element filename_element = (Element) filename_elements.item(j);
287 String filename_text = MSMUtils.getValue(filename_element);
288 if((filename != null && (filename.matches(filename_text) || (append_folder_level && filename.indexOf(File.separator) != -1 && filename_text.equals(filename.substring(0, filename.indexOf(File.separator)))))) || ((filename == null || append_folder_level) && filename_text.equals(DIRECTORY_FILENAME)) || purge) {
289 // If they match add all of the metadata found in the Description child element, remembering to abide by desired mode (accumulate vs. overwrite).
290 // Normal metadata
291 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
292 for(int k = 0; k < description_elements.getLength(); k++) {
293 Element description_element = (Element) description_elements.item(k);
294 // We have to do this for each type of metadata
295 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
296 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
297 for(int l = 0; l < metadata_elements.getLength(); l++) {
298 Element metadata_element = (Element) metadata_elements.item(l);
299 String raw_element = metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
300 //String language = metadata_element.getAttribute("language");
301 String mode = metadata_element.getAttribute(MODE_ATTRIBUTE);
302 String raw_value = MSMUtils.getValue(metadata_element);
303 //
304 //raw_value = Codec.transform(raw_value, Codec.DOM_TO_);
305 ///ystem.err.println("Retrieved raw value: " + raw_value);
306 // ***** LEGACY SUPPORT *****
307 // If this raw_value contains a '\' character, but no '\\', '[' or ']' characters, then replace the '\' with a '\\'
308 if(raw_value.indexOf(StaticStrings.ESCAPE_STR) != -1) {
309 ///ystem.err.println("Blarg");
310 Gatherer.println("Detected Legacy Path: " + raw_value);
311 raw_value = raw_value.replaceAll(StaticStrings.ESCAPE_PATTERN, StaticStrings.PIPE_STR);
312 Gatherer.println("Updated Path To: " + raw_value);
313 MSMUtils.setValue(metadata_element, raw_value);
314 }
315 // **************************
316 // Using the element string and value, retrieve a matching Metadata object from the cache
317 Metadata metadata = null;
318 // If this element has hierarchy values then we must ensure the raw value is a full path, not an index.
319 // Try to retrieve an already comstructed piece of metadata from file - but not if we are purging, as this will stuff up anything that is still using that metadata - such as the GTable
320 if(MetadataXMLFileManager.metadata_cache.contains(raw_element, raw_value) && !purge) {
321 ///ystem.err.println("HIT! Retrieve metadata from cache: " + raw_element + " -> " + raw_value + "\n");
322 metadata = (Metadata) MetadataXMLFileManager.metadata_cache.get(raw_element, raw_value);
323 }
324 else {
325 ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(raw_element);
326 if (element != null) {
327 GValueNode value = Metadata.getDefaultValueNode(element, raw_value);
328 ///ystem.err.println("Miss. Create new metadata: " + raw_element + " -> " + raw_value + "\n");
329 metadata = new Metadata(element, value);
330 if(!purge) {
331 MetadataXMLFileManager.metadata_cache.put(raw_element, raw_value, metadata);
332 }
333 ///ystem.err.println("Added metadata to cache: " + raw_element + " -> " + raw_value + "\n");
334 value = null;
335 element = null;
336 }
337 }
338
339 // Determine whether this metadata is file or folder level
340 if (metadata != null) {
341 // The metadata is folder level if the file expression matches .*
342 if (filename_text != null && filename_text.equals(DIRECTORY_FILENAME)) {
343 metadata.setFileLevel(false);
344 }
345 // Otherwise it must be file level
346 else {
347 metadata.setFileLevel(true);
348 }
349
350 metadata.setFile(file);
351 // If mode is overwrite, then remove any previous values for this metadata element.
352 if(mode.equals("accumulate")) {
353 metadata.setAccumulate(true);
354 }
355 else {
356 metadata.setAccumulate(false);
357 ///ystem.err.println("Metadata overwrites: " + metadata);
358 for(int m = metadatum.size() - 1; m >= 0; m--) {
359 Metadata old_metadata = (Metadata) metadatum.get(m);
360 if(old_metadata.getElement().equals(metadata.getElement())) {
361 metadatum.remove(m);
362 ///ystem.err.println("Removing overridden metadata: " + old_metadata);
363 }
364 old_metadata = null;
365 }
366 }
367 mode = null;
368 // Add the completed metadata and clean up
369 ///ystem.err.println("Adding metadata: " + metadata);
370 metadatum.add(metadata);
371 // Having found our metadata check if the value from the xml matches the one from the gvaluenode. If not update it. This happens whenever hierarchy information is involved (indexes rapidly become obsolete).
372 // If remove was set, remove it. We can only remove pure file level metadata, or folder level iff we were asked for folder level.
373 ///atherer.println("Have we been asked to remove the metadata: " + metadata);
374 ///atherer.println("Given:");
375 ///atherer.println("\tremove = " + remove);
376 ///atherer.println("\tfilename = " + filename);
377 ///atherer.println("\tfilename_text = " + filename_text + "?");
378 if(remove && ((filename != null && filename.matches(filename_text) && !filename_text.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME)))) {
379 ///atherer.println("Yes! Queuing for Removal.");
380 queued_for_removal.add(metadata_element);
381 }
382 else {
383 ///atherer.println("No. Updating.");
384 String current_value = metadata.getValueNode().getFullPath(false);
385 ///ystem.err.println("Checking the current mdv path: " + current_value);
386 ///ystem.err.println("Against whats in the metadata file: " + raw_value);
387 if(!raw_value.equals(current_value)) {
388 // Remove old text
389 while(metadata_element.hasChildNodes()) {
390 metadata_element.removeChild(metadata_element.getFirstChild());
391 }
392 // Add new.
393 metadata_element.appendChild(base_document.createTextNode(current_value));
394 }
395 }
396 }
397 metadata = null;
398 raw_value = null;
399 raw_element = null;
400 metadata_element = null;
401 }
402 metadata_elements = null;
403 }
404
405 // Now we remove any elements that have been queued for deletion
406 for(int a = 0; queued_for_removal != null && a < queued_for_removal.size(); a++) {
407 Element metadata_element = (Element) queued_for_removal.get(a);
408 description_element.removeChild(metadata_element);
409 up_to_date = false;
410 }
411 queued_for_removal.clear();
412 queued_for_removal = null;
413
414 // If the description_element no longer has any children remove it
415 NodeList metadata_elements = description_element.getElementsByTagName(StaticStrings.METADATA_ELEMENT);
416 NodeList extracted_elements = description_element.getElementsByTagName(StaticStrings.EXTRACTED_METADATA_ELEMENT);
417 if(metadata_elements.getLength() == 0 && extracted_elements.getLength() == 0) {
418 fileset_element.removeChild(description_element);
419 up_to_date = false;
420 }
421 description_element = null;
422 }
423 description_elements = null;
424 }
425 filename_text = null;
426 filename_element = null;
427 }
428 // If the file set no longer has any description entries, remove it entirely
429 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
430 if(description_elements.getLength() == 0) {
431 directorymetadata_element.removeChild(fileset_element);
432 up_to_date = false;
433 }
434 description_elements = null;
435 filename_elements = null;
436 fileset_element = null;
437 }
438 fileset_elements = null;
439 directorymetadata_element = null;
440 }
441 catch (Exception error) {
442 Gatherer.self.printStackTrace(error);
443 }
444 ///ystem.err.println("Found " + metadatum.size() + " pieces of metadata.");
445 return metadatum;
446 }
447
448 /** Determine if this document has been saved recently, and thus xml file version is up to date. */
449 public boolean isUpToDate() {
450 return false;
451 }
452
453 /** Determine is this is a valid Greenstone Directory Metadata file. It may of course just be some xml file with the name metadata.xml. */
454 public boolean isValid() {
455 // Just determine if the doctype is GreenstoneDirectoryMetadata and root node is called DirectoryMetadata.
456 String doctype_name = base_document.getDoctype().getName();
457 String root_name = base_document.getDocumentElement().getTagName();
458 return ((doctype_name.equals("GreenstoneDirectoryMetadata") && root_name.equals("GreenstoneDirectoryMetadata")) || (doctype_name.equals("DirectoryMetadata") && root_name.equals("DirectoryMetadata")));
459 }
460
461 /** Remove all of the extracted metadata (XMetadata) from this document. */
462 public void removeExtractedMetadata() {
463 try {
464 Element document_element = base_document.getDocumentElement();
465 NodeList extracted_metadata_elements = document_element.getElementsByTagName(StaticStrings.EXTRACTED_METADATA_ELEMENT);
466 document_element = null;
467 for(int i = extracted_metadata_elements.getLength(); i != 0; i--) {
468 Element extracted_metadata_element = (Element) extracted_metadata_elements.item(i - 1);
469 String element_name = extracted_metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
470 ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(element_name);
471 if(element != null) {
472 element.dec();
473 }
474 element = null;
475 ///ystem.err.println("Removing extracted metadata: " + element_name + "=" + MSMUtils.getValue(extracted_metadata_element));
476 element_name = null;
477 Node parent_node = extracted_metadata_element.getParentNode();
478 parent_node.removeChild(extracted_metadata_element);
479 parent_node = null;
480 extracted_metadata_element = null;
481 }
482 extracted_metadata_elements = null;
483 up_to_date = false;
484 }
485 catch(Exception exception) {
486 Gatherer.println("Exception in MetadataXMLFile.removeExtractedMetadata() - unexpected");
487 Gatherer.printStackTrace(exception);
488 }
489 }
490
491 /** Remove the given directory level metadata from this document. All directory level metadata is available under the FileSet with filename '.*'. There is at least one nasty case to consider, where the first overwriting metadata entry, of several with the same element, is removed. In this case the next entry must become overwrite to ensure proper inheritance. */
492 public void removeMetadata(String filename, Metadata metadata) {
493 Gatherer.println("Remove metadata: " + metadata + "\nFrom filename: " + filename);
494 try {
495 boolean found = false;
496 boolean first_metadata_element_found = true;
497 boolean make_next_metadata_element_overwrite = false;
498 boolean remove_fileset = false;
499 // Retrieve the document element.
500 Element directorymetadata_element = base_document.getDocumentElement();
501 // Iterate through the filesets looking for the directory level one.
502 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
503 for(int i = 0; !found && i < fileset_elements.getLength(); i++) {
504 Element fileset_element = (Element) fileset_elements.item(i);
505 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
506 for(int j = 0; !found && j < filename_elements.getLength(); j++) {
507 Element filename_element = (Element) filename_elements.item(j);
508 String filename_text = MSMUtils.getValue(filename_element);
509 if((filename != null && filename.matches(filename_text) && !filename.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME))) {
510 // Retrieve the Metadata Element for this fileset, and iterate through them looking for the one which we are to remove.
511 NodeList description_elements = fileset_element.getElementsByTagName("Description");
512 for(int k = 0; !found && k < description_elements.getLength(); k++) {
513 Element description_element = (Element) description_elements.item(k);
514 // We have to do this for each type of metadata
515 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
516 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
517 for(int l = 0; (!found || !make_next_metadata_element_overwrite) && l < metadata_elements.getLength(); l++) {
518 Element metadata_element = (Element) metadata_elements.item(l);
519 String element = metadata_element.getAttribute("name");
520 String value = MSMUtils.getValue(metadata_element);
521 // See if this is the metadata we wish to remove
522 if(element.equals(metadata.getElement().getName())) {
523 if(value.equals(metadata.getValueNode().getFullPath(false))) {
524 // Remove it
525 ///ystem.err.println("Remove " + element + "-" + value);
526 description_element.removeChild(metadata_element);
527 found = true;
528 // If this was the first metadata with this element found, and it was set to overwrite, then we have to ensure that the next metadata with this element found (if any) is changed to be overwrite now.
529 if(first_metadata_element_found && !metadata.accumulates()) {
530 ///ystem.err.println("First of this element found!");
531 make_next_metadata_element_overwrite = true;
532 }
533 }
534 // If this was the first metadata we've found with the element of the one to be removed set first found to false.
535 else if(first_metadata_element_found) {
536 ///ystem.err.println("Found a matching element: " + element + "=" + value);
537 first_metadata_element_found = false;
538 }
539 // Otherwise we should make this metadata overwrite as requested.
540 else if(make_next_metadata_element_overwrite) {
541 ///ystem.err.println("Changing to overwrite: " + element + "=" + value);
542 metadata_element.setAttribute(MODE_ATTRIBUTE, "");
543 }
544 }
545 value = null;
546 element = null;
547 metadata_element = null;
548 }
549 NodeList normal_metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[0]);
550 NodeList extracted_metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[1]);
551 // If we found it, removed it, and now the description tag has no children, mark the fileset for removal
552 if(normal_metadata_elements.getLength() == 0 && extracted_metadata_elements.getLength() == 0) {
553 remove_fileset = true;
554 }
555 extracted_metadata_elements = null;
556 normal_metadata_elements = null;
557 metadata_elements = null;
558 }
559 description_element = null;
560 }
561 description_elements = null;
562 }
563 filename_text = null;
564 filename_element = null;
565 }
566 filename_elements = null;
567 if(found && remove_fileset) {
568 directorymetadata_element.removeChild(fileset_element);
569 }
570 fileset_element = null;
571 }
572 fileset_elements = null;
573 directorymetadata_element = null;
574 up_to_date = false;
575 }
576 catch (Exception error) {
577 Gatherer.printStackTrace(error);
578 }
579 }
580
581 /** Change the up to date flag.
582 * @param up_to_date true if the document on the filesystem is the same as the one in memory, false otherwise
583 */
584 public void setUpToDate(boolean up_to_date) {
585 this.up_to_date = up_to_date;
586 }
587}
Note: See TracBrowser for help on using the repository browser.