blob: e585db0f73ae9673a4dae286660a3a250cc75a1d [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.generation;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.cocoon.Constants;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.search.LuceneCocoonSearcher;
import org.apache.cocoon.components.search.LuceneXMLIndexer;
import org.apache.cocoon.components.search.LuceneCocoonPager;
import org.apache.cocoon.components.search.LuceneCocoonHelper;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.search.Hits;
import org.apache.lucene.store.Directory;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Enumeration;
/**
* Generates an XML representation of a search result.
*
* <p>
* This generator generates xml content representening an XML search.
* The generated xml content contains the search result,
* the search query information, and navigation information about the
* search results.
* The query is sent to the generator, either via the 'queryString' request parameter
* or the 'query' SiteMap parameter. The sitemap overides the request.
* </p>
*
* <p>
* Search xml sample generated by this generator:
* </p>
* <pre><tt>
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
*
* &lt;search:results date=&quot;1008437081064&quot; query-string=&quot;cocoon&quot;
* start-index=&quot;0&quot; page-length=&quot;10&quot;
* xmlns:search=&quot;http://apache.org/cocoon/search/1.0&quot;
* xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;
* &lt;search:hits total-count=&quot;125&quot; count-of-pages=&quot;13&quot;&gt;
* &lt;search:hit rank=&quot;0&quot; score=&quot;1.0&quot;
* uri=&quot;http://localhost:8080/cocoon/documents/hosting.html&quot;&gt;
* &lt;search:field name="title"&gt;Document Title&lt;search:field/&gt;
* &lt;search:hit/&gt;
* ...
* &lt;/search:hits&gt;
*
* &lt;search:navigation total-count=&quot;125&quot; count-of-pages=&quot;13&quot;
* has-next=&quot;true&quot; has-previous=&quot;false&quot; next-index=&quot;10&quot; previous-index=&quot;0&quot;&gt;
* &lt;search:navigation-page start-index=&quot;0&quot;/&gt;
* &lt;search:navigation-page start-index=&quot;10&quot;/&gt;
* ...
* &lt;search:navigation-page start-index=&quot;120&quot;/&gt;
* &lt;/search:navigation&gt;
* &lt;/search:results&gt;
* </tt></pre>
*
* @author <a href="mailto:berni_huber@a1.net">Bernhard Huber</a>
* @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
* @author <a href="mailto:jeremy@apache.org">Jeremy Quinn</a>
* @author <a href="mailto:conal@nzetc.org">Conal Tuohy</a>
* @version CVS $Id: SearchGenerator.java,v 1.5 2004/03/05 13:01:59 bdelacretaz Exp $
*/
public class SearchGenerator extends ServiceableGenerator
implements Contextualizable, Initializable, Disposable
{
/**
* The XML namespace for the output document.
*/
protected final static String NAMESPACE = "http://apache.org/cocoon/search/1.0";
/**
* The XML namespace prefix for the output document.
*/
protected final static String PREFIX = "search";
/**
* The XML namespace for xlink
*/
protected final static String XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
/**
* Description of the Field
*/
protected final static String CDATA = "CDATA";
/**
* Name of root element of generated xml content, ie <code>results</code>.
*/
protected final static String RESULTS_ELEMENT = "results";
/**
* Qualified name of root element of generated xml content, ie <code>search:results</code>.
*/
protected final static String Q_RESULTS_ELEMENT = PREFIX + ":" + RESULTS_ELEMENT;
/**
* Attribute <code>date</code> of <code>results</code> element.
* It contains the date a long value, indicating when a search
* generated this xml content.
*/
protected final static String DATE_ATTRIBUTE = "date";
/**
* Attribute <code>query-string</code> of <code>results</code> element.
* Echos the <code>queryString</code> query parameter.
*/
protected final static String QUERY_STRING_ATTRIBUTE = "query-string";
/**
* Attribute <code>start-index</code> of <code>results</code> element.
* Echoes the <code>startIndex</code> query parameter.
*/
protected final static String START_INDEX_ATTRIBUTE = "start-index";
/**
* Attribute <code>page-length</code> of <code>results</code> element.
* Echoes the <code>pageLenth</code> query parameter.
*/
protected final static String PAGE_LENGTH_ATTRIBUTE = "page-length";
/**
* Attribute <code>name</code> of <code>hit</code> element.
*/
protected final static String NAME_ATTRIBUTE = "name";
/**
* Child element of generated xml content, ie <code>hits</code>.
* This element describes all hits.
*/
protected final static String HITS_ELEMENT = "hits";
/**
* QName of child element of generated xml content, ie <code>search:hits</code>.
* This element describes all hits.
*/
protected final static String Q_HITS_ELEMENT = PREFIX + ":" + HITS_ELEMENT;
/**
* Attribute <code>total-count</code> of <code>hits</code> element.
* The value describes total number of hits found by the search engine.
*/
protected final static String TOTAL_COUNT_ATTRIBUTE = "total-count";
/**
* Attribute <code>count-of-pages</code> of <code>hits</code> element.
* The value describes number of pages needed for all hits.
*/
protected final static String COUNT_OF_PAGES_ATTRIBUTE = "count-of-pages";
/**
* Child element of generated xml content, ie <code>hit</code>.
* This element describes a single hit.
*/
protected final static String HIT_ELEMENT = "hit";
/**
* QName of child element of generated xml content, ie <code>search:hit</code>.
* This element describes a single hit.
*/
protected final static String Q_HIT_ELEMENT = PREFIX + ":" + HIT_ELEMENT;
/**
* Attribute <code>rank</code> of <code>hit</code> element.
* The value describes the count index of this hits, ranging between 0, and
* total-count minus 1.
*/
protected final static String RANK_ATTRIBUTE = "rank";
/**
* Attribute <code>score</code> of <code>hit</code> element.
* The value describes the score of this hits, ranging between 0, and 1.0.
*/
protected final static String SCORE_ATTRIBUTE = "score";
/**
* Attribute <code>uri</code> of <code>hit</code> element.
* The value describes the uri of a document matching the search query.
*/
protected final static String URI_ATTRIBUTE = "uri";
/**
* Child element <code>field</code> of the <code>hit</code> element.
* This element contains value of the stored field of a hit.
*
* @since 2.0.4
*/
protected final static String FIELD_ELEMENT = "field";
/**
* QName of child element <code>search:field</code> of the <code>hit</code> element.
*/
protected final static String Q_FIELD_ELEMENT = PREFIX + ":" + FIELD_ELEMENT;
/**
* Child element of generated xml content, ie <code>navigation</code>.
* This element describes some hints for easier navigation.
*/
protected final static String NAVIGATION_ELEMENT = "navigation";
/**
* QName of child element of generated xml content, ie <code>search:navigation</code>.
*/
protected final static String Q_NAVIGATION_ELEMENT = PREFIX + ":" + NAVIGATION_ELEMENT;
/**
* Child element of generated xml content, ie <code>navigation-page</code>.
* This element describes the start-index of page containing hits.
*/
protected final static String NAVIGATION_PAGE_ELEMENT = "navigation-page";
/**
* QName of child element of generated xml content, ie <code>search:navigation-page</code>.
* This element describes the start-index of page containing hits.
*/
protected final static String Q_NAVIGATION_PAGE_ELEMENT = PREFIX + ":" + NAVIGATION_PAGE_ELEMENT;
/**
* Attribute <code>has-next</code> of <code>navigation-page</code> element.
* The value is true if a next navigation control should be presented.
*/
protected final static String HAS_NEXT_ATTRIBUTE = "has-next";
/**
* Attribute <code>has-next</code> of <code>navigation-page</code> element.
* The value is true if a previous navigation control should be presented.
*/
protected final static String HAS_PREVIOUS_ATTRIBUTE = "has-previous";
/**
* Attribute <code>next-index</code> of <code>navigation-page</code> element.
* The value describes the start-index of the next-to-be-presented page.
*/
protected final static String NEXT_INDEX_ATTRIBUTE = "next-index";
/**
* Attribute <code>previous-index</code> of <code>navigation-page</code> element.
* The value describes the start-index of the previous-to-be-presented page.
*/
protected final static String PREVIOUS_INDEX_ATTRIBUTE = "previous-index";
/**
* Setup parameter name of index directory, ie <code>index</code>.
*/
protected final static String INDEX_PARAM = "index";
/**
* Default value of setup parameter <code>index</code>, ie <code>index</code>.
*/
protected final static String INDEX_PARAM_DEFAULT = "index";
/**
* Setup the actual query from generator parameter,
* ie <code>query</code>.
*/
protected final static String QUERY_PARAM = "query";
/**
* Setup parameter name specifying the name of query-string query parameter,
* ie <code>query-string</code>.
*/
protected final static String QUERY_STRING_PARAM = "query-string";
/**
* Default value of setup parameter <code>query-string</code>, ie <code>queryString</code>.
*/
protected final static String QUERY_STRING_PARAM_DEFAULT = "queryString";
/**
* Setup parameter name specifying the name of start-index query parameter,
* ie <code>start-index</code>.
*/
protected final static String START_INDEX_PARAM = "start-index";
/**
* Default value of setup parameter <code>start-index</code>, ie <code>startIndex</code>.
*/
protected final static String START_INDEX_PARAM_DEFAULT = "startIndex";
/**
* Setup parameter name specifying the name of start-next-index query parameter,
* ie <code>start-next-index</code>.
*/
protected final static String START_INDEX_NEXT_PARAM = "start-next-index";
/**
* Default value of setup parameter <code>start-next-index</code>, ie <code>startNextIndex</code>.
*/
protected final static String START_INDEX_NEXT_PARAM_DEFAULT = "startNextIndex";
/**
* Setup parameter name specifying the name of start-previous-index query parameter,
* ie <code>start-previous-index</code>.
*/
protected final static String START_INDEX_PREVIOUS_PARAM = "start-previous-index";
/**
* Default value of setup parameter <code>start-previous-index</code>, ie <code>startPreviousIndex</code>.
*/
protected final static String START_INDEX_PREVIOUS_PARAM_DEFAULT = "startPreviousIndex";
/**
*Description of the Field
*
* @since
*/
protected final static int START_INDEX_DEFAULT = 0;
/**
* Setup parameter name specifying the name of page-length query parameter,
* ie <code>page-length</code>.
*/
protected final static String PAGE_LENGTH_PARAM = "page-length";
/**
*Description of the Field
*
* @since
*/
protected final static String PAGE_LENGTH_PARAM_DEFAULT = "pageLength";
/**
*Description of the Field
*
* @since
*/
protected final static int PAGE_LENGTH_DEFAULT = 10;
/**
* Default home directory of index directories.
* <p>
* Releative index directories specified in the setup of this generator are resolved
* relative to this directory.
* </p>
* <p>
* By default this directory is set to the <code>WORKING_DIR</code> of Cocoon.
* </p>
*/
private File workDir = null;
/**
* The avalon component to use for searching.
*/
private LuceneCocoonSearcher lcs;
/**
* Absolute filesystem directory of lucene index directory
*/
private File index = null;
/**
* Query-string to search for
*/
private String queryString = "";
/**
* Attributes used when generating xml content.
*/
private final AttributesImpl atts = new AttributesImpl();
/**
* startIndex of query parameter
*/
private Integer startIndex = null;
/**
* pageLength of query parameter
*/
private Integer pageLength = null;
// TODO: parameterize()
/**
* Set the current <code>ServiceManager</code> instance used by this
* <code>Serviceable</code>.
*/
public void service(ServiceManager manager) throws ServiceException {
super.service(manager);
// lcs = (LuceneCocoonSearcher) this.manager.lookup(LuceneCocoonSearcher.ROLE);
}
/**
* setup all members of this generator.
*
* @since
*/
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
throws ProcessingException, SAXException, IOException {
super.setup(resolver, objectModel, src, par);
String param_name;
Request request = ObjectModelHelper.getRequest(objectModel);
// get the analyzer
// Analyzer analyzer = LuceneCocoonHelper.getAnalyzer("org.apache.lucene.analysis.standard.StandardAnalyzer");
// lcs.setAnalyzer(analyzer);
String index_file_name = par.getParameter(INDEX_PARAM, INDEX_PARAM_DEFAULT);
if (request.getParameter(INDEX_PARAM) != null) {
index_file_name = request.getParameter(INDEX_PARAM);
}
// now set the index
index = new File(index_file_name);
if (!index.isAbsolute()) {
index = new File(workDir, index.toString());
}
// try getting the queryString from the generator sitemap params
queryString = par.getParameter(QUERY_PARAM, "");
// try getting the queryString from the request params
if (queryString.equals("")) {
param_name = par.getParameter(QUERY_STRING_PARAM, QUERY_STRING_PARAM_DEFAULT);
if (request.getParameter(param_name) != null) {
queryString = request.getParameter(param_name);
}
}
// always try lookup the start index from the request params
// get startIndex
startIndex = null;
param_name = par.getParameter(START_INDEX_NEXT_PARAM, START_INDEX_NEXT_PARAM_DEFAULT);
if (request.getParameter(param_name) != null) {
startIndex = createInteger(request.getParameter(param_name));
}
if (startIndex == null) {
param_name = par.getParameter(START_INDEX_PREVIOUS_PARAM, START_INDEX_PREVIOUS_PARAM_DEFAULT);
if (request.getParameter(param_name) != null) {
startIndex = createInteger(request.getParameter(param_name));
}
}
if (startIndex == null) {
param_name = par.getParameter(START_INDEX_PARAM, START_INDEX_PARAM_DEFAULT);
if (request.getParameter(param_name) != null) {
startIndex = createInteger(request.getParameter(param_name));
}
}
// get pageLength
param_name = par.getParameter(PAGE_LENGTH_PARAM, PAGE_LENGTH_PARAM_DEFAULT);
if (request.getParameter(param_name) != null) {
pageLength = createInteger(request.getParameter(param_name));
}
}
/**
* Contextualize this class.
*
* <p>
* Especially retrieve the work directory.
* If the index directory is specified relativly, the working directory is
* used as home directory of the index directory.
* </p>
*
* @param context Context to use
* @exception ContextException If contextualizing fails.
* @since
*/
public void contextualize(Context context) throws ContextException {
// retrieve the working directory, assuming that the index may reside there
workDir = (File) context.get(Constants.CONTEXT_WORK_DIR);
}
public void initialize() throws IOException {
// get the directory where the index resides
// Directory directory = LuceneCocoonHelper.getDirectory(new File(workDir, "index"), false);
// lcs.setDirectory(directory);
}
/**
* Generate xml content describing search results.
* Entry point of the ComposerGenerator.
* The xml content is generated from the hits object.
*
*
* @exception IOException when there is a problem reading the from file system.
* @since
* @throws SAXException when there is a problem creating the output SAX events.
* @throws ProcessingException when there is a problem obtaining the hits
*/
public void generate() throws IOException, SAXException, ProcessingException {
// set default parameter value, in case of no values are set yet.
if (startIndex == null) {
startIndex = new Integer(START_INDEX_DEFAULT);
}
if (pageLength == null) {
pageLength = new Integer(PAGE_LENGTH_DEFAULT);
}
// Start the document and set the namespace.
this.contentHandler.startDocument();
this.contentHandler.startPrefixMapping(PREFIX, NAMESPACE);
this.contentHandler.startPrefixMapping("xlink", XLINK_NAMESPACE);
generateResults();
// End the document.
this.contentHandler.endPrefixMapping("xlink");
this.contentHandler.endPrefixMapping(PREFIX);
this.contentHandler.endDocument();
}
/**
* Create an Integer.
* <p>
* Create an Integer from String s, if conversion fails return null.
* </p>
*
* @param s Converting s to an Integer
* @return Integer converted value originating from s, or null
* @since
*/
private Integer createInteger(String s) {
Integer i = null;
try {
i = new Integer(s);
} catch (NumberFormatException nfe) {
// ignore it, write only warning
if (getLogger().isWarnEnabled()) {
getLogger().warn("Cannot convert " + s + " to Integer", nfe);
}
}
return i;
}
/**
* Build and generate the search results.
* <p>
* First build the hits, next generate xml content from the hits,
* taking page index, and length into account.
* </p>
*
* @since
* @throws SAXException when there is a problem creating the output SAX events.
* @throws ProcessingException when there is a problem obtaining the hits
*/
private void generateResults() throws SAXException, ProcessingException {
// Make the hits
LuceneCocoonPager pager = buildHits();
// The current date and time.
long time = System.currentTimeMillis();
atts.clear();
atts.addAttribute("", DATE_ATTRIBUTE, DATE_ATTRIBUTE, CDATA, String.valueOf(time));
if (queryString != null && queryString.length() > 0)
atts.addAttribute("", QUERY_STRING_ATTRIBUTE, QUERY_STRING_ATTRIBUTE, CDATA, String.valueOf(queryString));
atts.addAttribute("", START_INDEX_ATTRIBUTE, START_INDEX_ATTRIBUTE, CDATA, String.valueOf(startIndex));
atts.addAttribute("", PAGE_LENGTH_ATTRIBUTE, PAGE_LENGTH_ATTRIBUTE, CDATA, String.valueOf(pageLength));
contentHandler.startElement(NAMESPACE, RESULTS_ELEMENT, Q_RESULTS_ELEMENT, atts);
// build xml from the hits
generateHits(pager);
generateNavigation(pager);
// End root element.
contentHandler.endElement(NAMESPACE, RESULTS_ELEMENT, Q_RESULTS_ELEMENT);
}
/**
* Generate the xml content of all hits
*
* @param pager the LuceneContentPager with the search results
* @since
* @throws SAXException when there is a problem creating the output SAX events.
*/
private void generateHits(LuceneCocoonPager pager) throws SAXException {
if (pager != null && pager.hasNext()) {
atts.clear();
atts.addAttribute("", TOTAL_COUNT_ATTRIBUTE, TOTAL_COUNT_ATTRIBUTE,
CDATA, String.valueOf(pager.getCountOfHits()));
atts.addAttribute("", COUNT_OF_PAGES_ATTRIBUTE, COUNT_OF_PAGES_ATTRIBUTE,
CDATA, String.valueOf(pager.getCountOfPages()));
contentHandler.startElement(NAMESPACE, HITS_ELEMENT, Q_HITS_ELEMENT, atts);
generateHit(pager);
contentHandler.endElement(NAMESPACE, HITS_ELEMENT, Q_HITS_ELEMENT);
}
}
/**
* Generate the xml content for each hit.
*
* @param pager the LuceneCocoonPager with the search results.
* @since
* @throws SAXException when there is a problem creating the output SAX events.
*/
private void generateHit(LuceneCocoonPager pager) throws SAXException {
// get the off set to start from
int counter = pager.getStartIndex();
// get an list of hits which should be placed onto a single page
List l = (List) pager.next();
Iterator i = l.iterator();
for (; i.hasNext(); counter++) {
LuceneCocoonPager.HitWrapper hw = (LuceneCocoonPager.HitWrapper) i.next();
Document doc = hw.getDocument();
float score = hw.getScore();
String uri = doc.get(LuceneXMLIndexer.URL_FIELD);
atts.clear();
atts.addAttribute("", RANK_ATTRIBUTE, RANK_ATTRIBUTE, CDATA,
String.valueOf(counter));
atts.addAttribute("", SCORE_ATTRIBUTE, SCORE_ATTRIBUTE, CDATA,
String.valueOf(score));
atts.addAttribute("", URI_ATTRIBUTE, URI_ATTRIBUTE, CDATA,
String.valueOf(uri));
contentHandler.startElement(NAMESPACE, HIT_ELEMENT, Q_HIT_ELEMENT, atts);
// fix me, add here a summary of this hit
for (Enumeration e = doc.fields(); e.hasMoreElements(); ) {
Field field = (Field)e.nextElement();
if (field.isStored()) {
if (LuceneXMLIndexer.URL_FIELD.equals(field.name()))
continue;
atts.clear();
atts.addAttribute("", NAME_ATTRIBUTE, NAME_ATTRIBUTE, CDATA, field.name());
contentHandler.startElement(NAMESPACE, FIELD_ELEMENT, Q_FIELD_ELEMENT, atts);
String value = field.stringValue();
contentHandler.characters(value.toCharArray(), 0, value.length());
contentHandler.endElement(NAMESPACE, FIELD_ELEMENT, Q_FIELD_ELEMENT);
}
}
contentHandler.endElement(NAMESPACE, HIT_ELEMENT, Q_HIT_ELEMENT);
}
}
/**
* Generate the navigation element.
*
* @param pager Description of Parameter
* @exception SAXException Description of Exception
* @since
*/
private void generateNavigation(LuceneCocoonPager pager) throws SAXException {
if (pager != null) {
// generate navigation element
atts.clear();
atts.addAttribute("", TOTAL_COUNT_ATTRIBUTE, TOTAL_COUNT_ATTRIBUTE,
CDATA, String.valueOf(pager.getCountOfHits()));
atts.addAttribute("", COUNT_OF_PAGES_ATTRIBUTE, COUNT_OF_PAGES_ATTRIBUTE,
CDATA, String.valueOf(pager.getCountOfPages()));
atts.addAttribute("", HAS_NEXT_ATTRIBUTE, HAS_NEXT_ATTRIBUTE,
CDATA, String.valueOf(pager.hasNext()));
atts.addAttribute("", HAS_PREVIOUS_ATTRIBUTE, HAS_PREVIOUS_ATTRIBUTE,
CDATA, String.valueOf(pager.hasPrevious()));
atts.addAttribute("", NEXT_INDEX_ATTRIBUTE, NEXT_INDEX_ATTRIBUTE,
CDATA, String.valueOf(pager.nextIndex()));
atts.addAttribute("", PREVIOUS_INDEX_ATTRIBUTE, PREVIOUS_INDEX_ATTRIBUTE,
CDATA, String.valueOf(pager.previousIndex()));
contentHandler.startElement(NAMESPACE, NAVIGATION_ELEMENT, Q_NAVIGATION_ELEMENT, atts);
int count_of_pages = pager.getCountOfPages();
for (int i = 0, page_start_index = 0;
i < count_of_pages;
i++, page_start_index += pageLength.intValue()) {
atts.clear();
atts.addAttribute("", START_INDEX_ATTRIBUTE, START_INDEX_ATTRIBUTE,
CDATA, String.valueOf(page_start_index));
contentHandler.startElement(NAMESPACE, NAVIGATION_PAGE_ELEMENT, Q_NAVIGATION_PAGE_ELEMENT, atts);
contentHandler.endElement(NAMESPACE, NAVIGATION_PAGE_ELEMENT, Q_NAVIGATION_PAGE_ELEMENT);
}
// navigation is EMPTY element
contentHandler.endElement(NAMESPACE, NAVIGATION_ELEMENT, Q_NAVIGATION_ELEMENT);
}
}
/**
* Build hits from a query input, and setup paging object.
*
* @since
* @throws ProcessingException if an error occurs
*/
private LuceneCocoonPager buildHits() throws ProcessingException {
if (queryString != null && queryString.length() != 0) {
Hits hits = null;
// TODO (VG): Move parts into compose/initialize/recycle
try {
lcs = (LuceneCocoonSearcher) this.manager.lookup(LuceneCocoonSearcher.ROLE);
Analyzer analyzer = LuceneCocoonHelper.getAnalyzer("org.apache.lucene.analysis.standard.StandardAnalyzer");
lcs.setAnalyzer(analyzer);
// get the directory where the index resides
Directory directory = LuceneCocoonHelper.getDirectory(index, false);
lcs.setDirectory(directory);
hits = lcs.search(queryString, LuceneXMLIndexer.BODY_FIELD);
} catch (IOException ioe) {
throw new ProcessingException("IOException in search", ioe);
} catch (ServiceException ce) {
throw new ProcessingException("ComponentException in search", ce);
} finally {
if (lcs != null) {
this.manager.release(lcs);
lcs = null;
}
}
// wrap the hits by an pager help object for accessing only a range of hits
LuceneCocoonPager pager = new LuceneCocoonPager(hits);
int start_index = START_INDEX_DEFAULT;
if (this.startIndex != null) {
start_index = this.startIndex.intValue();
if (start_index <= 0) {
start_index = 0;
}
pager.setStartIndex(start_index);
}
int page_length = PAGE_LENGTH_DEFAULT;
if (this.pageLength != null) {
page_length = this.pageLength.intValue();
if (page_length <= 0) {
page_length = hits.length();
}
pager.setCountOfHitsPerPage(page_length);
}
return pager;
}
return null;
}
/**
* Recycle the generator
*/
public void recycle() {
super.recycle();
this.queryString = null;
this.startIndex = null;
this.pageLength = null;
this.index = null;
}
public void dispose() {
// if (lcs != null) {
// this.manager.release(lcs);
// lcs = null;
// }
super.dispose();
}
}