package org.greenstone.gsdl3.gs3build.metadata; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.ArrayList; import java.util.HashMap; import org.greenstone.gsdl3.gs3build.util.MultiMap; import org.greenstone.gsdl3.gs3build.util.XMLTools; /** * Implement a generic, ordered namespace in METS. * * @see: org.greenstone.gsdl3.gs3build.metadata.METSNamespace */ public class OrderedNamespace extends METSNamespace { List metadataList; public OrderedNamespace(String name) { super(name); this.metadataList = new ArrayList(); } public OrderedNamespace(String name, METSLocation location) { super(name, location); this.metadataList = new ArrayList(); } public boolean validate(String field, String value) { return true; } /** * Add a metadata item. Whether the field and value validate for this * schema will also be tested. * * @param String the name of the field to be given the value * @param String the value to be assigned * * @return boolean whether the field value was added. This * would return false if the values did not validate, * for example. */ public boolean addMetadata(String label, String value) { if (!this.validate(label, value)) { return false; } this.metadataList.add(new NamespaceItem(label, value)); return true; } /** * Assign a metadata item. Whether the field and value validate for this * schema will also be tested. Any existing metadata for that field will * be destroyed if the new value validates. * * @param String the name of the field to be given the value * @param String the value to be assigned * * @return boolean whether the field value was added. This * would return false if the values did not validate, * for example. */ public boolean setMetadata(String label, String value) { if (!this.validate(label, value)){ return false; } // TODO: this.metadataMap.setOnly(label, value); int itemNo = this.findItem(label); if (itemNo >= 0){ this.metadataList.set(itemNo, new NamespaceItem(label, value)); return true; } return false; } /** * Remove all metadata values for a given field name * * @param String the field to delete * * @return boolean whether the field was actually deleted; * will return true if the field was already empty. */ public boolean removeMetadata(String label) { int itemNo; itemNo = this.findItem(label); while (itemNo >= 0){ this.metadataList.remove(itemNo); itemNo = this.findItem(label); } return true; } /** * Remove a particular incidence of a given metadata field for a document. * If an exact match for the given value is not found, nothing changes. * N.B. if a value occurs twice, only the first incidence of it will be * deleted from the list. * * @param String the field to have the value removed * @param String the value to be removed from a given field * * @return boolean true if an actual metadata text * is matched against the given value and is thus deleted. */ public boolean removeMetadata(String label, String value) { int itemNo; itemNo = this.findItem(label); if (itemNo >= 0) { this.metadataList.remove(itemNo); return true; } return false; } /** * Get the metadata items for a particular label * * @param String the label to fetch values for - must be devoid * of namespace prologue (i.e. "title" rather than * e.g. "dc:title"). * * @return List the list of corresponding values. May be * null if no values are found for the metadata */ public List getMetadata(String label) { List resultList = new ArrayList(); for (int i = 0; i < this.metadataList.size(); i ++) { NamespaceItem item = (NamespaceItem) this.metadataList.get(i); if (item.getLabel().equals(label)){ resultList.add(item.getValue()); } } if (resultList.size() > 0){ return resultList; } return null; } private int findItem(String label) { for (int i = 0; i < this.metadataList.size(); i ++) { if (((NamespaceItem) this.metadataList.get(i)).getLabel().equals(label)){ return i; } } return -1; } private int findItem(String label, String value) { for (int i = 0; i < this.metadataList.size(); i ++){ NamespaceItem item = (NamespaceItem) this.metadataList.get(i); if (item.getLabel().equals(label) && item.getValue().equals(value)){ return i; } } return -1; } public Iterator getMetadataNames() { return this.metadataList.iterator(); } /** * Write out the metadata to an XML file through a PrintWriter. * * @param PrintWriter the writer to use. */ public boolean write(PrintWriter writer) { // if this is a non-file block of metadata, write it out in long hand if (this.location == null){ String tag = XMLTools.getOpenTag("mets", "mdWrap"); tag = XMLTools.addAttribute(tag, "MDTYPE", "OTHER"); tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name); if (this.id != null) { this.id = "gsdl"+this.id; tag = XMLTools.addAttribute(tag, "ID", this.id); } writer.print(" "); //indentation writer.println(tag); Iterator items = this.metadataList.iterator(); while (items.hasNext()){ NamespaceItem item = (NamespaceItem) items.next(); this.writeItem(writer, item); } writer.print(" "); //indentation writer.println(""); } // otherwise, drop the metadata out in a simplified file-reference // form only else { String tag = XMLTools.getOpenTag("mets", "mdRef"); tag = XMLTools.addAttribute(tag, "LOCTYPE", this.location.getType()); tag = XMLTools.addAttribute(tag, "xlink:href", this.location.getLocation().toString()); tag = XMLTools.addAttribute(tag, "MDTYPE", this.name); //tag = XMLTools.addAttribute (tag, "MDTYPE", "OTHER"); //tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name); if (this.id != null) { tag = XMLTools.addAttribute(tag, "ID", this.id); } tag = XMLTools.makeSingleton(tag); } return true; } /** * Write out a single element - this may be overloaded to provide for the * appropriate formatting for this metadata. */ protected boolean writeItem(PrintWriter writer, NamespaceItem item) { // Do some default sillinesses //writer.write(" "); writer.write(XMLTools.getOpenTag(this.name, item.getLabel())); writer.write(item.getValue()); writer.write(XMLTools.getCloseTag(this.name, item.getLabel())); return true; } /** *

Indicate whether this metadata is open to being changed or not.

*

Metadata which is created from a distinct file cannot be changed, * only those which have no associated file can be modified. * * @return boolean whether this namespace can be altered. */ public boolean isEditable() { return (this.location == null); } }