/**
* 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.opensearch;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Map;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.generation.AbstractGenerator;
import org.apache.cocoon.util.HashUtil;
import org.apache.cocoon.xml.dom.DOMStreamer;
import org.apache.excalibur.source.SourceValidity;
import org.apache.excalibur.source.impl.validity.NOPValidity;
import org.dspace.app.util.OpenSearch;
import org.dspace.app.xmlui.utils.ContextUtil;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
/**
*
* Generate an OpenSearch-compliant description document for DSpace,
* based on dspace.cfg configuration properties
*
* @author Richard Rodgers
* @author Nestor Oviedo
*/
public class DescriptionOpenSearchGenerator extends AbstractGenerator
implements CacheableProcessingComponent, Recyclable
{
/** optional search scope (community or collection instance) or null */
protected DSpaceObject scope = null;
/**
* Generate the unique caching key.
* It includes the class name to ensure uniqueness
*/
public Serializable getKey()
{
StringBuffer key = new StringBuffer("key:");
key.append(DescriptionOpenSearchGenerator.class.getName());
if (scope != null)
{
key.append(":"+scope.getHandle());
}
return HashUtil.hash(key.toString());
}
/**
* It's not expected that the OpenSearch's configuration to be changed very frecuently,
* so we assume this component is always valid (the cache should be cleared to update this component)
*/
public SourceValidity getValidity()
{
return NOPValidity.SHARED_INSTANCE;
}
/**
* Setup configuration for this request.
* Parsing of the scope parameter
*
* @throws ProcessingException if the scope param cannot be resolved to a valid Community or Collection
*/
public void setup(SourceResolver resolver, Map objectModel, String src,
Parameters par) throws ProcessingException, SAXException, IOException
{
super.setup(resolver, objectModel, src, par);
// Checks if scope is a valid community/collection handle
Context context = null;
try {
context = ContextUtil.obtainContext(objectModel);
} catch (SQLException e) {
throw new ProcessingException("Couldn't get DSpace Context object", e);
}
Request request = ObjectModelHelper.getRequest(objectModel);
String scopeParam = request.getParameter("scope");
try {
scope = OpenSearch.resolveScope(context, scopeParam);
}
catch (SQLException e)
{
throw new ProcessingException("Error resolving scope handle param "+scopeParam, e);
}
}
/**
* Generate the OpenSearch description document
*/
public void generate() throws IOException, SAXException, ProcessingException
{
// Create the description document
Document retDoc = OpenSearch.getDescriptionDoc( scope == null ? null : scope.getHandle() );
// Send the SAX events
DOMStreamer streamer = new DOMStreamer(contentHandler, lexicalHandler);
streamer.stream(retDoc);
}
/**
* Recycle
*/
public void recycle()
{
this.scope = null;
super.recycle();
}
}