KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > generation > SearchGenerator


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.generation;
17
18 import org.apache.avalon.framework.activity.Disposable;
19 import org.apache.avalon.framework.context.Context;
20 import org.apache.avalon.framework.context.ContextException;
21 import org.apache.avalon.framework.context.Contextualizable;
22 import org.apache.avalon.framework.parameters.Parameters;
23 import org.apache.avalon.framework.service.ServiceException;
24 import org.apache.avalon.framework.service.ServiceManager;
25
26 import org.apache.cocoon.Constants;
27 import org.apache.cocoon.ProcessingException;
28 import org.apache.cocoon.components.search.LuceneCocoonHelper;
29 import org.apache.cocoon.components.search.LuceneCocoonPager;
30 import org.apache.cocoon.components.search.LuceneCocoonSearcher;
31 import org.apache.cocoon.components.search.LuceneXMLIndexer;
32 import org.apache.cocoon.environment.ObjectModelHelper;
33 import org.apache.cocoon.environment.Request;
34 import org.apache.cocoon.environment.SourceResolver;
35
36 import org.apache.lucene.analysis.Analyzer;
37 import org.apache.lucene.document.Document;
38 import org.apache.lucene.document.Field;
39 import org.apache.lucene.search.Hits;
40 import org.apache.lucene.store.Directory;
41
42 import org.xml.sax.SAXException JavaDoc;
43 import org.xml.sax.helpers.AttributesImpl JavaDoc;
44
45 import java.io.File JavaDoc;
46 import java.io.IOException JavaDoc;
47 import java.util.Enumeration JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.List JavaDoc;
50 import java.util.Map JavaDoc;
51
52 /**
53  * Generates an XML representation of a search result.
54  *
55  * <p>
56  * This generator generates xml content representening an XML search.
57  * The generated xml content contains the search result,
58  * the search query information, and navigation information about the
59  * search results.
60  * The query is sent to the generator, either via the 'queryString' request parameter
61  * or the 'query' SiteMap parameter. The sitemap overides the request.
62  * </p>
63  *
64  * <p>
65  * Search xml sample generated by this generator:
66  * </p>
67  * <pre><tt>
68  * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
69  *
70  * &lt;search:results date=&quot;1008437081064&quot; query-string=&quot;cocoon&quot;
71  * start-index=&quot;0&quot; page-length=&quot;10&quot;
72  * xmlns:search=&quot;http://apache.org/cocoon/search/1.0&quot;
73  * xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;
74  * &lt;search:hits total-count=&quot;125&quot; count-of-pages=&quot;13&quot;&gt;
75  * &lt;search:hit rank=&quot;0&quot; score=&quot;1.0&quot;
76  * uri=&quot;http://localhost:8080/cocoon/documents/hosting.html&quot;&gt;
77  * &lt;search:field name="title"&gt;Document Title&lt;search:field/&gt;
78  * &lt;search:hit/&gt;
79  * ...
80  * &lt;/search:hits&gt;
81  *
82  * &lt;search:navigation total-count=&quot;125&quot; count-of-pages=&quot;13&quot;
83  * has-next=&quot;true&quot; has-previous=&quot;false&quot; next-index=&quot;10&quot; previous-index=&quot;0&quot;&gt;
84  * &lt;search:navigation-page start-index=&quot;0&quot;/&gt;
85  * &lt;search:navigation-page start-index=&quot;10&quot;/&gt;
86  * ...
87  * &lt;search:navigation-page start-index=&quot;120&quot;/&gt;
88  * &lt;/search:navigation&gt;
89  * &lt;/search:results&gt;
90  * </tt></pre>
91  *
92  * @author <a HREF="mailto:berni_huber@a1.net">Bernhard Huber</a>
93  * @author <a HREF="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
94  * @author <a HREF="mailto:jeremy@apache.org">Jeremy Quinn</a>
95  * @author <a HREF="mailto:conal@nzetc.org">Conal Tuohy</a>
96  * @version CVS $Id: SearchGenerator.java 76089 2004-11-17 01:57:02Z antonio $
97  */

