1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.calendar.service.search;
35
36 import fr.paris.lutece.plugins.calendar.service.Utils;
37 import fr.paris.lutece.plugins.calendar.web.Constants;
38 import fr.paris.lutece.portal.service.search.IndexationService;
39 import fr.paris.lutece.portal.service.search.SearchItem;
40 import fr.paris.lutece.portal.service.util.AppLogService;
41 import fr.paris.lutece.portal.service.util.AppPropertiesService;
42
43 import java.text.ParseException;
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Date;
47 import java.util.List;
48
49 import org.apache.commons.lang.StringUtils;
50 import org.apache.lucene.document.DateTools;
51 import org.apache.lucene.document.Document;
52 import org.apache.lucene.index.DirectoryReader;
53 import org.apache.lucene.index.IndexReader;
54 import org.apache.lucene.index.Term;
55 import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
56 import org.apache.lucene.search.BooleanClause;
57 import org.apache.lucene.search.BooleanQuery;
58 import org.apache.lucene.search.IndexSearcher;
59 import org.apache.lucene.search.PhraseQuery;
60 import org.apache.lucene.search.Query;
61 import org.apache.lucene.search.ScoreDoc;
62 import org.apache.lucene.search.TermQuery;
63 import org.apache.lucene.search.TermRangeQuery;
64 import org.apache.lucene.search.TopDocs;
65 import org.apache.lucene.util.BytesRef;
66
67
68
69
70
71 public class CalendarLuceneSearchEngine implements CalendarSearchEngine
72 {
73 private static final String OPEN_PARENTHESIS = "(";
74 private static final String SPACE = " ";
75 private static final String CLOSE_PARENTHESIS = ")";
76 private static final String OR = "OR";
77 private static final String PROPERTY_RESULTS_LIMIT = "calendar.indexer.results.limit";
78
79
80
81
82
83
84
85
86
87
88 public List<CalendarSearchResult> getSearchResults( String[] arrayAgendaIds, String[] arrayCategory,
89 String strContent, Date dateBegin, Date dateEnd )
90 {
91 ArrayList<CalendarSearchItem> listResults = new ArrayList<CalendarSearchItem>( );
92
93 if ( arrayAgendaIds == null || arrayAgendaIds.length == 0 )
94 {
95 return new ArrayList<CalendarSearchResult>( );
96 }
97 IndexSearcher searcher = null;
98
99
100 Query filterRole = null;
101
102 try
103 {
104 IndexReader ir = DirectoryReader.open( IndexationService.getDirectoryIndex( ) );
105 searcher = new IndexSearcher( ir );
106
107 Collection<String> queriesForSearchInContent = new ArrayList<String>( );
108 Collection<String> queriesForSearchInTitle = new ArrayList<String>( );
109 Collection<String> fieldsForSearchInContent = new ArrayList<String>( );
110 Collection<String> fieldsForSearchInTitle = new ArrayList<String>( );
111 Collection<BooleanClause.Occur> flagsForSearchInContent = new ArrayList<BooleanClause.Occur>( );
112 Collection<BooleanClause.Occur> flagsForSearchInTitle = new ArrayList<BooleanClause.Occur>( );
113
114
115 if ( arrayAgendaIds.length > 0 )
116 {
117 String strQueryCalendar = OPEN_PARENTHESIS;
118 int intMoreCalendar = 0;
119
120 for ( String strAgendaId : arrayAgendaIds )
121 {
122 strQueryCalendar += ( strAgendaId + "_" + Constants.CALENDAR_SHORT_NAME );
123 ++intMoreCalendar;
124
125 if ( ( arrayAgendaIds.length > 1 ) && ( intMoreCalendar < arrayAgendaIds.length ) )
126 {
127 strQueryCalendar += ( SPACE + OR + SPACE );
128 }
129 }
130
131 strQueryCalendar += CLOSE_PARENTHESIS;
132
133 Query queryAgendaId = new TermQuery( new Term( Constants.FIELD_CALENDAR_ID, strQueryCalendar ) );
134 queriesForSearchInContent.add( queryAgendaId.toString( ) );
135 queriesForSearchInTitle.add( queryAgendaId.toString( ) );
136 fieldsForSearchInContent.add( Constants.FIELD_CALENDAR_ID );
137 flagsForSearchInContent.add( BooleanClause.Occur.MUST );
138 fieldsForSearchInTitle.add( Constants.FIELD_CALENDAR_ID );
139 flagsForSearchInTitle.add( BooleanClause.Occur.MUST );
140 }
141
142
143 if ( ( arrayCategory != null ) && ( arrayCategory.length > 0 ) )
144 {
145 String strQueryCategory = OPEN_PARENTHESIS;
146 int intMoreCategory = 0;
147
148 for ( String strCategoryId : arrayCategory )
149 {
150 strQueryCategory += strCategoryId;
151 ++intMoreCategory;
152
153 if ( ( arrayCategory.length > 1 ) && ( intMoreCategory < arrayCategory.length ) )
154 {
155 strQueryCategory += ( SPACE + OR + SPACE );
156 }
157 }
158
159 strQueryCategory += CLOSE_PARENTHESIS;
160
161 Query queryAgendaId = new TermQuery( new Term( Constants.FIELD_CATEGORY, strQueryCategory ) );
162 queriesForSearchInContent.add( queryAgendaId.toString( ) );
163 queriesForSearchInTitle.add( queryAgendaId.toString( ) );
164 fieldsForSearchInContent.add( Constants.FIELD_CATEGORY );
165 flagsForSearchInContent.add( BooleanClause.Occur.MUST );
166 fieldsForSearchInTitle.add( Constants.FIELD_CATEGORY );
167 flagsForSearchInTitle.add( BooleanClause.Occur.MUST );
168 }
169
170
171 PhraseQuery.Builder queryTypeBuilder = new PhraseQuery.Builder( );
172 queryTypeBuilder.add( new Term( SearchItem.FIELD_TYPE, Constants.PLUGIN_NAME ) );
173 PhraseQuery queryType = queryTypeBuilder.build( );
174 queriesForSearchInContent.add( queryType.toString( ) );
175 queriesForSearchInTitle.add( queryType.toString( ) );
176 fieldsForSearchInContent.add( SearchItem.FIELD_TYPE );
177 flagsForSearchInContent.add( BooleanClause.Occur.MUST );
178 fieldsForSearchInTitle.add( SearchItem.FIELD_TYPE );
179 flagsForSearchInTitle.add( BooleanClause.Occur.MUST );
180
181
182 if ( StringUtils.isNotBlank( strContent ) )
183 {
184 Query queryContent = new TermQuery( new Term( SearchItem.FIELD_CONTENTS, strContent ) );
185 queriesForSearchInTitle.add( queryContent.toString( ) );
186 fieldsForSearchInContent.add( SearchItem.FIELD_CONTENTS );
187 flagsForSearchInContent.add( BooleanClause.Occur.MUST );
188
189 Query queryTitle = new TermQuery( new Term( SearchItem.FIELD_TITLE, strContent ) );
190 queriesForSearchInContent.add( queryTitle.toString( ) );
191 fieldsForSearchInTitle.add( SearchItem.FIELD_TITLE );
192 flagsForSearchInTitle.add( BooleanClause.Occur.MUST );
193 }
194
195
196 if ( ( dateBegin != null ) && ( dateEnd != null ) )
197 {
198 BytesRef strDateBegin = new BytesRef( Utils.getDate( dateBegin ) );
199 BytesRef strDateEnd = new BytesRef( Utils.getDate( dateEnd ) );
200 Query queryDate = new TermRangeQuery( SearchItem.FIELD_DATE, strDateBegin, strDateEnd, true, true );
201 queriesForSearchInContent.add( queryDate.toString( ) );
202 queriesForSearchInTitle.add( queryDate.toString( ) );
203 fieldsForSearchInContent.add( SearchItem.FIELD_DATE );
204 flagsForSearchInContent.add( BooleanClause.Occur.MUST );
205 fieldsForSearchInTitle.add( SearchItem.FIELD_DATE );
206 flagsForSearchInTitle.add( BooleanClause.Occur.MUST );
207 }else{
208 BytesRef strDate = new BytesRef( Utils.getDate( new Date()) );
209 Query queryDate = new TermRangeQuery( SearchItem.FIELD_DATE, strDate ,null, true, true );
210 queriesForSearchInContent.add( queryDate.toString( ) );
211 queriesForSearchInTitle.add( queryDate.toString( ) );
212 fieldsForSearchInContent.add( SearchItem.FIELD_DATE );
213 flagsForSearchInContent.add( BooleanClause.Occur.MUST );
214 fieldsForSearchInTitle.add( SearchItem.FIELD_DATE );
215 flagsForSearchInTitle.add( BooleanClause.Occur.MUST );
216
217 }
218
219
220 Query queryMulti = MultiFieldQueryParser.parse(
221 queriesForSearchInContent.toArray( new String[queriesForSearchInContent.size( )] ),
222 fieldsForSearchInContent.toArray( new String[fieldsForSearchInContent.size( )] ),
223 flagsForSearchInContent.toArray( new BooleanClause.Occur[flagsForSearchInContent.size( )] ),
224 IndexationService.getAnalyser( ) );
225
226
227 TopDocs hits = null;
228
229 int nLimit = Integer.parseInt( AppPropertiesService.getProperty( PROPERTY_RESULTS_LIMIT ) );
230
231 if ( filterRole != null ) {
232 BooleanQuery.Builder bQueryBuilder = new BooleanQuery.Builder( );
233 bQueryBuilder.add( queryMulti, BooleanClause.Occur.MUST );
234 bQueryBuilder.add( filterRole, BooleanClause.Occur.FILTER );
235 queryMulti = bQueryBuilder.build( );
236 }
237
238 hits = searcher.search( queryMulti, nLimit );
239
240 for ( int i = 0; hits.totalHits > i; i++ )
241 {
242 ScoreDoc hit = hits.scoreDocs[i];
243 Document document = searcher.doc( hit.doc );
244 CalendarSearchItem si = new CalendarSearchItem( document );
245 listResults.add( si );
246 }
247
248
249 Query queryMultiTitle = MultiFieldQueryParser.parse(
250 queriesForSearchInTitle.toArray( new String[queriesForSearchInTitle.size( )] ),
251 fieldsForSearchInTitle.toArray( new String[fieldsForSearchInTitle.size( )] ),
252 flagsForSearchInTitle.toArray( new BooleanClause.Occur[flagsForSearchInTitle.size( )] ),
253 IndexationService.getAnalyser( ) );
254
255
256 TopDocs hitsTitle = null;
257
258 if ( filterRole != null ) {
259 BooleanQuery.Builder bQueryBuilderTitle = new BooleanQuery.Builder( );
260 bQueryBuilderTitle.add( queryMultiTitle, BooleanClause.Occur.MUST );
261 bQueryBuilderTitle.add( filterRole, BooleanClause.Occur.FILTER );
262 queryMultiTitle = bQueryBuilderTitle.build( );
263 }
264
265 hitsTitle = searcher.search( queryMultiTitle, nLimit );
266
267 for ( int i = 0; hitsTitle.totalHits > i; i++ )
268 {
269 ScoreDoc hit = hitsTitle.scoreDocs[i];
270 Document document = searcher.doc( hit.doc );
271 CalendarSearchItem si = new CalendarSearchItem( document );
272 listResults.add( si );
273 }
274 }
275 catch ( Exception e )
276 {
277 AppLogService.error( e.getMessage( ), e );
278 }
279
280 return convertList( listResults );
281 }
282
283
284
285
286
287
288 private List<CalendarSearchResult> convertList( List<CalendarSearchItem> listSource )
289 {
290 List<CalendarSearchResult> listDest = new ArrayList<CalendarSearchResult>( );
291
292 for ( CalendarSearchItem item : listSource )
293 {
294 CalendarSearchResult result = new CalendarSearchResult( );
295 result.setId( item.getId( ) );
296
297 try
298 {
299 result.setDate( DateTools.stringToDate( item.getDate( ) ) );
300 }
301 catch ( ParseException e )
302 {
303 AppLogService.error( "Bad Date Format for indexed item \"" + item.getTitle( ) + "\" : "
304 + e.getMessage( ) );
305 }
306
307 result.setUrl( item.getUrl( ) );
308 result.setTitle( item.getTitle( ) );
309 result.setSummary( item.getSummary( ) );
310 result.setType( item.getType( ) );
311 result.setHtmlSummary( item.getHtmlSummary( ) );
312 listDest.add( result );
313 }
314
315 return listDest;
316 }
317 }