/** * 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 org.apache.avalon.excalibur.pool.Recyclable; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.caching.CacheableProcessingComponent; 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.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.handle.HandleManager; import org.dspace.search.DSQuery; import org.dspace.search.QueryArgs; import org.dspace.search.QueryResults; 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 Discovery search service * (Solr based search) * 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 StandardOpenSearchGenerator extends AbstractOpenSearchGenerator implements CacheableProcessingComponent, Recyclable { /** * Generate the search results document. * Params have been parsed in superclass's setup() method */ public void generate() throws IOException, SAXException, ProcessingException { try { // create a new search only if there isn't a cached one if (resultsDoc == null) { Context context = ContextUtil.obtainContext(objectModel); QueryArgs qArgs = new QueryArgs(); qArgs.setQuery(query); qArgs.setStart(start); qArgs.setPageSize(rpp); if(sort != null) { qArgs.setSortOption(sort); qArgs.setSortOrder(sortOrder); } // Perform the search QueryResults qResults = null; if (scope == null) { qResults = DSQuery.doQuery(context, qArgs); } else if (scope.getType() == Constants.COLLECTION) { qResults = DSQuery.doQuery(context, qArgs, (Collection) scope); } else if (scope.getType() == Constants.COMMUNITY) { qResults = DSQuery.doQuery(context, qArgs, (Community) scope); } else { throw new IllegalStateException("Invalid container for search context (container type is "+scope.getClass().getName()+")"); } // now instantiate the results DSpaceObject[] results = new DSpaceObject[qResults.getHitHandles().size()]; for (int i = 0; i < qResults.getHitHandles().size(); i++) { String myHandle = qResults.getHitHandles().get(i); DSpaceObject dso = HandleManager.resolveToObject(context, myHandle); if (dso == null) { throw new SQLException("Query \"" + query + "\" returned unresolvable handle: " + myHandle); } results[i] = dso; } // generates the OpenSearch result resultsDoc = OpenSearch.getResultsDoc(format, query, qResults.getHitCount(), qResults.getStart(), qResults.getPageSize(), 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); } } }