/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.components.search; import org.apache.lucene.document.Document; import org.apache.lucene.search.Hits; import java.io.IOException; import java.util.ArrayList; import java.util.ListIterator; import java.util.NoSuchElementException; /** * This class should help you to manage paging of hits. * * @author <a href="mailto:berni_huber@a1.net">Bernhard Huber</a> * @version CVS $Id$ */ public class LuceneCocoonPager implements ListIterator { /** * Default count of hits per page. */ public final static int COUNT_OF_HITS_PER_PAGE_DEFAULT = 5; /** * Default starting index */ public final static int HITS_INDEX_START_DEFAULT = 0; /** * Current index of hit to return by next() */ int hitsIndex = HITS_INDEX_START_DEFAULT; /** * Maximum count of hits to return by next(), and previous() */ int countOfHitsPerPage = COUNT_OF_HITS_PER_PAGE_DEFAULT; /** * Hits to iterate upon */ private Hits hits; /** * @param hits Description of Parameter */ public LuceneCocoonPager(Hits hits) { setHits(hits); } /** * Constructor for the LuceneCocoonPager object */ public LuceneCocoonPager() { } /** * Sets the hits attribute of the LuceneCocoonPager object * * @param hits The new hits value */ public void setHits(Hits hits) { this.hits = hits; this.hitsIndex = HITS_INDEX_START_DEFAULT; } /** * Set count of hits displayed per single page * * @param countOfHitsPerPage The new countOfHitsPerPage value */ public void setCountOfHitsPerPage(int countOfHitsPerPage) { this.countOfHitsPerPage = countOfHitsPerPage; if (this.countOfHitsPerPage <= 0) { this.countOfHitsPerPage = 1; } } /** * Get starting index for retrieving hits * * @param start_index The new startIndex value */ public void setStartIndex(int start_index) { this.hitsIndex = start_index; } /** * Replaces the last element returned by next or previous with the * specified element (optional operation). * * @param o Description of Parameter */ public void set(Object o) { throw new UnsupportedOperationException(); } /** * Get count of hits * * @return The count of hits */ public int getCountOfHits() { return hits.length(); } /** * Get count of hits displayed per single page * * @return The countOfHitsPerPage value */ public int getCountOfHitsPerPage() { return this.countOfHitsPerPage; } /** * Caluclate count of pages for displaying all hits * * @return The countOfPages value */ public int getCountOfPages() { int count_of_pages = hits.length() / this.countOfHitsPerPage; int remainder = hits.length() % this.countOfHitsPerPage; if (remainder != 0) { count_of_pages += 1; } return count_of_pages; } /** * Set starting index for retrieving hits * * @return The startIndex value */ public int getStartIndex() { return this.hitsIndex; } /** * Inserts the specified element into the list (optional operation). * * @param o Description of Parameter * @exception UnsupportedOperationException Description of Exception */ public void add(Object o) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Returns true if this list iterator has more elements when traversing * the list in the forward direction. * * @return Description of the Returned Value */ public boolean hasNext() { return hitsIndex + countOfHitsPerPage < hits.length(); } /** * Returns true if this list iterator has more elements when traversing * the list in the reverse direction. * * @return Description of the Returned Value */ public boolean hasPrevious() { return hitsIndex >= countOfHitsPerPage; } /** * Returns the next element in the list. * * @return Description of the Returned Value */ public Object next() { ArrayList hitsPerPageList = new ArrayList(); int endIndex = Math.min(hits.length(), hitsIndex + countOfHitsPerPage); //do not increment the actual hitsindex int hits_copy = hitsIndex; while (hits_copy < endIndex) { try { HitWrapper hit = new HitWrapper(hits.score(hits_copy), hits.doc(hits_copy)); hitsPerPageList.add(hit); } catch (IOException ioe) { throw new NoSuchElementException("no more hits: " + ioe.getMessage()); } hits_copy++; } return hitsPerPageList; } /** * Returns the index of the element that would be returned by a * subsequent call to next. * * @return Description of the Returned Value */ public int nextIndex() { return Math.min(hitsIndex + countOfHitsPerPage, hits.length() - 1); } /** * Returns the previous element in the list. * * @return Description of the Returned Value */ public Object previous() { ArrayList hitsPerPageList = new ArrayList(); int startIndex = Math.max(0, hitsIndex - countOfHitsPerPage); int endIndex = Math.min(hits.length() - 1, hitsIndex - countOfHitsPerPage); if (startIndex < endIndex) { while (startIndex < endIndex) { try { HitWrapper hit = new HitWrapper(hits.score(startIndex), hits.doc(startIndex)); hitsPerPageList.add(hit); } catch (IOException ioe) { throw new NoSuchElementException("no more hits: " + ioe.getMessage()); } startIndex++; } hitsIndex = endIndex; } else { throw new NoSuchElementException(); } return hitsPerPageList; } /** * Returns the index of the element that would be returned by a * subsequent call to previous. * * @return Description of the Returned Value */ public int previousIndex() { return Math.max(0, hitsIndex - countOfHitsPerPage); } /** * Removes from the list the last element that was returned by next or * previous (optional operation). */ public void remove() { throw new UnsupportedOperationException(); } /** * A helper class encapsulating found document, and its score * * @author <a href="mailto:berni_huber@a1.net">Bernhard Huber</a> * @version CVS $Id$ */ public static class HitWrapper { float score; Document document; /** * Constructor for the HitWrapper object * * @param score Description of Parameter * @param document Description of Parameter */ public HitWrapper(float score, Document document) { this.document = document; this.score = score; } /** * Gets the document attribute of the HitWrapper object * * @return The document value */ public Document getDocument() { return document; } /** * Gets the score attribute of the HitWrapper object * * @return The score value */ public float getScore() { return score; } /** * Gets the field attribute of the HitWrapper object * * @param field Description of Parameter * @return The field value */ public String getField(String field) { return document.get(field); } } }