/**
* 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.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.xml.dom.DOMStreamer;
import org.dspace.app.util.OpenSearch;
import org.dspace.app.xmlui.utils.ContextUtil;
import org.dspace.app.xmlui.utils.FeedUtils;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.SearchUtils;
import org.dspace.sort.SortOption;
import org.xml.sax.SAXException;
/**
* Generate an OpenSearch compliant search results document for DSpace, either scoped by a collection,
* a community or the whole repository.
*
* This class implements the generate() method in order to issue a search using the PostgreSQL indexes.
* Search params are parsed by AbstractOpenSearchGenerator class.
* I18N: Feed's are internationalized, meaning that they may contain references
* to messages contained in the global messages.xml file using cocoon's i18n
* schema. However the library used to build the feeds does not understand
* this schema to work around this limitation I created a little hack. It
* basically works like this, when text that needs to be localized is put into
* the feed it is always mangled such that a prefix is added to the messages's
* key. Thus if the key were "xmlui.feed.text" then the resulting text placed
* into the feed would be "I18N:xmlui.feed.text". After the library is finished
* and produced it's final result the output is traversed to find these
* occurrences and replace them with proper cocoon i18n elements.
*
* @author Richard Rodgers
* @author Nestor Oviedo
*/
public class DiscoveryOpenSearchGenerator extends AbstractOpenSearchGenerator
implements CacheableProcessingComponent, Recyclable
{
/** the search service to use */
private SearchService searchService = null;
/**
* Setup the Discovery search service. Other paramas are setup in superclass's methods
*/
public void setup(SourceResolver resolver, Map objectModel, String src,
Parameters par) throws ProcessingException, SAXException, IOException
{
super.setup(resolver, objectModel, src, par);
searchService = SearchUtils.getSearchService();
if(searchService == null)
throw new IllegalStateException("Couldn't get a search service instance");
}
/**
* Generate the search results document.
*/
public void generate() throws IOException, SAXException, ProcessingException
{
try
{
if (resultsDoc == null)
{
Context context = ContextUtil.obtainContext(objectModel);
DiscoverQuery queryArgs = new DiscoverQuery();
Request request = ObjectModelHelper.getRequest(objectModel);
// Sets the query
queryArgs.setQuery(query);
// start -1 because Solr indexing starts at 0 and OpenSearch
// indexing starts at 1.
queryArgs.setStart(start - 1);
queryArgs.setMaxResults(rpp);
// we want Items only
queryArgs.setDSpaceObjectFilter(Constants.ITEM);
// sort info
if(sort != null)
{
String sortField = this.searchService.toSortFieldIndex(sort.getMetadata(), sort.getType());
if(SortOption.ASCENDING.equals( sortOrder ))
queryArgs.setSortField(sortField, DiscoverQuery.SORT_ORDER.asc);
else
queryArgs.setSortField(sortField, DiscoverQuery.SORT_ORDER.desc);
}
DiscoverResult queryResults = null;
if(scope == null)
queryResults = SearchUtils.getSearchService().search(context, queryArgs);
else
queryResults = SearchUtils.getSearchService().search(context, scope, queryArgs);
// creates the results array and generates the OpenSearch result
DSpaceObject[] results = new DSpaceObject[queryResults.getDspaceObjects().size()];
queryResults.getDspaceObjects().toArray(results);
resultsDoc = OpenSearch.getResultsDoc(format, query, (int) queryResults.getTotalSearchResults(), start, rpp, scope, results, FeedUtils.i18nLabels);
FeedUtils.unmangleI18N(resultsDoc);
}
// Send the SAX events
DOMStreamer streamer = new DOMStreamer(contentHandler, lexicalHandler);
streamer.stream(resultsDoc);
}
catch (SQLException sqle)
{
throw new SAXException(sqle);
}
catch (SearchServiceException se)
{
throw new ProcessingException(se);
}
}
/**
* Recycle
*/
public void recycle()
{
this.searchService = null;
super.recycle();
}
}