98 public class SearchGenerator extends ServiceableGenerator
99     implements Contextualizable, Disposable
100 {
101
102     /**
103      * The XML namespace for the output document.
104      */

105     protected final static String JavaDoc NAMESPACE = "http://apache.org/cocoon/search/1.0";
106
107     /**
108      * The XML namespace prefix for the output document.
109      */

110     protected final static String JavaDoc PREFIX = "search";
111
112     /**
113      * The XML namespace for xlink
114      */

115     protected final static String JavaDoc XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
116
117     /**
118      * Description of the Field
119      */

120     protected final static String JavaDoc CDATA = "CDATA";
121
122     /**
123      * Name of root element of generated xml content, ie <code>results</code>.
124      */

125     protected final static String JavaDoc RESULTS_ELEMENT = "results";
126
127     /**
128      * Qualified name of root element of generated xml content, ie <code>search:results</code>.
129      */

130     protected final static String JavaDoc Q_RESULTS_ELEMENT = PREFIX + ":" + RESULTS_ELEMENT;
131
132
133     /**
134      * Attribute <code>date</code> of <code>results</code> element.
135      * It contains the date a long value, indicating when a search
136      * generated this xml content.
137      */

138     protected final static String JavaDoc DATE_ATTRIBUTE = "date";
139
140     /**
141      * Attribute <code>query-string</code> of <code>results</code> element.
142      * Echos the <code>queryString</code> query parameter.
143      */

144     protected final static String JavaDoc QUERY_STRING_ATTRIBUTE = "query-string";
145
146     /**
147      * Attribute <code>start-index</code> of <code>results</code> element.
148      * Echoes the <code>startIndex</code> query parameter.
149      */

150     protected final static String JavaDoc START_INDEX_ATTRIBUTE = "start-index";
151
152     /**
153      * Attribute <code>page-length</code> of <code>results</code> element.
154      * Echoes the <code>pageLenth</code> query parameter.
155      */

156     protected final static String JavaDoc PAGE_LENGTH_ATTRIBUTE = "page-length";
157
158     /**
159      * Attribute <code>name</code> of <code>hit</code> element.
160      */

161     protected final static String JavaDoc NAME_ATTRIBUTE = "name";
162
163     /**
164      * Child element of generated xml content, ie <code>hits</code>.
165      * This element describes all hits.
166      */

167     protected final static String JavaDoc HITS_ELEMENT = "hits";
168
169     /**
170      * QName of child element of generated xml content, ie <code>search:hits</code>.
171      * This element describes all hits.
172      */

173     protected final static String JavaDoc Q_HITS_ELEMENT = PREFIX + ":" + HITS_ELEMENT;
174
175     /**
176      * Attribute <code>total-count</code> of <code>hits</code> element.
177      * The value describes total number of hits found by the search engine.
178      */

179     protected final static String JavaDoc TOTAL_COUNT_ATTRIBUTE = "total-count";
180
181     /**
182      * Attribute <code>count-of-pages</code> of <code>hits</code> element.
183      * The value describes number of pages needed for all hits.
184      */

185     protected final static String JavaDoc COUNT_OF_PAGES_ATTRIBUTE = "count-of-pages";
186
187     /**
188      * Child element of generated xml content, ie <code>hit</code>.
189      * This element describes a single hit.
190      */

191     protected final static String JavaDoc HIT_ELEMENT = "hit";
192
193     /**
194      * QName of child element of generated xml content, ie <code>search:hit</code>.
195      * This element describes a single hit.
196      */

197     protected final static String JavaDoc Q_HIT_ELEMENT = PREFIX + ":" + HIT_ELEMENT;
198
199     /**
200      * Attribute <code>rank</code> of <code>hit</code> element.
201      * The value describes the count index of this hits, ranging between 0, and
202      * total-count minus 1.
203      */

204     protected final static String JavaDoc RANK_ATTRIBUTE = "rank";
205
206     /**
207      * Attribute <code>score</code> of <code>hit</code> element.
208      * The value describes the score of this hits, ranging between 0, and 1.0.
209      */

210     protected final static String JavaDoc SCORE_ATTRIBUTE = "score";
211
212     /**
213      * Attribute <code>uri</code> of <code>hit</code> element.
214      * The value describes the uri of a document matching the search query.
215      */

216     protected final static String JavaDoc URI_ATTRIBUTE = "uri";
217
218     /**
219      * Child element <code>field</code> of the <code>hit</code> element.
220      * This element contains value of the stored field of a hit.
221      *
222      * @since 2.0.4
223      */

224     protected final static String JavaDoc FIELD_ELEMENT = "field";
225
226     /**
227      * QName of child element <code>search:field</code> of the <code>hit</code> element.
228      */

229     protected final static String JavaDoc Q_FIELD_ELEMENT = PREFIX + ":" + FIELD_ELEMENT;
230
231     /**
232      * Child element of generated xml content, ie <code>navigation</code>.
233      * This element describes some hints for easier navigation.
234      */

235     protected final static String JavaDoc NAVIGATION_ELEMENT = "navigation";
236
237     /**
238      * QName of child element of generated xml content, ie <code>search:navigation</code>.
239      */

240     protected final static String JavaDoc Q_NAVIGATION_ELEMENT = PREFIX + ":" + NAVIGATION_ELEMENT;
241
242     /**
243      * Child element of generated xml content, ie <code>navigation-page</code>.
244      * This element describes the start-index of page containing hits.
245      */

246     protected final static String JavaDoc NAVIGATION_PAGE_ELEMENT = "navigation-page";
247
248     /**
249      * QName of child element of generated xml content, ie <code>search:navigation-page</code>.
250      * This element describes the start-index of page containing hits.
251      */

252     protected final static String JavaDoc Q_NAVIGATION_PAGE_ELEMENT = PREFIX + ":" + NAVIGATION_PAGE_ELEMENT;
253
254     /**
255      * Attribute <code>has-next</code> of <code>navigation-page</code> element.
256      * The value is true if a next navigation control should be presented.
257      */

258     protected final static String JavaDoc HAS_NEXT_ATTRIBUTE = "has-next";
259
260     /**
261      * Attribute <code>has-next</code> of <code>navigation-page</code> element.
262      * The value is true if a previous navigation control should be presented.
263      */

264     protected final static String JavaDoc HAS_PREVIOUS_ATTRIBUTE = "has-previous";
265
266     /**
267      * Attribute <code>next-index</code> of <code>navigation-page</code> element.
268      * The value describes the start-index of the next-to-be-presented page.
269      */

270     protected final static String JavaDoc NEXT_INDEX_ATTRIBUTE = "next-index";
271
272     /**
273      * Attribute <code>previous-index</code> of <code>navigation-page</code> element.
274      * The value describes the start-index of the previous-to-be-presented page.
275      */

276     protected final static String JavaDoc PREVIOUS_INDEX_ATTRIBUTE = "previous-index";
277
278     /**
279      * Setup parameter name of index directory, ie <code>index</code>.
280      */

281     protected final static String JavaDoc INDEX_PARAM = "index";
282
283     /**
284      * Default value of setup parameter <code>index</code>, ie <code>index</code>.
285      */

286     protected final static String JavaDoc INDEX_PARAM_DEFAULT = "index";
287
288     /**
289      * Setup the actual query from generator parameter,
290      * ie <code>query</code>.
291      */

292     protected final static String JavaDoc QUERY_PARAM = "query";
293
294     /**
295      * Setup parameter name specifying the name of query-string query parameter,
296      * ie <code>query-string</code>.
297      */

298     protected final static String JavaDoc QUERY_STRING_PARAM = "query-string";
299
300     /**
301      * Default value of setup parameter <code>query-string</code>, ie <code>queryString</code>.
302      */

303     protected final static String JavaDoc QUERY_STRING_PARAM_DEFAULT = "queryString";
304
305     /**
306      * Setup parameter name specifying the name of start-index query parameter,
307      * ie <code>start-index</code>.
308      */

309     protected final static String JavaDoc START_INDEX_PARAM = "start-index";
310
311     /**
312      * Default value of setup parameter <code>start-index</code>, ie <code>startIndex</code>.
313      */

314     protected final static String JavaDoc START_INDEX_PARAM_DEFAULT = "startIndex";
315
316     /**
317      * Setup parameter name specifying the name of start-next-index query parameter,
318      * ie <code>start-next-index</code>.
319      */

320     protected final static String JavaDoc START_INDEX_NEXT_PARAM = "start-next-index";
321
322     /**
323      * Default value of setup parameter <code>start-next-index</code>, ie <code>startNextIndex</code>.
324      */

325     protected final static String JavaDoc START_INDEX_NEXT_PARAM_DEFAULT = "startNextIndex";
326
327     /**
328      * Setup parameter name specifying the name of start-previous-index query parameter,
329      * ie <code>start-previous-index</code>.
330      */

331     protected final static String JavaDoc START_INDEX_PREVIOUS_PARAM = "start-previous-index";
332
333     /**
334      * Default value of setup parameter <code>start-previous-index</code>, ie <code>startPreviousIndex</code>.
335      */

336     protected final static String JavaDoc START_INDEX_PREVIOUS_PARAM_DEFAULT = "startPreviousIndex";
337
338     /**
339      *Description of the Field
340      *
341      * @since
342      */

343     protected final static int START_INDEX_DEFAULT = 0;
344
345     /**
346      * Setup parameter name specifying the name of page-length query parameter,
347      * ie <code>page-length</code>.
348      */

349     protected final static String JavaDoc PAGE_LENGTH_PARAM = "page-length";
350
351     /**
352      *Description of the Field
353      *
354      * @since
355      */

356     protected final static String JavaDoc PAGE_LENGTH_PARAM_DEFAULT = "pageLength";
357
358     /**
359      *Description of the Field
360      *
361      * @since
362      */

363     protected final static int PAGE_LENGTH_DEFAULT = 10;
364
365
366
367     /**
368      * Default home directory of index directories.
369      * <p>
370      * Releative index directories specified in the setup of this generator are resolved
371      * relative to this directory.
372      * </p>
373      * <p>
374      * By default this directory is set to the <code>WORKING_DIR</code> of Cocoon.
375      * </p>
376      */

377     private File JavaDoc workDir = null;
378
379     /**
380      * The avalon component to use for searching.
381      */

382     private LuceneCocoonSearcher lcs;
383
384     /**
385      * Absolute filesystem directory of lucene index directory
386      */

387     private File JavaDoc index = null;
388
389     /**
390      * Query-string to search for
391      */

392     private String JavaDoc queryString = "";
393
394     /**
395      * Attributes used when generating xml content.
396      */

397     private final AttributesImpl JavaDoc atts = new AttributesImpl JavaDoc();
398
399     /**
400      * startIndex of query parameter
401      */

402     private Integer JavaDoc startIndex = null;
403
404     /**
405      * pageLength of query parameter
406      */

407     private Integer JavaDoc pageLength = null;
408
409
410     // TODO: parameterize()
411

412     /**
413      * Set the current <code>ServiceManager</code> instance used by this
414      * <code>Serviceable</code>.
415      */

416     public void service(ServiceManager manager) throws ServiceException {
417         super.service(manager);
418     }
419
420     /**
421      * setup all members of this generator.
422      *
423      * @since
424      */

425     public void setup(SourceResolver resolver, Map JavaDoc objectModel, String JavaDoc src, Parameters par)
426              throws ProcessingException, SAXException JavaDoc, IOException JavaDoc {
427         super.setup(resolver, objectModel, src, par);
428
429         try {
430             lcs = (LuceneCocoonSearcher) this.manager.lookup(LuceneCocoonSearcher.ROLE);
431         } catch (ServiceException e) {
432             throw new ProcessingException("Unable to lookup " + LuceneCocoonSearcher.ROLE, e);
433         }
434
435         String JavaDoc param_name;
436         Request request = ObjectModelHelper.getRequest(objectModel);
437
438         String JavaDoc index_file_name = par.getParameter(INDEX_PARAM, INDEX_PARAM_DEFAULT);
439         if (request.getParameter(INDEX_PARAM) != null) {
440             index_file_name = request.getParameter(INDEX_PARAM);
441         }
442
443         // now set the index
444
index = new File JavaDoc(index_file_name);
445         if (!index.isAbsolute()) {
446             index = new File JavaDoc(workDir, index.toString());
447         }
448
449         // try getting the queryString from the generator sitemap params
450

451         queryString = par.getParameter(QUERY_PARAM, "");
452
453         // try getting the queryString from the request params
454
if (queryString.equals("")) {
455             param_name = par.getParameter(QUERY_STRING_PARAM, QUERY_STRING_PARAM_DEFAULT);
456             if (request.getParameter(param_name) != null) {
457                 queryString = request.getParameter(param_name);
458             }
459         }
460         // always try lookup the start index from the request params
461
// get startIndex
462
startIndex = null;
463         param_name = par.getParameter(START_INDEX_NEXT_PARAM, START_INDEX_NEXT_PARAM_DEFAULT);
464         if (request.getParameter(param_name) != null) {
465             startIndex = createInteger(request.getParameter(param_name));
466         }
467
468         if (startIndex == null) {
469             param_name = par.getParameter(START_INDEX_PREVIOUS_PARAM, START_INDEX_PREVIOUS_PARAM_DEFAULT);
470             if (request.getParameter(param_name) != null) {
471                 startIndex = createInteger(request.getParameter(param_name));
472             }
473         }
474         if (startIndex == null) {
475             param_name = par.getParameter(START_INDEX_PARAM, START_INDEX_PARAM_DEFAULT);
476             if (request.getParameter(param_name) != null) {
477                 startIndex = createInteger(request.getParameter(param_name));
478             }
479         }
480
481         // get pageLength
482
param_name = par.getParameter(PAGE_LENGTH_PARAM, PAGE_LENGTH_PARAM_DEFAULT);
483         if (request.getParameter(param_name) != null) {
484             pageLength = createInteger(request.getParameter(param_name));
485         }
486     }
487
488
489     /**
490      * Contextualize this class.
491      *
492      * <p>
493      * Especially retrieve the work directory.
494      * If the index directory is specified relativly, the working directory is
495      * used as home directory of the index directory.
496      * </p>
497      *
498      * @param context Context to use
499      * @exception ContextException If contextualizing fails.
500      * @since
501      */

502     public void contextualize(Context context) throws ContextException {
503         // retrieve the working directory, assuming that the index may reside there
504
workDir = (File JavaDoc) context.get(Constants.CONTEXT_WORK_DIR);
505     }
506
507     /**
508      * Generate xml content describing search results.
509      * Entry point of the ComposerGenerator.
510      * The xml content is generated from the hits object.
511      *
512      *
513      * @exception IOException when there is a problem reading the from file system.
514      * @since
515      * @throws SAXException when there is a problem creating the output SAX events.
516      * @throws ProcessingException when there is a problem obtaining the hits
517      */

518     public void generate() throws IOException JavaDoc, SAXException JavaDoc, ProcessingException {
519         // set default parameter value, in case of no values are set yet.
520
if (startIndex == null) {
521             startIndex = new Integer JavaDoc(START_INDEX_DEFAULT);
522         }
523         if (pageLength == null) {
524             pageLength = new Integer JavaDoc(PAGE_LENGTH_DEFAULT);
525         }
526
527         // Start the document and set the namespace.
528
this.contentHandler.startDocument();
529         this.contentHandler.startPrefixMapping(PREFIX, NAMESPACE);
530         this.contentHandler.startPrefixMapping("xlink", XLINK_NAMESPACE);
531
532         generateResults();
533
534         // End the document.
535
this.contentHandler.endPrefixMapping("xlink");
536         this.contentHandler.endPrefixMapping(PREFIX);
537         this.contentHandler.endDocument();
538     }
539
540
541     /**
542      * Create an Integer.
543      * <p>
544      * Create an Integer from String s, if conversion fails return null.
545      * </p>
546      *
547      * @param s Converting s to an Integer
548      * @return Integer converted value originating from s, or null
549      * @since
550      */

551     private Integer JavaDoc createInteger(String JavaDoc s) {
552         Integer JavaDoc i = null;
553         try {
554             i = new Integer JavaDoc(s);
555         } catch (NumberFormatException JavaDoc nfe) {
556             // ignore it, write only warning
557
if (getLogger().isWarnEnabled()) {
558                 getLogger().warn("Cannot convert " + s + " to Integer", nfe);
559             }
560         }
561         return i;
562     }
563
564
565     /**
566      * Build and generate the search results.
567      * <p>
568      * First build the hits, next generate xml content from the hits,
569      * taking page index, and length into account.
570      * </p>
571      *
572      * @since
573      * @throws SAXException when there is a problem creating the output SAX events.
574      * @throws ProcessingException when there is a problem obtaining the hits
575      */

576     private void generateResults() throws SAXException JavaDoc, ProcessingException {
577
578         // Make the hits
579
LuceneCocoonPager pager = buildHits();
580
581         // The current date and time.
582
long time = System.currentTimeMillis();
583
584         atts.clear();
585         atts.addAttribute("", DATE_ATTRIBUTE, DATE_ATTRIBUTE, CDATA, String.valueOf(time));
586         if (queryString != null && queryString.length() > 0)
587             atts.addAttribute("", QUERY_STRING_ATTRIBUTE, QUERY_STRING_ATTRIBUTE, CDATA, String.valueOf(queryString));
588         atts.addAttribute("", START_INDEX_ATTRIBUTE, START_INDEX_ATTRIBUTE, CDATA, String.valueOf(startIndex));
589         atts.addAttribute("", PAGE_LENGTH_ATTRIBUTE, PAGE_LENGTH_ATTRIBUTE, CDATA, String.valueOf(pageLength));
590
591         contentHandler.startElement(NAMESPACE, RESULTS_ELEMENT, Q_RESULTS_ELEMENT, atts);
592
593         // build xml from the hits
594
generateHits(pager);
595         generateNavigation(pager);
596
597         // End root element.
598
contentHandler.endElement(NAMESPACE, RESULTS_ELEMENT, Q_RESULTS_ELEMENT);
599     }
600
601
602     /**
603      * Generate the xml content of all hits
604      *
605      * @param pager the LuceneContentPager with the search results
606      * @since
607      * @throws SAXException when there is a problem creating the output SAX events.
608      */

609     private void generateHits(LuceneCocoonPager pager) throws SAXException JavaDoc {
610         if (pager != null) {
611             atts.clear();
612             atts.addAttribute("", TOTAL_COUNT_ATTRIBUTE, TOTAL_COUNT_ATTRIBUTE,
613                 CDATA, String.valueOf(pager.getCountOfHits()));
614             atts.addAttribute("", COUNT_OF_PAGES_ATTRIBUTE, COUNT_OF_PAGES_ATTRIBUTE,
615                 CDATA, String.valueOf(pager.getCountOfPages()));
616             contentHandler.startElement(NAMESPACE, HITS_ELEMENT, Q_HITS_ELEMENT, atts);
617             generateHit(pager);
618             contentHandler.endElement(NAMESPACE, HITS_ELEMENT, Q_HITS_ELEMENT);
619         }
620     }
621
622
623     /**
624      * Generate the xml content for each hit.
625      *
626      * @param pager the LuceneCocoonPager with the search results.
627      * @since
628      * @throws SAXException when there is a problem creating the output SAX events.
629      */

630     private void generateHit(LuceneCocoonPager pager) throws SAXException JavaDoc {
631         // get the off set to start from
632
int counter = pager.getStartIndex();
633
634         // get an list of hits which should be placed onto a single page
635
List JavaDoc l = (List JavaDoc) pager.next();
636         Iterator JavaDoc i = l.iterator();
637         for (; i.hasNext(); counter++) {
638             LuceneCocoonPager.HitWrapper hw = (LuceneCocoonPager.HitWrapper) i.next();
639             Document doc = hw.getDocument();
640             float score = hw.getScore();
641             String JavaDoc uri = doc.get(LuceneXMLIndexer.URL_FIELD);
642
643             atts.clear();
644             atts.addAttribute("", RANK_ATTRIBUTE, RANK_ATTRIBUTE, CDATA,
645                     String.valueOf(counter));
646             atts.addAttribute("", SCORE_ATTRIBUTE, SCORE_ATTRIBUTE, CDATA,
647                     String.valueOf(score));
648             atts.addAttribute("", URI_ATTRIBUTE, URI_ATTRIBUTE, CDATA,
649                     String.valueOf(uri));
650             contentHandler.startElement(NAMESPACE, HIT_ELEMENT, Q_HIT_ELEMENT, atts);
651             // fix me, add here a summary of this hit
652
for (Enumeration JavaDoc e = doc.fields(); e.hasMoreElements(); ) {
653                 Field field = (Field)e.nextElement();
654                 if (field.isStored()) {
655                     if (LuceneXMLIndexer.URL_FIELD.equals(field.name()))
656                         continue;
657                     atts.clear();
658                     atts.addAttribute("", NAME_ATTRIBUTE, NAME_ATTRIBUTE, CDATA, field.name());
659                     contentHandler.startElement(NAMESPACE, FIELD_ELEMENT, Q_FIELD_ELEMENT, atts);
660                     String JavaDoc value = field.stringValue();
661                     contentHandler.characters(value.toCharArray(), 0, value.length());
662                     contentHandler.endElement(NAMESPACE, FIELD_ELEMENT, Q_FIELD_ELEMENT);
663                 }
664             }
665
666             contentHandler.endElement(NAMESPACE, HIT_ELEMENT, Q_HIT_ELEMENT);
667         }
668     }
669
670
671     /**
672      * Generate the navigation element.
673      *
674      * @param pager Description of Parameter
675      * @exception SAXException Description of Exception
676      * @since
677      */

678     private void generateNavigation(LuceneCocoonPager pager) throws SAXException JavaDoc {
679
680         if (pager != null) {
681             // generate navigation element
682
atts.clear();
683             atts.addAttribute("", TOTAL_COUNT_ATTRIBUTE, TOTAL_COUNT_ATTRIBUTE,
684                 CDATA, String.valueOf(pager.getCountOfHits()));
685             atts.addAttribute("", COUNT_OF_PAGES_ATTRIBUTE, COUNT_OF_PAGES_ATTRIBUTE,
686                 CDATA, String.valueOf(pager.getCountOfPages()));
687             atts.addAttribute("", HAS_NEXT_ATTRIBUTE, HAS_NEXT_ATTRIBUTE,
688                 CDATA, String.valueOf(pager.hasNext()));
689             atts.addAttribute("", HAS_PREVIOUS_ATTRIBUTE, HAS_PREVIOUS_ATTRIBUTE,
690                 CDATA, String.valueOf(pager.hasPrevious()));
691             atts.addAttribute("", NEXT_INDEX_ATTRIBUTE, NEXT_INDEX_ATTRIBUTE,
692                 CDATA, String.valueOf(pager.nextIndex()));
693             atts.addAttribute("", PREVIOUS_INDEX_ATTRIBUTE, PREVIOUS_INDEX_ATTRIBUTE,
694                 CDATA, String.valueOf(pager.previousIndex()));
695             contentHandler.startElement(NAMESPACE, NAVIGATION_ELEMENT, Q_NAVIGATION_ELEMENT, atts);
696             int count_of_pages = pager.getCountOfPages();
697             for (int i = 0, page_start_index = 0;
698                     i < count_of_pages;
699                     i++, page_start_index += pageLength.intValue()) {
700                 atts.clear();
701                 atts.addAttribute("", START_INDEX_ATTRIBUTE, START_INDEX_ATTRIBUTE,
702                     CDATA, String.valueOf(page_start_index));
703                 contentHandler.startElement(NAMESPACE, NAVIGATION_PAGE_ELEMENT, Q_NAVIGATION_PAGE_ELEMENT, atts);
704                 contentHandler.endElement(NAMESPACE, NAVIGATION_PAGE_ELEMENT, Q_NAVIGATION_PAGE_ELEMENT);
705             }
706             // navigation is EMPTY element
707
contentHandler.endElement(NAMESPACE, NAVIGATION_ELEMENT, Q_NAVIGATION_ELEMENT);
708         }
709     }
710
711
712     /**
713      * Build hits from a query input, and setup paging object.
714      *
715      * @since
716      * @throws ProcessingException if an error occurs
717      */

718     private LuceneCocoonPager buildHits() throws ProcessingException {
719
720         if (queryString != null && queryString.length() != 0) {
721             Hits hits = null;
722
723             try {
724                 Analyzer analyzer = LuceneCocoonHelper.getAnalyzer("org.apache.lucene.analysis.standard.StandardAnalyzer");
725                 lcs.setAnalyzer(analyzer);
726                 // get the directory where the index resides
727
Directory directory = LuceneCocoonHelper.getDirectory(index, false);
728                 lcs.setDirectory(directory);
729                 hits = lcs.search(queryString, LuceneXMLIndexer.BODY_FIELD);
730             } catch (IOException JavaDoc ioe) {
731                 throw new ProcessingException("IOException in search", ioe);
732             }
733
734             // wrap the hits by an pager help object for accessing only a range of hits
735
LuceneCocoonPager pager = new LuceneCocoonPager(hits);
736
737             int start_index = START_INDEX_DEFAULT;
738             if (this.startIndex != null) {
739                 start_index = this.startIndex.intValue();
740                 if (start_index <= 0) {
741                     start_index = 0;
742                 }
743                 pager.setStartIndex(start_index);
744             }
745
746             int page_length = PAGE_LENGTH_DEFAULT;
747             if (this.pageLength != null) {
748                 page_length = this.pageLength.intValue();
749                 if (page_length <= 0) {
750                     page_length = hits.length();
751                 }
752                 pager.setCountOfHitsPerPage(page_length);
753             }
754
755             return pager;
756         }
757
758         return null;
759     }
760
761     /**
762      * Recycle the generator
763      */

764     public void recycle() {
765         super.recycle();
766         if (lcs != null) {
767             this.manager.release(lcs);
768         }
769         this.queryString = null;
770         this.startIndex = null;
771         this.pageLength = null;
772         this.index = null;
773     }
774
775     public void dispose() {
776         super.dispose();
777     }
778 }
779
780
Popular Tags