Source code: com/RuntimeCollective/search/bean/SearchResults.java
1 /* $Header: /home/CVS/rjp/src/com/RuntimeCollective/search/bean/SearchResults.java,v 1.12 2003/09/30 15:12:57 joe Exp $
2 * $Revision: 1.12 $
3 * $Date: 2003/09/30 15:12:57 $
4 *
5 * ====================================================================
6 *
7 * Josephine : http://www.runtime-collective.com/josephine/index.html
8 *
9 * Copyright (C) 2003 Runtime Collective
10 *
11 * This product includes software developed by the
12 * Apache Software Foundation (http://www.apache.org/).
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30 package com.RuntimeCollective.search.bean;
31
32 import com.RuntimeCollective.search.SearchException;
33 import com.RuntimeCollective.search.bean.SearchResult;
34 import com.RuntimeCollective.webapps.bean.User;
35
36 import org.apache.lucene.search.Hits;
37 import org.apache.lucene.document.Document;
38
39 import java.util.List;
40 import java.util.Vector;
41 import java.io.IOException;
42
43 /**
44 * A collection of SearchResult objects, with methods to access them conveniently from a jsp
45 *
46 * @author Joe Holmberg
47 * @version $Id: SearchResults.java,v 1.12 2003/09/30 15:12:57 joe Exp $
48 */
49 public class SearchResults {
50
51 Vector allResults;
52 int page = 1;
53 int resultsPerPage = 20;
54 SearchCriterion[] searchCriteria;
55
56 /**
57 * Make a new set of SearchResults, from a Lucene <code>Hits</code> collection.
58 * This constructor is called from <code>SearchIndex.performSearch()</code>.
59 * @param hits All Hits returned for this search.
60 * @param sc An array of SearchCriterion used to make this search. This is handy for showing the user what they searched for.
61 */
62 public SearchResults(Hits hits, SearchCriterion[] sc) throws SearchException {
63 searchCriteria = sc;
64
65 allResults = new Vector();
66 try {
67 for (int i=0; i<hits.length(); i++) {
68 allResults.add(new SearchResult(hits.doc(i), hits.score(i), i+1));
69 }
70 } catch (IOException e) {
71 throw new SearchException("IOException constructing new SearchResults: "+e);
72 }
73 }
74
75 /**
76 * Make a new set of SearchResults, from a Lucene <code>Hits</code> collection, with a maximum size.
77 * This constructor is called from <code>SearchIndex.performSearch()</code>.
78 * @param hits All Hits returned for this search.
79 * @param sc An array of SearchCriterion used to make this search. This is handy for showing the user what they searched for.
80 * @param maxNoResults The maximum number of results.
81 */
82 public SearchResults(Hits hits, SearchCriterion[] sc, int maxNoResults) throws SearchException {
83 searchCriteria = sc;
84 allResults = new Vector();
85
86 if (hits.length() < maxNoResults)
87 maxNoResults = hits.length();
88
89 try {
90 for (int i=0; i<maxNoResults; i++) {
91 allResults.add(new SearchResult(hits.doc(i), hits.score(i), i+1));
92 }
93 } catch (IOException e) {
94 throw new SearchException("IOException constructing new SearchResults: "+e);
95 }
96 }
97
98 /**
99 * Return an array of SearchCriteria.
100 */
101 public SearchCriterion[] getSearchCriteriaObjects() { return searchCriteria; }
102
103 /**
104 * Return a string of the first search criteria given for this search.
105 * (maybe there'll be different ways of doing this when we eventually have multiple criteria...)
106 */
107 public String getFirstCriterion() {
108 return searchCriteria[0].getCriterion();
109 }
110
111 /**
112 * Return the value of the first search criteria's <code>findAllWords</code>.
113 * (maybe there'll be different ways of doing this when we eventually have multiple criteria...)
114 */
115 public boolean getFirstFindAllWords() {
116 return searchCriteria[0].getFindAllWords();
117 }
118
119 protected User TheUser = null;
120
121 /**
122 * Set the User who performed this Search
123 */
124 public void setUser(User user) {
125 TheUser = user;
126 }
127
128 /**
129 * Returns the User who performed this Search
130 */
131 public User getUser() {
132 return TheUser;
133 }
134
135 /**
136 * Returns the number of search results
137 */
138 public int getNumberOfResults() {
139 return allResults.size();
140 }
141
142 /**
143 * Return a List that contains all the SearchResult objects in this collection.
144 */
145 public List getAllResults() {
146 return allResults;
147 }
148
149 /**
150 * Set the List that contains all the SearchResult objects in this collection.
151 */
152 public void setAllResults(List results) {
153 allResults = new Vector(results);
154 }
155
156 /**
157 * Remove one result
158 * @param pos, the position of the result in the list
159 */
160 public void removeResult(int pos) {
161 allResults.remove(pos);
162 }
163
164 /**
165 * Return a List that contains the next set of SearchResult objects in this collection.
166 * <p>How many <code>SearchResult</code>s are in the List depends on <code>resultsPerPage</code>,
167 * which is set with <code>setResultsPerPage</code>.
168 * <p>To advance to the next page of results, call <code>nextPage()</code>.
169 * <p>To set the next page arbitrarily, call <code>setPageNumber(int)</code>.
170 */
171 public List getPageResults() {
172 int firstResult = (page-1) * resultsPerPage;
173 int lastResult = firstResult + resultsPerPage - 1;
174 //RuntimeParameters.logDebug(this, "getPageResults: firstResult="+firstResult+", lastResult="+lastResult);
175
176 if (lastResult >= allResults.size()) {
177 lastResult = allResults.size() - 1;
178 //RuntimeParameters.logDebug(this, "Too big; cutting down to "+lastResult);
179 }
180
181 // TEMP
182 //RuntimeParameters.logDebug(this, "Number of results: "+allResults.subList(firstResult, lastResult).size());
183 //java.util.Iterator temp = allResults.subList(firstResult, lastResult).iterator();
184 //while (temp.hasNext())
185 //RuntimeParameters.logDebug(this, "*** Text: "+((SearchResult)temp.next()).getSearchText());
186 // /TEMP
187
188 // endIndex is exclusive
189 return allResults.subList(firstResult, lastResult + 1);
190 }
191
192 /**
193 * Returns <code>true</code> if there is another search results page
194 */
195 public boolean getHasNextPage() {
196 return (page < getMaxPageNumber());
197 }
198
199 /**
200 * Returns <code>true</code> if there is a previous search results page
201 */
202 public boolean getHasPreviousPage() {
203 return (page > 1);
204 }
205
206 /**
207 * Advance one page; returns false if there is no next page
208 */
209 public boolean nextPage() {
210 if (getHasNextPage()) {
211 page++;
212 return true;
213 } else {
214 return false;
215 }
216 }
217
218 /**
219 * Go back one page; returns false if there is no page before
220 */
221 public boolean previousPage() {
222 if (getHasPreviousPage()) {
223 page--;
224 return true;
225 } else {
226 return false;
227 }
228 }
229
230 /** Get the highest page number available */
231 public int getMaxPageNumber() {
232 //RuntimeParameters.logDebug(this, "maxPageNumber: num results="+allResults.size()+", resultsPP="+resultsPerPage+", so max="+Math.ceil((double)allResults.size() / (double)resultsPerPage));
233 double rpp = (double)allResults.size() / (double)resultsPerPage;
234 return (int)Math.ceil(rpp);
235 }
236
237 /** Get the number of results to return with getPageResults() */
238 public int getResultsPerPage() { return this.resultsPerPage; }
239 /** Set the number of results to return with getPageResults()
240 * @exception IllegalArgumentException if the results per page given is less than 1
241 */
242 public void setResultsPerPage(int resultsPerPage) {
243 if (resultsPerPage > 0)
244 this.resultsPerPage = resultsPerPage;
245 else throw new IllegalArgumentException("Must have at least one result per page");
246 }
247
248 /** Get which "page" of results will be returned by getPageResults() */
249 public int getPageNumber() { return this.page; }
250
251 /** Directly select which "page" of results to return with getPageResults().
252 * @exception IllegalArgumentException if the page number is out of bounds
253 */
254 public void setPageNumber(int page) {
255 if (page >= 1 && page <= getMaxPageNumber())
256 this.page = page;
257 else throw new IllegalArgumentException("Page number out of bounds");
258 }
259 }