package org.greenstone.gsdl3.gs3build.doctypes; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.util.HashMap; import java.util.Map; import java.sql.SQLException; import java.sql.ResultSet; import java.net.URL; import org.greenstone.gsdl3.gs3build.metadata.NamespaceFactory; import org.greenstone.gsdl3.gs3build.metadata.GSDL3Namespace; import org.greenstone.gsdl3.gs3build.metadata.METSDescriptiveSet; import org.greenstone.gsdl3.gs3build.metadata.METSFile; import org.greenstone.gsdl3.gs3build.metadata.METSFileSet; import org.greenstone.gsdl3.gs3build.metadata.METSHeader; import org.greenstone.gsdl3.gs3build.metadata.METSStructure; import org.greenstone.gsdl3.gs3build.metadata.METSStructureSet; import org.greenstone.gsdl3.gs3build.metadata.METSDivision; import org.greenstone.gsdl3.gs3build.metadata.METSNamespace; import org.greenstone.gsdl3.gs3build.util.MultiMap; import org.greenstone.gsdl3.gs3build.util.GS3SQLConnection; /** * Provide a base-line functionality for the DocumentInterface * class. */ public abstract class AbstractDocument implements DocumentInterface { METSFileSet fileSet; METSDescriptiveSet metadata; METSStructureSet structureSet; METSHeader header; DocumentID id; boolean isModified; /** *

Create a very vanilla document with a given document identifier.

*

Most commonly used in dealing with loading files using DocumentFactory * or similar.

* * @param DocumentID the document identifier */ public AbstractDocument(DocumentID id) { this.fileSet = new METSFileSet(); this.metadata = new METSDescriptiveSet(); this.header = new METSHeader(); this.structureSet = new METSStructureSet(); this.id = id; } /** * Create a basic document from a given URLURL the URL of the first file in the document package */ public AbstractDocument(URL url) { this.fileSet = new METSFileSet(); METSFile metsFile = this.fileSet.addFile(url); this.metadata = new METSDescriptiveSet(); this.header = new METSHeader(); this.structureSet = new METSStructureSet(); this.id = null; METSStructure structure = new METSStructure("All", "All", "Whole Document"); METSDivision documentBody = new METSDivision("All", "All", "All", "Whole Document", "Document"); structure.addDivision(documentBody); this.structureSet.addStructure(structure); documentBody.addFileReference(metsFile.getID()); documentBody.addMetadataReference("DM1"); } /** * Set the identified for the document. Every document should have * a document number set on its accession, either through metadata * placed upon it internally or externally, or by assignment through * a DocumentIDFactory. Each identifier should be * unique. * * @param DocumentID the document identifier - in XML * terms, the gsdl3:id element. */ public void setID(DocumentID id) { this.id = id; this.isModified = true; } /** * Get the document identifier - this should be unique to the document, * but care must be taken in the configuration of the collection to * ensure that this is the case. * * @return DocumentID the identifer */ public DocumentID getID() { return this.id; } /** * Indicate whether this document is indexed. * * @see: DocumentInterface.isIndexed */ public boolean isIndexed() { return true; } /** * Obtain the METS header of this document * * @return METSHeader the header */ public METSHeader getHeader() { return this.header; } /** * Set the METS header for this document. * * @param METSHeader the header */ public void setHeader(METSHeader header) { this.header = header; } /** * A simple implementation of the isDocumentType function that does not consider * inheritance - it must be extended as required. */ public boolean isDocumentType(String type) { return type.equals(this.getDocumentType()); } public abstract String getDocumentType(); public abstract String getDocumentText(); public abstract String getSectionText(String sectionId); public String getMETSType() { return "document"; } /** * @see DocumentInterface:addDocumentMetadata */ public void addDocumentMetadata(String name, String value) { int colonAt = name.indexOf(":"); String namespace; if (colonAt > 0) { namespace = name.substring(0, colonAt); name = name.substring(colonAt+1); } else { namespace = GSDL3Namespace.GSDL3_NAMESPACE_ID; } // no need to set isModified, as the following call will do it anyway! this.addDocumentMetadata(namespace, name, value); } /** * @see DocumentInterface:addDocumentMetadata */ public void addDocumentMetadata(String namespace, String label, String value) { this.metadata.addMetadata("default", namespace, label, value); this.isModified = true; } /** * Post metadata to a file in this document - the appropriate changes * should be made... */ public void postFileMetadata(URL fileLocation, String namespace, String label, String value) { // First get the list of file groups, etc. that this file is associated with... List fileGroups = this.fileSet.findGroups(fileLocation); // Next, get the METS divisions associated with each file group... List divisions = this.structureSet.findDivisionsForFiles(fileGroups); // Finally, post the metadata to the metadata group associated with each structure Iterator divisionIter = divisions.iterator(); while (divisionIter.hasNext()) { METSDivision division = (METSDivision) divisionIter.next(); // get the open namespace for this division METSNamespace namespaceMetadata = division.findNamespace(namespace, true, this.metadata); // then post the metadata to it... namespaceMetadata.addMetadata(label, value); } } /** * @see DocumentInterface:setDocumentMetadata */ public void setDocumentMetadata(String namespace, String label, String value) { this.metadata.setMetadata("default", namespace, label, value); this.isModified = true; } /** * Get the metadata structure of the document * * @return METSDescriptive the metadata holder for the document. */ public METSDescriptiveSet getDocumentMetadata() { return this.metadata; } /** * Set the metadata structure for this document * * @param METSDescriptive the new metadata holder for the document. */ public void setDocumentMetadata(METSDescriptiveSet metadata) { this.metadata = metadata; this.isModified = true; } /** * Get the metadata structure of the document * * @return METSStructureSet the metadata holder for the document. */ public METSStructureSet getDocumentStructure() { return this.structureSet; } public void setDocumentStructure(METSStructureSet structureSet) { this.structureSet = structureSet; } /** * Get the values associated with a particular metadata value. * * @param String the namespace to find the values in. * @param String the label to match to find the values. * * @return List the values. */ public List getDocumentMetadataItem(String namespace, String label) { return this.metadata.getMetadata("default", namespace, label); } /** * Get the values associated with a particular metadata value. * * @param String the namespace and label separated by a * colon. * * @return List the values. */ public List getDocumentMetadataItem(String namespaceLabel) { String namespace, label; int colonAt = namespaceLabel.indexOf(':'); if (colonAt < 0) { namespace = GSDL3Namespace.GSDL3_NAMESPACE_ID; label = namespaceLabel; } else { namespace = namespaceLabel.substring(0, colonAt); label = namespaceLabel.substring(colonAt+1); } return this.metadata.getMetadata("default", namespace, label); } /** * @see DocumentInterface:getDocumentFiles */ public METSFileSet getDocumentFiles() { return this.fileSet; } public void setDocumentFiles(METSFileSet fileSet) { this.fileSet = fileSet; } /** * @see DocumentInterface:isMETSCompatible */ public boolean isMETSCompatible() { return true; } /** * Use a default document writer - this may be overridden for subclasses... * * @see DocumentInterface:writeMETSObject */ public DocumentWriter getMETSWriter() { return new DocumentWriter(); } /** * Use a default SQL document writer - this may be overridden for subclasses... * */ public DocumentSQLWriter getSQLWriter() { return new DocumentSQLWriter(); } /** * Obtain a document from the SQL database */ public static AbstractDocument readSQL(GS3SQLConnection connection, ResultSet sqlResult) { try { DocumentID id = new DocumentID(sqlResult.getString("DocID")); String type = sqlResult.getString("docType"); // Use a factory method to create the correct subtype... AbstractDocument document = DocumentFactory.createDocument(type, id); // Get the individual components of the document METSFileSet fileSet = METSFileSet.readSQL(document, connection); document.setDocumentFiles(fileSet); METSDescriptiveSet descriptiveSet = METSDescriptiveSet.readSQL(document, connection); document.setDocumentMetadata(descriptiveSet); METSStructureSet structureSet = METSStructureSet.readSQL(document, connection); document.setDocumentStructure(structureSet); // indicate that the document is not currently modified document.setModified(false); return document; } catch (SQLException sqlEx) { } return null; } /** * */ public boolean isModified() { return this.isModified; } public void setModified(boolean isModified) { this.isModified = isModified; } }