001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.search;
018:
019: import org.apache.lucene.document.Document;
020: import org.apache.lucene.search.Hits;
021:
022: import java.io.IOException;
023: import java.util.ArrayList;
024: import java.util.ListIterator;
025: import java.util.NoSuchElementException;
026:
027: /**
028: * This class should help you to manage paging of hits.
029: *
030: * @author <a href="mailto:berni_huber@a1.net">Bernhard Huber</a>
031: * @version CVS $Id: LuceneCocoonPager.java 433543 2006-08-22 06:22:54Z crossley $
032: */
033: public class LuceneCocoonPager implements ListIterator {
034: /**
035: * Default count of hits per page.
036: */
037: public final static int COUNT_OF_HITS_PER_PAGE_DEFAULT = 5;
038:
039: /**
040: * Default starting index
041: */
042: public final static int HITS_INDEX_START_DEFAULT = 0;
043:
044: /**
045: * Current index of hit to return by next()
046: */
047: int hitsIndex = HITS_INDEX_START_DEFAULT;
048:
049: /**
050: * Maximum count of hits to return by next(), and previous()
051: */
052: int countOfHitsPerPage = COUNT_OF_HITS_PER_PAGE_DEFAULT;
053:
054: /**
055: * Hits to iterate upon
056: */
057: private Hits hits;
058:
059: /**
060: * @param hits Description of Parameter
061: */
062: public LuceneCocoonPager(Hits hits) {
063: setHits(hits);
064: }
065:
066: /**
067: * Constructor for the LuceneCocoonPager object
068: */
069: public LuceneCocoonPager() {
070: }
071:
072: /**
073: * Sets the hits attribute of the LuceneCocoonPager object
074: *
075: * @param hits The new hits value
076: */
077: public void setHits(Hits hits) {
078: this .hits = hits;
079: this .hitsIndex = HITS_INDEX_START_DEFAULT;
080: }
081:
082: /**
083: * Set count of hits displayed per single page
084: *
085: * @param countOfHitsPerPage The new countOfHitsPerPage value
086: */
087: public void setCountOfHitsPerPage(int countOfHitsPerPage) {
088: this .countOfHitsPerPage = countOfHitsPerPage;
089: if (this .countOfHitsPerPage <= 0) {
090: this .countOfHitsPerPage = 1;
091: }
092: }
093:
094: /**
095: * Get starting index for retrieving hits
096: *
097: * @param start_index The new startIndex value
098: */
099: public void setStartIndex(int start_index) {
100: this .hitsIndex = start_index;
101: }
102:
103: /**
104: * Replaces the last element returned by next or previous with the
105: * specified element (optional operation).
106: *
107: * @param o Description of Parameter
108: */
109: public void set(Object o) {
110: throw new UnsupportedOperationException();
111: }
112:
113: /**
114: * Get count of hits
115: *
116: * @return The count of hits
117: */
118: public int getCountOfHits() {
119: return hits.length();
120: }
121:
122: /**
123: * Get count of hits displayed per single page
124: *
125: * @return The countOfHitsPerPage value
126: */
127: public int getCountOfHitsPerPage() {
128: return this .countOfHitsPerPage;
129: }
130:
131: /**
132: * Caluclate count of pages for displaying all hits
133: *
134: * @return The countOfPages value
135: */
136: public int getCountOfPages() {
137: int count_of_pages = hits.length() / this .countOfHitsPerPage;
138: int remainder = hits.length() % this .countOfHitsPerPage;
139: if (remainder != 0) {
140: count_of_pages += 1;
141: }
142: return count_of_pages;
143: }
144:
145: /**
146: * Set starting index for retrieving hits
147: *
148: * @return The startIndex value
149: */
150: public int getStartIndex() {
151: return this .hitsIndex;
152: }
153:
154: /**
155: * Inserts the specified element into the list (optional operation).
156: *
157: * @param o Description of Parameter
158: * @exception UnsupportedOperationException Description of Exception
159: */
160: public void add(Object o) throws UnsupportedOperationException {
161: throw new UnsupportedOperationException();
162: }
163:
164: /**
165: * Returns true if this list iterator has more elements when traversing
166: * the list in the forward direction.
167: *
168: * @return Description of the Returned Value
169: */
170: public boolean hasNext() {
171: return hitsIndex + countOfHitsPerPage < hits.length();
172: }
173:
174: /**
175: * Returns true if this list iterator has more elements when traversing
176: * the list in the reverse direction.
177: *
178: * @return Description of the Returned Value
179: */
180: public boolean hasPrevious() {
181: return hitsIndex >= countOfHitsPerPage;
182: }
183:
184: /**
185: * Returns the next element in the list.
186: *
187: * @return Description of the Returned Value
188: */
189: public Object next() {
190: ArrayList hitsPerPageList = new ArrayList();
191: int endIndex = Math.min(hits.length(), hitsIndex
192: + countOfHitsPerPage);
193: //do not increment the actual hitsindex
194: int hits_copy = hitsIndex;
195: while (hits_copy < endIndex) {
196: try {
197: HitWrapper hit = new HitWrapper(hits.score(hits_copy),
198: hits.doc(hits_copy));
199: hitsPerPageList.add(hit);
200: } catch (IOException ioe) {
201: throw new NoSuchElementException("no more hits: "
202: + ioe.getMessage());
203: }
204: hits_copy++;
205: }
206: return hitsPerPageList;
207: }
208:
209: /**
210: * Returns the index of the element that would be returned by a
211: * subsequent call to next.
212: *
213: * @return Description of the Returned Value
214: */
215: public int nextIndex() {
216: return Math.min(hitsIndex + countOfHitsPerPage,
217: hits.length() - 1);
218: }
219:
220: /**
221: * Returns the previous element in the list.
222: *
223: * @return Description of the Returned Value
224: */
225: public Object previous() {
226: ArrayList hitsPerPageList = new ArrayList();
227:
228: int startIndex = Math.max(0, hitsIndex - countOfHitsPerPage);
229: int endIndex = Math.min(hits.length() - 1, hitsIndex
230: - countOfHitsPerPage);
231:
232: if (startIndex < endIndex) {
233: while (startIndex < endIndex) {
234: try {
235: HitWrapper hit = new HitWrapper(hits
236: .score(startIndex), hits.doc(startIndex));
237: hitsPerPageList.add(hit);
238: } catch (IOException ioe) {
239: throw new NoSuchElementException("no more hits: "
240: + ioe.getMessage());
241: }
242: startIndex++;
243: }
244: hitsIndex = endIndex;
245: } else {
246: throw new NoSuchElementException();
247: }
248: return hitsPerPageList;
249: }
250:
251: /**
252: * Returns the index of the element that would be returned by a
253: * subsequent call to previous.
254: *
255: * @return Description of the Returned Value
256: */
257: public int previousIndex() {
258: return Math.max(0, hitsIndex - countOfHitsPerPage);
259: }
260:
261: /**
262: * Removes from the list the last element that was returned by next or
263: * previous (optional operation).
264: */
265: public void remove() {
266: throw new UnsupportedOperationException();
267: }
268:
269: /**
270: * A helper class encapsulating found document, and its score
271: *
272: * @author <a href="mailto:berni_huber@a1.net">Bernhard Huber</a>
273: * @version CVS $Id: LuceneCocoonPager.java 433543 2006-08-22 06:22:54Z crossley $
274: */
275: public static class HitWrapper {
276: float score;
277: Document document;
278:
279: /**
280: * Constructor for the HitWrapper object
281: *
282: * @param score Description of Parameter
283: * @param document Description of Parameter
284: */
285: public HitWrapper(float score, Document document) {
286: this .document = document;
287: this .score = score;
288: }
289:
290: /**
291: * Gets the document attribute of the HitWrapper object
292: *
293: * @return The document value
294: */
295: public Document getDocument() {
296: return document;
297: }
298:
299: /**
300: * Gets the score attribute of the HitWrapper object
301: *
302: * @return The score value
303: */
304: public float getScore() {
305: return score;
306: }
307:
308: /**
309: * Gets the field attribute of the HitWrapper object
310: *
311: * @param field Description of Parameter
312: * @return The field value
313: */
314: public String getField(String field) {
315: return document.get(field);
316: }
317: }
318: }
|