KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mvnforum > search > post > PostSearchQuery


1 /*
2  * $Header: /cvsroot/mvnforum/mvnforum/src/com/mvnforum/search/post/PostSearchQuery.java,v 1.7 2006/04/14 17:05:27 minhnn Exp $
3  * $Author: minhnn $
4  * $Revision: 1.7 $
5  * $Date: 2006/04/14 17:05:27 $
6  *
7  * ====================================================================
8  *
9  * Copyright (C) 2002-2006 by MyVietnam.net
10  *
11  * All copyright notices regarding mvnForum MUST remain
12  * intact in the scripts and in the outputted HTML.
13  * The "powered by" text/logo with a link back to
14  * http://www.mvnForum.com and http://www.MyVietnam.net in
15  * the footer of the pages MUST remain visible when the pages
16  * are viewed on the internet or intranet.
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31  *
32  * Support can be obtained from support forums at:
33  * http://www.mvnForum.com/mvnforum/index
34  *
35  * Correspondence and Marketing Questions can be sent to:
36  * info at MyVietnam net
37  *
38  * @author: Minh Nguyen
39  * @author: Dejan Krsmanovic dejan_krsmanovic@yahoo.com
40  */

41 package com.mvnforum.search.post;
42
43 import java.io.IOException JavaDoc;
44 import java.sql.Timestamp JavaDoc;
45 import java.util.*;
46
47 import com.mvnforum.MVNForumConfig;
48 import com.mvnforum.auth.MVNForumPermission;
49 import com.mvnforum.db.*;
50 import com.mvnforum.search.CombineFilter;
51 import com.mvnforum.search.IntegerFilter;
52 import net.myvietnam.mvncore.exception.DatabaseException;
53 import net.myvietnam.mvncore.exception.ObjectNotFoundException;
54 import org.apache.commons.logging.Log;
55 import org.apache.commons.logging.LogFactory;
56 import org.apache.lucene.analysis.Analyzer;
57 import org.apache.lucene.document.Document;
58 import org.apache.lucene.index.Term;
59 import org.apache.lucene.queryParser.ParseException;
60 import org.apache.lucene.queryParser.QueryParser;
61 import org.apache.lucene.search.*;
62 import org.apache.lucene.store.Directory;
63
64 /**
65  * This class is used for specifying query that should be searched for. Query
66  * can contain keywords and further it can be filtered by specifying member
67  * name of the author, forumID as well as date interval for searching.
68  *
69  * searchString contains one or more keywords. Each keyword can use wildcards.
70  * ? for single character and * for multiple characters.
71  * For specifying boolean operators AND and OR operators can be used.....
72  *
73  * For all available options consult Lucene documentation http://jakarta.apache.org/lucene
74  *
75  * @author Dejan Krsmanovic dejan_krsmanovic@yahoo.com
76  */

