/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE and NOTICE files at the root of the source * tree and available online at * * http://www.dspace.org/license/ */ package org.dspace.app.xmlui.objectmanager; import java.sql.SQLException; import org.dspace.app.xmlui.wing.AttributeMap; import org.dspace.app.xmlui.wing.Namespace; import org.dspace.app.xmlui.wing.WingException; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.handle.HandleManager; import org.xml.sax.SAXException; /** * This is an an adapter which translates a DSpace repository into a METS * document. Unfortunately there is no real definition of what this is. So * we just kind of made it up based upon what we saw for the item profile. * * The basic structure is simply two parts, the descriptive metadata and a * structural map. The descriptive metadata is a place to put metadata about * the whole repository. The structural map is used to map relationships * between communities & collections in dspace. * * @author Scott Phillips */ public class RepositoryAdapter extends AbstractAdapter { /** MODS namespace */ public static final String MODS_URI = "http://www.loc.gov/mods/v3"; public static final Namespace MODS = new Namespace(MODS_URI); /** A space separated list of descriptive metadata sections */ private String dmdSecIDS; /** Dspace context to be able to look up additional objects */ private Context context; /** * Construct a new RepositoryAdapter * * @param context * The DSpace context to look up communities / collections. * * @param contextPath * The contextPath of this webapplication. */ public RepositoryAdapter(Context context, String contextPath) { super(contextPath); this.context = context; } /** * * * * Abstract methods * * * */ /** * Return the handle prefix as the identifier. */ protected String getMETSID() { return HandleManager.getPrefix(); } /** * The OBJID is used to encode the URL to the object, in this * case the repository which is just at the contextPath. */ protected String getMETSOBJID() throws WingException { if (contextPath == null) { return "/"; } else { return contextPath + "/"; } } /** * @return Return the URL for editing this item */ protected String getMETSOBJEDIT() { return null; } /** * Return the profile this METS document conforms too... * * FIXME: It dosn't conform to a profile. This needs to be fixed. */ protected String getMETSProfile() { return "DRI DSPACE Repository Profile 1.0"; } /** * Return a friendly label for the METS document stating that this is a * DSpace repository. */ protected String getMETSLabel() { return "DSpace Repository"; } /** * * * * METS structural methods * * * */ /** * Render the repository's descriptive metadata section. * * For a the DSPace repository we just grab a few items * from the config file and put them into the descriptive * section, such as the name, hostname, handle prefix, and * default language. * */ protected void renderDescriptiveSection() throws SAXException { AttributeMap attributes; // Generate our ids String dmdID = getGenericID("dmd_"); String groupID = getGenericID("group_dmd_"); // //////////////////////////////// // Start a single dmdSec attributes = new AttributeMap(); attributes.put("ID", dmdID); attributes.put("GROUPID", groupID); startElement(METS,"dmdSec",attributes); // //////////////////////////////// // Start a metadata wrapper (hardcoded to mods) attributes = new AttributeMap(); attributes.put("MDTYPE", "OTHER"); attributes.put("OTHERMDTYPE", "DIM"); startElement(METS,"mdWrap",attributes); // //////////////////////////////// // Start the xml data startElement(METS,"xmlData"); ///////////////////////////////// // Start the DIM element attributes = new AttributeMap(); attributes.put("dspaceType", Constants.typeText[Constants.SITE]); startElement(DIM,"dim",attributes); // Entry for dspace.name attributes = new AttributeMap(); attributes.put("mdschema","dspace"); attributes.put("element", "name"); startElement(DIM,"field",attributes); sendCharacters(ConfigurationManager.getProperty("dspace.name")); endElement(DIM,"field"); // Entry for dspace.hostname attributes = new AttributeMap(); attributes.put("mdschema","dspace"); attributes.put("element", "hostname"); startElement(DIM,"field",attributes); sendCharacters(ConfigurationManager.getProperty("dspace.hostname")); endElement(DIM,"field"); // Entry for handle.prefix attributes = new AttributeMap(); attributes.put("mdschema","dspace"); attributes.put("element", "handle"); startElement(DIM,"field",attributes); sendCharacters(HandleManager.getPrefix()); endElement(DIM,"field"); // Entry for default.language attributes = new AttributeMap(); attributes.put("mdschema","dspace"); attributes.put("element", "default"); attributes.put("qualifier", "language"); startElement(DIM,"field",attributes); sendCharacters(ConfigurationManager.getProperty("default.language")); endElement(DIM,"field"); // /////////////////////////////// // End the DIM element endElement(DIM,"dim"); // End all the open elements. endElement(METS,"xmlData"); endElement(METS,"mdWrap"); endElement(METS,"dmdSec"); // Remember the IDS this.dmdSecIDS = dmdID; } /** * Render the repository's structure map. This map will include a reference to * all the community and collection objects showing how they are related to * one another. */ protected void renderStructureMap() throws SQLException, SAXException { AttributeMap attributes; // ////////////////////////// // Start the new struct map attributes = new AttributeMap(); attributes.put("TYPE", "LOGICAL"); attributes.put("LABEL", "DSpace"); startElement(METS,"structMap",attributes); // //////////////////////////////// // Start the special first division attributes = new AttributeMap(); attributes.put("TYPE", "DSpace Repository"); // add references to the Descriptive metadata if (dmdSecIDS != null) { attributes.put("DMDID", dmdSecIDS); } startElement(METS,"div",attributes); // Put each root level node into the document. for (Community community : Community.findAllTop(context)) { renderStructuralDiv(community); } // ////////////////// // Close special first division and structural map endElement(METS,"div"); endElement(METS,"structMap"); } /** * * * * private helpful methods * * * */ /** * Recursively the DSpace hierarchy rendering each container and subcontainers. * * @param dso * The DSpace Object to be rendered. */ private void renderStructuralDiv(DSpaceObject dso) throws SAXException, SQLException { AttributeMap attributes; // //////////////////////////////// // Start the new div for this repository container attributes = new AttributeMap(); if (dso instanceof Community) { attributes.put("TYPE", "DSpace Community"); } else if (dso instanceof Collection) { attributes.put("TYPE", "DSpace Collection"); } startElement(METS,"div",attributes); // ////////////////////////////////// // Start a metadata pointer for this container attributes = new AttributeMap(); AttributeMap attributesXLINK = new AttributeMap(); attributesXLINK.setNamespace(XLINK); attributes.put("LOCTYPE", "URL"); attributesXLINK.put("href", "/metadata/handle/"+ dso.getHandle() +"/mets.xml"); startElement(METS,"mptr",attributes,attributesXLINK); endElement(METS,"mptr"); // Recurse to insure that our children are also included even if this // node already existed in the div structure. if (dso instanceof Community) { for (DSpaceObject child : ((Community)dso).getCollections()) { renderStructuralDiv(child); } for (DSpaceObject child : ((Community)dso).getSubcommunities()) { renderStructuralDiv(child); } } // //////////////////// // Close division endElement(METS,"div"); } }