/* * IncludePageMeta.java * * Version: $Revision: 3705 $ * * Date: $Date: 2009-04-11 17:02:24 +0000 (Sat, 11 Apr 2009) $ * * Copyright (c) 2002, Hewlett-Packard Company and Massachusetts * Institute of Technology. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Hewlett-Packard Company nor the name of the * Massachusetts Institute of Technology nor the names of their * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.dspace.app.xmlui.wing; import java.io.IOException; import java.io.Serializable; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.avalon.framework.parameters.ParameterException; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.util.HashUtil; import org.apache.excalibur.source.SourceValidity; import org.apache.excalibur.source.impl.validity.NOPValidity; import org.dspace.app.xmlui.wing.element.PageMeta; import org.xml.sax.SAXException; /** * Include metadata in the resulting DRI document as derived from the sitemap * parameters. * * Parameters should consist of a dublin core name and value. The format for * a parameter name must follow the form: "<element>.<qualifier>.<language>#order" * The qualifier, language, and order are all optional components. The order * component is an integer and is needed to insure that parameter names are * unique. Since Cocoon's parameters are Hashes duplicate names are not allowed * the order syntax allows the sitemap programer to specify an order in which * these metadata values should be placed inside the document. * * The following are a valid examples: * * <map:parameter name="theme.name.en" value="My Theme"/> * * <map:parameter name="theme.path" value="/MyTheme/"/> * * <map:parameter name="theme.css#1" value="style.css"/> * * <map:parameter name="theme.css#2" value="style.css-ie"/> * * <map:parameter name="theme.css#2" value="style.css-ff"/> * * @author Scott Phillips */ public class IncludePageMeta extends AbstractWingTransformer implements CacheableProcessingComponent { /** The metadata loaded from the sitemap parameters. */ private List<Metadata> metadataList; /** * Generate the unique key. * This key must be unique inside the space of this component. * * @return The generated key hashes the src */ public Serializable getKey() { String key = ""; for (Metadata metadata : metadataList) { key = "-" + metadata.getName() + "=" + metadata.getValue(); } return HashUtil.hash(key); } /** * Generate the validity object. * * @return The generated validity object or <code>null</code> if the * component is currently not cacheable. */ public SourceValidity getValidity() { return NOPValidity.SHARED_INSTANCE; } /** * Extract the metadata name value pairs from the sitemap parameters. */ public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException { try { String[] names = parameters.getNames(); metadataList = new ArrayList<Metadata>(); for (String name : names) { String[] nameParts = name.split("#"); String dcName = null; int order = -1; if (nameParts.length == 1) { dcName = nameParts[0]; order = 1; } else if (nameParts.length == 2) { dcName = nameParts[0]; order = Integer.valueOf(nameParts[1]); } else { throw new ProcessingException("Unable to parse page metadata name, '" + name + "', into parts."); } String[] dcParts = dcName.split("\\."); String element = null; String qualifier = null; String language = null; if (dcParts.length == 1) { element = dcParts[0]; } else if (dcParts.length == 2) { element = dcParts[0]; qualifier = dcParts[1]; } else if (dcParts.length == 3) { element = dcParts[0]; qualifier = dcParts[1]; language = dcParts[2]; } else { throw new ProcessingException("Unable to parse page metadata name, '" + name + "', into parts."); } String value = parameters.getParameter(name); Metadata metadata = new Metadata(element,qualifier,language,order,value); metadataList.add(metadata); } Collections.sort(metadataList); } catch (ParameterException pe) { throw new ProcessingException(pe); } // Initialize the Wing framework. try { this.setupWing(); } catch (WingException we) { throw new ProcessingException(we); } } /** * Include the metadata in the page metadata. */ public void addPageMeta(PageMeta pageMeta) throws WingException { for (Metadata metadata : metadataList) { String element = metadata.getElement(); String qualifier = metadata.getQualifier(); String language = metadata.getLanguage(); String value = metadata.getValue(); // Add our new metadata. pageMeta.addMetadata(element, qualifier, language) .addContent(value); } } /** * Private class to keep track of metadata name/value pairs. */ class Metadata implements Comparable<Metadata> { private String element; private String qualifier; private String language; private int order; private String value; public Metadata(String element,String qualifier, String language, int order, String value) { this.element = element; this.qualifier = qualifier; this.language = language; this.order = order; this.value = value; } public String getElement() { return this.element; } public String getQualifier() { return this.qualifier; } public String getLanguage() { return this.language; } public int getOrder() { return this.order; } public String getName() { String name = this.element; if (this.qualifier != null) { name += "." + this.qualifier; if (this.language != null) { name += "." + this.language; } } name += "#" + order; return name; } public String getValue() { return this.value; } public int compareTo(Metadata other) { String myName = this.element + "." +this.qualifier + "." + this.language; String otherName = other.element + "." + other.qualifier + "." + other.language; int result = myName.compareTo(otherName); if (result == 0) { if (this.order == other.order ) { result = 0; // These two metadata element's names are completely identical. } else if (this.order > other.order) { result = 1; // The other metadata element belongs AFTER this element. } else { result = -1; // The other metadata element belongs BEFORE this element. } } return result; } } }