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

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

Fixed a bug matching filenames to metadata.xml filesets.

  • Property svn:keywords set to Author Date Id Revision
File size: 29.4 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 gdm_element = base_document.getDocumentElement();
90
91 // Find the fileset element for the filename
92 Element fileset_element = findFileSetElementForFile(gdm_element, filename);
93
94 // If there is no existing fileset, then create one
95 if (fileset_element == null) {
96 // System.err.println("Creating a new fileset.");
97 fileset_element = base_document.createElement(FILESET_ELEMENT);
98 Element filename_element = base_document.createElement(FILENAME_ELEMENT);
99 Element description_element = base_document.createElement(DESCRIPTION_ELEMENT);
100 fileset_element.appendChild(filename_element);
101 fileset_element.appendChild(description_element);
102 Text filename_text = null;
103 // If the filename is null then we add a directory metadata set as gdm_element's first child
104 if (filename == null) {
105 filename_text = base_document.createTextNode(DIRECTORY_FILENAME);
106 if (gdm_element.hasChildNodes()) {
107 gdm_element.insertBefore(fileset_element, gdm_element.getFirstChild());
108 }
109 else {
110 gdm_element.appendChild(fileset_element);
111 }
112 }
113 // Otherwise we append the new fileset to gdm_element's children
114 else {
115 // System.err.println("New fileset for " + filename);
116 filename = Codec.transform(filename, Codec.TEXT_TO_REGEXP);
117 // System.err.println("After transform: " + filename);
118 filename_text = base_document.createTextNode(filename);
119 gdm_element.appendChild(fileset_element);
120 }
121 filename_element.appendChild(filename_text);
122 filename_text = null;
123 description_element = null;
124 filename_element = null;
125 }
126 // Now, finally, we can add the metadata.
127 Element metadata_element = null;
128 String name = metadata.getElement().getName();
129 // If this is extracted metadata, we use a special element name that won't be recognized by greenstone
130 if(name.startsWith(Utility.EXTRACTED_METADATA_NAMESPACE)) {
131 metadata_element = base_document.createElement(ALL_METADATA_TYPES[1]);
132 name = name.substring(Utility.EXTRACTED_METADATA_NAMESPACE.length() + 1);
133 }
134 else {
135 metadata_element = base_document.createElement(ALL_METADATA_TYPES[0]);
136 }
137 metadata_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
138
139 // To determine if this metadata entry should overwrite or accumulate we check if there are other entries with the same element in this fileset.
140 boolean will_accumulate = false;
141 NodeList sibling_description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
142 for(int k = 0; !will_accumulate && k < sibling_description_elements.getLength(); k++) {
143 Element sibling_description_element = (Element) sibling_description_elements.item(k);
144 // We have to do this for each type of metadata
145 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
146 NodeList sibling_metadata_elements = sibling_description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
147 for(int l = 0; !will_accumulate && l < sibling_metadata_elements.getLength(); l++) {
148 Element sibling_metadata_element = (Element) sibling_metadata_elements.item(l);
149 // 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.
150 if(sibling_metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE))) {
151 // Check the values and return if they are the same.
152 if(metadata.getAbsoluteValue().equals(MSMUtils.getValue(sibling_metadata_element))) {
153 return;
154 }
155 will_accumulate = true;
156 }
157 sibling_metadata_element = null;
158 }
159 sibling_metadata_elements = null;
160 }
161 sibling_description_element = null;
162 }
163 sibling_description_elements = null;
164 if(will_accumulate || force_accumulate) { //mode.equals(ACCUMULATE)) {
165 metadata_element.setAttribute(MODE_ATTRIBUTE, ACCUMULATE);
166 }
167 // 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
168 GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(metadata.getElement());
169 String node_value = null;
170 if(model != null && model.isHierarchy()) {
171 //node_value = /odec.transform(metadata.getValueNode().getFullPath(false), /odec.TEXT_TO_DOM);
172 node_value = metadata.getValueNode().getFullPath(false);
173 }
174 else {
175 node_value = metadata.getAbsoluteValue();
176 }
177 ///ystem.err.println("Creating node in MetadataXMLFile: '" + node_value + "'");
178 metadata_element.appendChild(base_document.createTextNode(node_value));
179 // Retrieve the first description element for this fileset (there should only be one, but I'll play it safe).
180 NodeList description_elements = fileset_element.getElementsByTagName("Description");
181 Element description_element = (Element) description_elements.item(0);
182 description_element.appendChild(metadata_element);
183 description_element = null;
184 metadata_element = null;
185 fileset_element = null;
186 gdm_element = null;
187 up_to_date = false;
188 }
189 catch (Exception error) {
190 Gatherer.printStackTrace(error);
191 }
192 }
193
194 public int countMetadata() {
195 int count = 0;
196 try {
197 // Retrieve the document element.
198 Element directorymetadata_element = base_document.getDocumentElement();
199 // Iterate through the filesets, checking the FileName child element against the target file's name using regular expression matching.
200 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
201 for(int i = 0; i < fileset_elements.getLength(); i++) {
202 Element fileset_element = (Element) fileset_elements.item(i);
203 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
204 for(int k = 0; k < description_elements.getLength(); k++) {
205 Element description_element = (Element) description_elements.item(k);
206 // We have to do this for each type of metadata
207 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
208 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
209 count = count + metadata_elements.getLength();
210 metadata_elements = null;
211 }
212 description_element = null;
213 }
214 description_elements = null;
215 fileset_element = null;
216 }
217 fileset_elements = null;
218 directorymetadata_element = null;
219 }
220 catch (Exception error) {
221 Gatherer.printStackTrace(error);
222 }
223 return count;
224 }
225
226
227 private Element findFileSetElementForFile(Element gdm_element, String filename)
228 {
229 // Iterate through the filesets looking for one that matches the given filename
230 NodeList fileset_elements = gdm_element.getElementsByTagName(FILESET_ELEMENT);
231 for (int i = 0; i < fileset_elements.getLength(); i++) {
232 Element fileset_element = (Element) fileset_elements.item(i);
233
234 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
235 for (int j = 0; j < filename_elements.getLength(); j++) {
236 Element filename_element = (Element) filename_elements.item(j);
237 String filename_pattern = MSMUtils.getValue(filename_element);
238
239 // System.err.println("Checking " + filename + " against " + filename_pattern);
240
241 // Is this a file match?
242 if (filename != null && filename.matches(filename_pattern) &&
243 !filename_pattern.equals(DIRECTORY_FILENAME)) {
244 // System.err.println("Existing file fileset!");
245 return fileset_element;
246 }
247 // Is this a folder match?
248 else if (filename == null && filename_pattern.equals(DIRECTORY_FILENAME)) {
249 // System.err.println("Existing folder fileset!");
250 return fileset_element;
251 }
252 }
253 }
254
255 // No match found
256 return null;
257 }
258
259
260 /** Retrieve the document this class is wrapping. */
261 public Document getDocument() {
262 return base_document;
263 }
264
265 /** Get all of the metadata, including directory level, associated with this file. */
266 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file, boolean append_folder_level) {
267 return getMetadata(filename, remove, metadatum_so_far, file, append_folder_level, false);
268 }
269 /** 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. */
270 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file, boolean append_folder_level, boolean purge) {
271 Gatherer.println("Get metadata for " + filename);
272 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);
273 // Of course null is not an acceptable filename
274 //if(filename == null) {
275 // return metadatum_so_far;
276 //}
277 ArrayList metadatum = null;
278 ArrayList queued_for_removal = new ArrayList();
279 if(metadatum_so_far == null) {
280 metadatum = new ArrayList();
281 }
282 else {
283 metadatum = metadatum_so_far;
284 }
285 try {
286 // Retrieve the document element.
287 Element directorymetadata_element = base_document.getDocumentElement();
288 // Iterate through the filesets, checking the FileName child element against the target file's name using regular expression matching.
289 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
290 for(int i = 0; i < fileset_elements.getLength(); i++) {
291 Element fileset_element = (Element) fileset_elements.item(i);
292 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
293 for(int j = 0; j < filename_elements.getLength(); j++) {
294 Element filename_element = (Element) filename_elements.item(j);
295 String filename_text = MSMUtils.getValue(filename_element);
296 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) {
297 // If they match add all of the metadata found in the Description child element, remembering to abide by desired mode (accumulate vs. overwrite).
298 // Normal metadata
299 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
300 for(int k = 0; k < description_elements.getLength(); k++) {
301 Element description_element = (Element) description_elements.item(k);
302 // We have to do this for each type of metadata
303 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
304 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
305 for(int l = 0; l < metadata_elements.getLength(); l++) {
306 Element metadata_element = (Element) metadata_elements.item(l);
307 String raw_element = metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
308 //String language = metadata_element.getAttribute("language");
309 String mode = metadata_element.getAttribute(MODE_ATTRIBUTE);
310 String raw_value = MSMUtils.getValue(metadata_element);
311 //
312 //raw_value = Codec.transform(raw_value, Codec.DOM_TO_);
313 ///ystem.err.println("Retrieved raw value: " + raw_value);
314 // ***** LEGACY SUPPORT *****
315 // If this raw_value contains a '\' character, but no '\\', '[' or ']' characters, then replace the '\' with a '\\'
316 if(raw_value.indexOf(StaticStrings.ESCAPE_STR) != -1) {
317 ///ystem.err.println("Blarg");
318 Gatherer.println("Detected Legacy Path: " + raw_value);
319 raw_value = raw_value.replaceAll(StaticStrings.ESCAPE_PATTERN, StaticStrings.PIPE_STR);
320 Gatherer.println("Updated Path To: " + raw_value);
321 MSMUtils.setValue(metadata_element, raw_value);
322 }
323 // **************************
324 // Using the element string and value, retrieve a matching Metadata object from the cache
325 Metadata metadata = null;
326 // If this element has hierarchy values then we must ensure the raw value is a full path, not an index.
327 // 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
328 if(MetadataXMLFileManager.metadata_cache.contains(raw_element, raw_value) && !purge) {
329 ///ystem.err.println("HIT! Retrieve metadata from cache: " + raw_element + " -> " + raw_value + "\n");
330 metadata = (Metadata) MetadataXMLFileManager.metadata_cache.get(raw_element, raw_value);
331 }
332 else {
333 ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(raw_element);
334 if (element != null) {
335 GValueNode value = Metadata.getDefaultValueNode(element, raw_value);
336 ///ystem.err.println("Miss. Create new metadata: " + raw_element + " -> " + raw_value + "\n");
337 metadata = new Metadata(element, value);
338 if(!purge) {
339 MetadataXMLFileManager.metadata_cache.put(raw_element, raw_value, metadata);
340 }
341 ///ystem.err.println("Added metadata to cache: " + raw_element + " -> " + raw_value + "\n");
342 value = null;
343 element = null;
344 }
345 }
346
347 // Determine whether this metadata is file or folder level
348 if (metadata != null) {
349 // The metadata is folder level if the file expression matches .*
350 if (filename_text != null && filename_text.equals(DIRECTORY_FILENAME)) {
351 metadata.setFileLevel(false);
352 }
353 // Otherwise it must be file level
354 else {
355 metadata.setFileLevel(true);
356 }
357
358 metadata.setFile(file);
359 // If mode is overwrite, then remove any previous values for this metadata element.
360 if(mode.equals("accumulate")) {
361 metadata.setAccumulate(true);
362 }
363 else {
364 metadata.setAccumulate(false);
365 ///ystem.err.println("Metadata overwrites: " + metadata);
366 for(int m = metadatum.size() - 1; m >= 0; m--) {
367 Metadata old_metadata = (Metadata) metadatum.get(m);
368 if(old_metadata.getElement().equals(metadata.getElement())) {
369 metadatum.remove(m);
370 ///ystem.err.println("Removing overridden metadata: " + old_metadata);
371 }
372 old_metadata = null;
373 }
374 }
375 mode = null;
376 // Add the completed metadata and clean up
377 ///ystem.err.println("Adding metadata: " + metadata);
378 metadatum.add(metadata);
379 // 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).
380 // If remove was set, remove it. We can only remove pure file level metadata, or folder level iff we were asked for folder level.
381 ///atherer.println("Have we been asked to remove the metadata: " + metadata);
382 ///atherer.println("Given:");
383 ///atherer.println("\tremove = " + remove);
384 ///atherer.println("\tfilename = " + filename);
385 ///atherer.println("\tfilename_text = " + filename_text + "?");
386 if(remove && ((filename != null && filename.matches(filename_text) && !filename_text.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME)))) {
387 ///atherer.println("Yes! Queuing for Removal.");
388 queued_for_removal.add(metadata_element);
389 }
390 else {
391 ///atherer.println("No. Updating.");
392 String current_value = metadata.getValueNode().getFullPath(false);
393 ///ystem.err.println("Checking the current mdv path: " + current_value);
394 ///ystem.err.println("Against whats in the metadata file: " + raw_value);
395 if(!raw_value.equals(current_value)) {
396 // Remove old text
397 while(metadata_element.hasChildNodes()) {
398 metadata_element.removeChild(metadata_element.getFirstChild());
399 }
400 // Add new.
401 metadata_element.appendChild(base_document.createTextNode(current_value));
402 }
403 }
404 }
405 metadata = null;
406 raw_value = null;
407 raw_element = null;
408 metadata_element = null;
409 }
410 metadata_elements = null;
411 }
412
413 // Now we remove any elements that have been queued for deletion
414 for(int a = 0; queued_for_removal != null && a < queued_for_removal.size(); a++) {
415 Element metadata_element = (Element) queued_for_removal.get(a);
416 description_element.removeChild(metadata_element);
417 up_to_date = false;
418 }
419 queued_for_removal.clear();
420 queued_for_removal = null;
421
422 // If the description_element no longer has any children remove it
423 NodeList metadata_elements = description_element.getElementsByTagName(StaticStrings.METADATA_ELEMENT);
424 NodeList extracted_elements = description_element.getElementsByTagName(StaticStrings.EXTRACTED_METADATA_ELEMENT);
425 if(metadata_elements.getLength() == 0 && extracted_elements.getLength() == 0) {
426 fileset_element.removeChild(description_element);
427 up_to_date = false;
428 }
429 description_element = null;
430 }
431 description_elements = null;
432 }
433 filename_text = null;
434 filename_element = null;
435 }
436 // If the file set no longer has any description entries, remove it entirely
437 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
438 if(description_elements.getLength() == 0) {
439 directorymetadata_element.removeChild(fileset_element);
440 up_to_date = false;
441 }
442 description_elements = null;
443 filename_elements = null;
444 fileset_element = null;
445 }
446 fileset_elements = null;
447 directorymetadata_element = null;
448 }
449 catch (Exception error) {
450 Gatherer.self.printStackTrace(error);
451 }
452 ///ystem.err.println("Found " + metadatum.size() + " pieces of metadata.");
453 return metadatum;
454 }
455
456 /** Determine if this document has been saved recently, and thus xml file version is up to date. */
457 public boolean isUpToDate() {
458 return false;
459 }
460
461 /** Determine is this is a valid Greenstone Directory Metadata file. It may of course just be some xml file with the name metadata.xml. */
462 public boolean isValid() {
463 // Just determine if the doctype is GreenstoneDirectoryMetadata and root node is called DirectoryMetadata.
464 String doctype_name = base_document.getDoctype().getName();
465 String root_name = base_document.getDocumentElement().getTagName();
466 return ((doctype_name.equals("GreenstoneDirectoryMetadata") && root_name.equals("GreenstoneDirectoryMetadata")) || (doctype_name.equals("DirectoryMetadata") && root_name.equals("DirectoryMetadata")));
467 }
468
469 /** Remove all of the extracted metadata (XMetadata) from this document. */
470 public void removeExtractedMetadata() {
471 try {
472 Element document_element = base_document.getDocumentElement();
473 NodeList extracted_metadata_elements = document_element.getElementsByTagName(StaticStrings.EXTRACTED_METADATA_ELEMENT);
474 document_element = null;
475 for(int i = extracted_metadata_elements.getLength(); i != 0; i--) {
476 Element extracted_metadata_element = (Element) extracted_metadata_elements.item(i - 1);
477 String element_name = extracted_metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
478 ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(element_name);
479 if(element != null) {
480 element.dec();
481 }
482 element = null;
483 ///ystem.err.println("Removing extracted metadata: " + element_name + "=" + MSMUtils.getValue(extracted_metadata_element));
484 element_name = null;
485 Node parent_node = extracted_metadata_element.getParentNode();
486 parent_node.removeChild(extracted_metadata_element);
487 parent_node = null;
488 extracted_metadata_element = null;
489 }
490 extracted_metadata_elements = null;
491 up_to_date = false;
492 }
493 catch(Exception exception) {
494 Gatherer.println("Exception in MetadataXMLFile.removeExtractedMetadata() - unexpected");
495 Gatherer.printStackTrace(exception);
496 }
497 }
498
499 /** 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. */
500 public void removeMetadata(String filename, Metadata metadata) {
501 Gatherer.println("Remove metadata: " + metadata + "\nFrom filename: " + filename);
502 try {
503 boolean found = false;
504 boolean first_metadata_element_found = true;
505 boolean make_next_metadata_element_overwrite = false;
506 boolean remove_fileset = false;
507 // Retrieve the document element.
508 Element directorymetadata_element = base_document.getDocumentElement();
509 // Iterate through the filesets looking for the directory level one.
510 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
511 for(int i = 0; !found && i < fileset_elements.getLength(); i++) {
512 Element fileset_element = (Element) fileset_elements.item(i);
513 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
514 for(int j = 0; !found && j < filename_elements.getLength(); j++) {
515 Element filename_element = (Element) filename_elements.item(j);
516 String filename_text = MSMUtils.getValue(filename_element);
517 if((filename != null && filename.matches(filename_text) && !filename.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME))) {
518 // Retrieve the Metadata Element for this fileset, and iterate through them looking for the one which we are to remove.
519 NodeList description_elements = fileset_element.getElementsByTagName("Description");
520 for(int k = 0; !found && k < description_elements.getLength(); k++) {
521 Element description_element = (Element) description_elements.item(k);
522 // We have to do this for each type of metadata
523 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) {
524 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]);
525 for(int l = 0; (!found || !make_next_metadata_element_overwrite) && l < metadata_elements.getLength(); l++) {
526 Element metadata_element = (Element) metadata_elements.item(l);
527 String element = metadata_element.getAttribute("name");
528 String value = MSMUtils.getValue(metadata_element);
529 // See if this is the metadata we wish to remove
530 if(element.equals(metadata.getElement().getName())) {
531 if(value.equals(metadata.getValueNode().getFullPath(false))) {
532 // Remove it
533 ///ystem.err.println("Remove " + element + "-" + value);
534 description_element.removeChild(metadata_element);
535 found = true;
536 // 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.
537 if(first_metadata_element_found && !metadata.accumulates()) {
538 ///ystem.err.println("First of this element found!");
539 make_next_metadata_element_overwrite = true;
540 }
541 }
542 // If this was the first metadata we've found with the element of the one to be removed set first found to false.
543 else if(first_metadata_element_found) {
544 ///ystem.err.println("Found a matching element: " + element + "=" + value);
545 first_metadata_element_found = false;
546 }
547 // Otherwise we should make this metadata overwrite as requested.
548 else if(make_next_metadata_element_overwrite) {
549 ///ystem.err.println("Changing to overwrite: " + element + "=" + value);
550 metadata_element.setAttribute(MODE_ATTRIBUTE, "");
551 }
552 }
553 value = null;
554 element = null;
555 metadata_element = null;
556 }
557 NodeList normal_metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[0]);
558 NodeList extracted_metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[1]);
559 // If we found it, removed it, and now the description tag has no children, mark the fileset for removal
560 if(normal_metadata_elements.getLength() == 0 && extracted_metadata_elements.getLength() == 0) {
561 remove_fileset = true;
562 }
563 extracted_metadata_elements = null;
564 normal_metadata_elements = null;
565 metadata_elements = null;
566 }
567 description_element = null;
568 }
569 description_elements = null;
570 }
571 filename_text = null;
572 filename_element = null;
573 }
574 filename_elements = null;
575 if(found && remove_fileset) {
576 directorymetadata_element.removeChild(fileset_element);
577 }
578 fileset_element = null;
579 }
580 fileset_elements = null;
581 directorymetadata_element = null;
582 up_to_date = false;
583 }
584 catch (Exception error) {
585 Gatherer.printStackTrace(error);
586 }
587 }
588
589 /** Change the up to date flag.
590 * @param up_to_date true if the document on the filesystem is the same as the one in memory, false otherwise
591 */
592 public void setUpToDate(boolean up_to_date) {
593 this.up_to_date = up_to_date;
594 }
595}
Note: See TracBrowser for help on using the repository browser.