77 public class PostSearchQuery
78 {
79     private static Log log = LogFactory.getLog(PostSearchQuery.class);
80
81     // constant for search by time
82
public static final int SEARCH_ANY_DATE = 0;
83
84     public static final int SEARCH_NEWER = 1;
85     public static final int SEARCH_OLDER = 2;
86
87     // constant for search by the post title/body
88
public static final int SEARCH_ONLY_TITLE = 1;
89     public static final int SEARCH_ONLY_BODY = 2;
90
91     private int memberID = -1;
92     private int forumId = 0;
93     private boolean withAttachment = false;// currently doesnt use this variable, use minAttachmentCount
94

95     // search with ignore attachment ( attachmentCount is negative )
96
private int minAttachmentCount = -1;// or 0 should also be okie
97

98     private String JavaDoc searchString = null;
99
100     private Timestamp JavaDoc fromDate = null;
101     private Timestamp JavaDoc toDate = null;
102
103     private int hitCount = 0;
104     private Collection searchResult = null;
105
106     // 1|2 = 3;
107
private int scopeInPost = SEARCH_ONLY_TITLE|SEARCH_ONLY_BODY;
108
109     public PostSearchQuery() {
110     }
111
112     /**
113      * Set name of the author that should be searched for
114      * @param memberId
115      */

116     public void setMemberId(int memberId) {
117         this.memberID = memberId;
118     }
119
120     /**
121      * Id of forum where post belongs. Set to -1 if all forums should be searched
122      * @param forumId
123      */

124     public void setForumId(int forumId) {
125         this.forumId = forumId;
126     }
127
128     /**
129      * Set string that should be searched for.
130      * @param searchString
131      */

132     public void setSearchString(String JavaDoc searchString) {
133         this.searchString = searchString;
134     }
135
136     public void setScopeInPost(int scopeInPost) {
137         this.scopeInPost = scopeInPost;
138     }
139
140     public void setFromDate(Timestamp JavaDoc fromDate) {
141         this.fromDate = fromDate;
142     }
143
144     public void setToDate(Timestamp JavaDoc toDate) {
145         this.toDate = toDate;
146     }
147
148     /**
149      *
150      * @param withAttachment boolean
151      * @deprecated use setMinAttachmentCount
152      */

153     public void setWithAttachment(boolean withAttachment) {
154         this.withAttachment = withAttachment;
155     }
156
157     public void setMinAttachmentCount(int count) {
158         this.minAttachmentCount = count;
159     }
160
161     // Note that with IndexSearcher, the directory is closed automatically
162
protected IndexSearcher getSearcher(Directory directory) throws IOException JavaDoc {
163         try {
164             IndexSearcher searcher = new IndexSearcher(directory);
165             return searcher;
166         } catch (IOException JavaDoc ex) {
167             // we throw new IOException because the original exception
168
// contain sensitive directory information
169
log.error("Cannot access the lucene search index for query. Please check if you have configed mvnForumHome properly. You can also go to Admin Zone to rebuild the Lucene index files.", ex);
170             //@todo : localize me
171
throw new IOException JavaDoc("Cannot access the lucene search index. Please report this error to web site Administrator (check mvnForumHome or rebuild Lucene index).");
172         }
173     }
174
175     public void searchDocuments(int offset, int rowsToReturn, MVNForumPermission permission)
176         throws IOException JavaDoc, DatabaseException, ObjectNotFoundException {
177
178         // Now check if at least one of these input is present: key, member, attachment
179
if ((searchString == null || searchString.equals("")) &&
180             (memberID == -1) &&
181             (minAttachmentCount < 1)) {
182             // should throw an Exception here, if not, later call getPostResult() will return null
183
return;
184         }
185         //Build the query
186
BooleanQuery query = new BooleanQuery();
187         try {
188             Query topicBodyQuery = getTopicBodyQuery();
189             if (topicBodyQuery != null) {
190                 query.add(topicBodyQuery, true, false);
191                 log.debug("topicBodyQuery = " + topicBodyQuery);
192             }
193
194             Query withAttachmentQuery = getWithAttachmentQuery();
195             if (withAttachment) {
196                 query.add(withAttachmentQuery, true, false);
197                 log.debug("withAttachmentQuery = " + withAttachmentQuery);
198             }
199
200             Query categoryForumQuery = getCategoryForumQuery(permission);
201             if (categoryForumQuery != null) {
202                 log.debug("categoryForumQuery = " + categoryForumQuery);
203                 query.add(categoryForumQuery, true, false);
204             }
205
206             Query memberQuery = getMemberQuery();
207             if (memberQuery != null) {
208                 log.debug("memberQuery = " + memberQuery);
209                 query.add(memberQuery, true, false);
210             }
211         } catch (ParseException pe) {
212             log.error("Cannot parse the search query", pe);
213         }
214         log.debug("booleanQuery = " + query);
215
216         DateFilter dateFilter = null;
217         //Add date filter if some of dates provided
218
if (fromDate != null && toDate != null) {
219             dateFilter = new DateFilter(PostIndexer.FIELD_POST_DATE, fromDate, toDate);
220         } else if (fromDate != null) {
221             dateFilter = DateFilter.After(PostIndexer.FIELD_POST_DATE, fromDate);
222         } else if (toDate != null) {
223             dateFilter = DateFilter.Before(PostIndexer.FIELD_POST_DATE, toDate);
224         }
225
226         IntegerFilter attachCountFilter = null;
227
228         if ( minAttachmentCount > 0 ) {
229             attachCountFilter = IntegerFilter.greaterThan(PostIndexer.FIELD_ATTACHMENT_COUNT, minAttachmentCount);
230         }
231
232         Filter filter = null;
233
234         if (dateFilter != null) {
235             if (attachCountFilter != null) {
236                 filter = new CombineFilter(dateFilter, attachCountFilter);
237             } else {
238                 filter = dateFilter;
239             }
240         } else {
241             filter = attachCountFilter;
242         }
243
244         //Now search the documents
245
Directory directory = null;
246         IndexSearcher searcher = null;
247         try {
248             directory = MVNForumConfig.getSearchPostIndexDir();
249             searcher = getSearcher(directory);
250
251             //If filter set then use it
252
Hits postHits = null;
253             if (filter != null) {
254                 postHits = searcher.search(query, filter);
255             } else {
256                 postHits = searcher.search(query);
257             }
258
259             hitCount = postHits.length();
260             searchResult = getPosts(postHits, offset, rowsToReturn);
261         } catch (IOException JavaDoc ex) {
262             throw ex;
263         } finally {
264             // NOTE that we don't close directory because searcher.close() already do that
265
if (searcher != null) {
266                 try {
267                     searcher.close();
268                 } catch (IOException JavaDoc ex) {
269                     log.debug("Error closing Lucene IndexSearcher", ex);
270                 }
271             }
272         }
273     }
274
275     public int getHitCount() {
276         return hitCount;
277     }
278
279     public Collection getPostResult() {
280         if (searchResult == null) {
281             //create an empty list, in case result is null
282
searchResult = new ArrayList();
283         }
284         return searchResult;
285     }
286
287     private Collection getPosts(Hits postHits, int offset, int rowsToReturn)
288         throws IOException JavaDoc, ObjectNotFoundException, DatabaseException {
289
290         if (offset < 0) throw new IllegalArgumentException JavaDoc("The offset < 0 is not allowed.");
291         if (rowsToReturn <= 0) throw new IllegalArgumentException JavaDoc("The rowsToReturn <= 0 is not allowed.");
292
293         //int hitCount = getHitCount();
294
ArrayList retValue = new ArrayList(hitCount);
295
296         for (int i = offset; (i < offset + rowsToReturn) && (i < hitCount); i++) {
297             Document postDocument = postHits.doc(i);
298             int postID = Integer.parseInt(postDocument.get(PostIndexer.FIELD_POST_ID));
299             PostBean postBean = DAOFactory.getPostDAO().getPost(postID);
300             retValue.add(postBean);
301         }
302         return retValue;
303     }
304
305     private Query getTopicBodyQuery() throws ParseException {
306         if (searchString == null || searchString.equals("")) {
307             return null;
308         }
309         Analyzer analyzer = PostIndexer.getAnalyzer();
310         BooleanQuery topicBodyQuery = new BooleanQuery();
311
312         //add topic query
313
Query topicQuery = QueryParser.parse(searchString,
314                                              PostIndexer.FIELD_POST_TOPIC,
315                                              analyzer);
316         topicBodyQuery.add(topicQuery, false, false);
317
318         //add body query
319
Query bodyQuery = QueryParser.parse(searchString,
320                                             PostIndexer.FIELD_POST_BODY,
321                                             analyzer);
322         if ( scopeInPost == SEARCH_ONLY_TITLE) {
323             return topicQuery;
324         } else if ( scopeInPost == SEARCH_ONLY_BODY){
325             return bodyQuery;
326         }
327         topicBodyQuery.add(bodyQuery, false, false);
328
329         return topicBodyQuery;
330     }
331
332     private Query getMemberQuery() {
333         Query memberQuery = null;
334         if (memberID > 0) {
335             Term memberTerm = new Term(PostIndexer.FIELD_MEMBER_ID, String.valueOf(memberID));
336             memberQuery = new TermQuery(memberTerm);
337         }
338         return memberQuery;
339     }
340
341     private Query getWithAttachmentQuery() {
342         Query withAttachmentQuery = null;
343         if (withAttachment) {
344             Term withAttachmentTerm = new Term(PostIndexer.FIELD_WITH_ATTACHMENT, String.valueOf(withAttachment));
345             withAttachmentQuery = new TermQuery(withAttachmentTerm);
346         }
347         return withAttachmentQuery;
348     }
349
350     private Query getCategoryForumQuery(MVNForumPermission permission) throws DatabaseException {
351         BooleanQuery categoryForumQuery = new BooleanQuery();
352         if (forumId == 0) {
353             // search all forum
354
Collection forumBeans = ForumCache.getInstance().getBeans();
355             for (Iterator iter = forumBeans.iterator(); iter.hasNext(); ) {
356                 ForumBean forumBean = (ForumBean)iter.next();
357                 int currentForumID = forumBean.getForumID();
358                 if ((forumBean.getForumStatus() != ForumBean.FORUM_STATUS_DISABLED) &&
359                     permission.canReadPost(currentForumID)) {
360
361                     Term forumTerm = new Term(PostIndexer.FIELD_FORUM_ID, String.valueOf(currentForumID));
362                     Query forumQuery = new TermQuery(forumTerm);
363                     categoryForumQuery.add(forumQuery, false, false);
364                 }
365             }
366         } else if (forumId > 0) {
367             // search in forum
368
Term forumTerm = new Term(PostIndexer.FIELD_FORUM_ID, String.valueOf(forumId));
369             Query forumQuery = new TermQuery(forumTerm);
370             categoryForumQuery.add(forumQuery, true, false);
371         } else if (forumId < 0) {
372             // search in category
373
int categoryID = -forumId;//category is the negative value of forumID in this case
374
Collection forumBeans = ForumCache.getInstance().getBeans();
375             for (Iterator iter = forumBeans.iterator(); iter.hasNext(); ) {
376                 ForumBean forumBean = (ForumBean)iter.next();
377                 if (forumBean.getCategoryID() == categoryID) {
378                     int currentForumID = forumBean.getForumID();
379                     if ((forumBean.getForumStatus() != ForumBean.FORUM_STATUS_DISABLED) &&
380                         permission.canReadPost(currentForumID)) {
381
382                         Term forumTerm = new Term(PostIndexer.FIELD_FORUM_ID, String.valueOf(currentForumID));
383                         Query forumQuery = new TermQuery(forumTerm);
384                         categoryForumQuery.add(forumQuery, false, false);
385                     }
386                 }
387             }
388         }
389         return categoryForumQuery;
390     }
391 }
392
Popular Tags