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.directory.service.directorysearch;
35
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.Date;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map.Entry;
42
43 import javax.servlet.http.HttpServletRequest;
44
45 import org.apache.commons.collections.CollectionUtils;
46 import org.apache.commons.lang3.mutable.MutableBoolean;
47 import org.apache.lucene.index.IndexWriter;
48 import org.apache.lucene.search.IndexSearcher;
49 import org.json.JSONException;
50 import org.json.JSONObject;
51
52 import fr.paris.lutece.plugins.directory.business.Directory;
53 import fr.paris.lutece.plugins.directory.business.DirectoryHome;
54 import fr.paris.lutece.plugins.directory.business.EntryTypeArray;
55 import fr.paris.lutece.plugins.directory.business.IndexerAction;
56 import fr.paris.lutece.plugins.directory.business.IndexerActionFilter;
57 import fr.paris.lutece.plugins.directory.business.IndexerActionHome;
58 import fr.paris.lutece.plugins.directory.business.Record;
59 import fr.paris.lutece.plugins.directory.business.RecordField;
60 import fr.paris.lutece.plugins.directory.business.RecordFieldFilter;
61 import fr.paris.lutece.plugins.directory.business.RecordFieldHome;
62 import fr.paris.lutece.plugins.directory.service.record.IRecordService;
63 import fr.paris.lutece.plugins.directory.service.record.RecordService;
64 import fr.paris.lutece.plugins.directory.utils.DirectoryUtils;
65 import fr.paris.lutece.portal.service.plugin.Plugin;
66 import fr.paris.lutece.portal.service.plugin.PluginService;
67 import fr.paris.lutece.portal.service.spring.SpringContextService;
68 import fr.paris.lutece.portal.service.util.AppLogService;
69
70
71
72
73 public class DirectorySearchService
74 {
75 private static final String BEAN_SEARCH_ENGINE = "directorySearchEngine";
76 private static final String PARAMETER_ID_DIRECTORY = "id_directory";
77 private static final String PARAMETER_ID_ENTRY = "id_entry";
78 private static final String JSON_QUERY_RESULT = "query";
79
80 private static IDirectorySearchIndexer _indexer;
81 private static DirectorySearchFactory _directorySearchFactory;
82 private static final int CONSTANT_TIME_CORRECTION = 3600000 * 12;
83
84
85 private static DirectorySearchService _singleton;
86
87
88
89
90 public DirectorySearchService( )
91 {
92 _indexer = SpringContextService.getBean( "directoryIndexer" );
93 _directorySearchFactory = DirectorySearchFactory.getInstance( );
94 }
95
96
97
98
99
100 public static DirectorySearchService getInstance( )
101 {
102 if ( _singleton == null )
103 {
104 _singleton = new DirectorySearchService( );
105 }
106
107 return _singleton;
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 public List<Integer> getSearchResults( Directory directory, HashMap<String, List<RecordField>> mapSearch, Date dateCreation, Date dateCreationBegin,
130 Date dateCreationEnd, RecordFieldFilter filter, Plugin plugin )
131 {
132 return getSearchResults( directory, mapSearch, dateCreationEnd, dateCreationBegin, dateCreationEnd, null, null, null, filter, plugin );
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 public List<Integer> getSearchResults( Directory directory, HashMap<String, List<RecordField>> mapSearch, Date dateCreation, Date dateCreationBegin,
161 Date dateCreationEnd, Date dateModification, Date dateModificationBegin, Date dateModificationEnd, RecordFieldFilter filter, Plugin plugin )
162 {
163 List<Integer> listRecordResult = new ArrayList<Integer>( );
164
165 IRecordService recordService = SpringContextService.getBean( RecordService.BEAN_SERVICE );
166 listRecordResult = recordService.getListRecordId( filter, plugin );
167
168 if ( mapSearch != null )
169 {
170 List<Integer> listRecordResultTmp = null;
171 List<RecordField> recordFieldSearch;
172 HashMap<String, Object> mapSearchItemEntry;
173 boolean bSearchRecordEmpty;
174 boolean bSearchEmpty;
175
176 try
177 {
178 IDirectorySearchEngine engine = SpringContextService.getBean( BEAN_SEARCH_ENGINE );
179
180 listRecordResultTmp = new ArrayList<Integer>( );
181 bSearchEmpty = true;
182
183 for ( Object entryMapSearch : mapSearch.entrySet( ) )
184 {
185 recordFieldSearch = ( (Entry<String, List<RecordField>>) entryMapSearch ).getValue( );
186
187 int nIdEntry = DirectoryUtils.convertStringToInt( ( (Entry<String, List<RecordField>>) entryMapSearch ).getKey( ) );
188 bSearchRecordEmpty = true;
189
190 if ( recordFieldSearch != null )
191 {
192 mapSearchItemEntry = new HashMap<String, Object>( );
193
194 boolean bIsArray = false;
195 boolean bFirstRecord = true;
196
197 for ( RecordField recordField : recordFieldSearch )
198 {
199 if ( recordField.getEntry( ) instanceof EntryTypeArray )
200 {
201
202 bIsArray = true;
203 mapSearchItemEntry = new HashMap<String, Object>( );
204 recordField.getEntry( ).addSearchCriteria( mapSearchItemEntry, recordField );
205
206 if ( mapSearchItemEntry.size( ) > 0 )
207 {
208 bSearchRecordEmpty = false;
209 bSearchEmpty = false;
210 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY, directory.getIdDirectory( ) );
211 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY_ENTRY, nIdEntry );
212
213 List<Integer> ids = engine.getSearchResults( mapSearchItemEntry );
214
215 if ( CollectionUtils.isEmpty( ids ) )
216 {
217 listRecordResultTmp = new ArrayList<Integer>( );
218
219 break;
220 }
221 else
222 if ( bFirstRecord )
223 {
224 listRecordResultTmp = ids;
225 bFirstRecord = false;
226 }
227 else
228 {
229 listRecordResultTmp = (List<Integer>) CollectionUtils.intersection( listRecordResultTmp, ids );
230 }
231 }
232 }
233 else
234 {
235 recordField.getEntry( ).addSearchCriteria( mapSearchItemEntry, recordField );
236 }
237 }
238
239 if ( !bIsArray && ( mapSearchItemEntry.size( ) > 0 ) )
240 {
241 bSearchRecordEmpty = false;
242 bSearchEmpty = false;
243 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY, directory.getIdDirectory( ) );
244 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY_ENTRY, nIdEntry );
245 listRecordResultTmp.addAll( engine.getSearchResults( mapSearchItemEntry ) );
246 }
247
248 if ( !bSearchRecordEmpty && !directory.isSearchOperatorOr( ) )
249 {
250
251 listRecordResult = DirectoryUtils.retainAllIdsKeepingFirstOrder( listRecordResult, listRecordResultTmp );
252 listRecordResultTmp = new ArrayList<Integer>( );
253 }
254 }
255 }
256
257 if ( directory.isSearchOperatorOr( ) && !bSearchEmpty )
258 {
259 listRecordResult = DirectoryUtils.retainAllIdsKeepingFirstOrder( listRecordResult, listRecordResultTmp );
260 }
261
262
263 if ( dateCreation != null )
264 {
265 listRecordResultTmp = new ArrayList<Integer>( );
266 mapSearchItemEntry = new HashMap<String, Object>( );
267 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY, directory.getIdDirectory( ) );
268 dateCreation.setTime( dateCreation.getTime( ) + CONSTANT_TIME_CORRECTION );
269
270 mapSearchItemEntry.put( DirectorySearchItem.FIELD_DATE_CREATION, dateCreation );
271 listRecordResultTmp.addAll( engine.getSearchResults( mapSearchItemEntry ) );
272
273
274 listRecordResult = DirectoryUtils.retainAllIdsKeepingFirstOrder( listRecordResult, listRecordResultTmp );
275 }
276 else
277 if ( ( dateCreationBegin != null ) && ( dateCreationEnd != null ) )
278 {
279 dateCreationBegin.setTime( dateCreationBegin.getTime( ) + CONSTANT_TIME_CORRECTION );
280 dateCreationEnd.setTime( dateCreationEnd.getTime( ) + CONSTANT_TIME_CORRECTION );
281
282 listRecordResultTmp = new ArrayList<Integer>( );
283 mapSearchItemEntry = new HashMap<String, Object>( );
284 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY, directory.getIdDirectory( ) );
285 mapSearchItemEntry.put( DirectorySearchItem.FIELD_DATE_CREATION_BEGIN, dateCreationBegin );
286 mapSearchItemEntry.put( DirectorySearchItem.FIELD_DATE_CREATION_END, dateCreationEnd );
287 listRecordResultTmp.addAll( engine.getSearchResults( mapSearchItemEntry ) );
288
289
290 listRecordResult = DirectoryUtils.retainAllIdsKeepingFirstOrder( listRecordResult, listRecordResultTmp );
291 }
292
293
294 if ( dateModification != null )
295 {
296 listRecordResultTmp = new ArrayList<Integer>( );
297 mapSearchItemEntry = new HashMap<String, Object>( );
298 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY, directory.getIdDirectory( ) );
299 dateModification.setTime( dateModification.getTime( ) + CONSTANT_TIME_CORRECTION );
300
301 mapSearchItemEntry.put( DirectorySearchItem.FIELD_DATE_MODIFICATION, dateModification );
302 listRecordResultTmp.addAll( engine.getSearchResults( mapSearchItemEntry ) );
303
304
305 listRecordResult = DirectoryUtils.retainAllIdsKeepingFirstOrder( listRecordResult, listRecordResultTmp );
306 }
307 else
308 if ( ( dateModificationBegin != null ) && ( dateModificationEnd != null ) )
309 {
310 dateModificationBegin.setTime( dateModificationBegin.getTime( ) + CONSTANT_TIME_CORRECTION );
311 dateModificationEnd.setTime( dateModificationEnd.getTime( ) + CONSTANT_TIME_CORRECTION );
312
313 listRecordResultTmp = new ArrayList<Integer>( );
314 mapSearchItemEntry = new HashMap<String, Object>( );
315 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY, directory.getIdDirectory( ) );
316 mapSearchItemEntry.put( DirectorySearchItem.FIELD_DATE_MODIFICATION_BEGIN, dateModificationBegin );
317 mapSearchItemEntry.put( DirectorySearchItem.FIELD_DATE_MODIFICATION_END, dateModificationEnd );
318 listRecordResultTmp.addAll( engine.getSearchResults( mapSearchItemEntry ) );
319
320
321 listRecordResult = DirectoryUtils.retainAllIdsKeepingFirstOrder( listRecordResult, listRecordResultTmp );
322 }
323 }
324 catch( Exception e )
325 {
326 AppLogService.error( e.getMessage( ), e );
327
328 listRecordResult = new ArrayList<Integer>( );
329 }
330 }
331
332 return listRecordResult;
333 }
334
335 public String getAutocompleteResult( HttpServletRequest request ) throws Exception
336 {
337 String strIdDirectory = request.getParameter( PARAMETER_ID_DIRECTORY );
338 String strIdEntry = request.getParameter( PARAMETER_ID_ENTRY );
339 Plugin plugin = PluginService.getPlugin( "directory" );
340 StringBuffer result = new StringBuffer( );
341
342 IDirectorySearchEngine engine = SpringContextService.getBean( BEAN_SEARCH_ENGINE );
343
344 if ( ( ( strIdDirectory != null ) && !strIdDirectory.equals( DirectoryUtils.EMPTY_STRING ) )
345 && ( ( strIdEntry != null ) && !strIdEntry.equals( DirectoryUtils.EMPTY_STRING ) ) )
346 {
347 HashMap<String, Object> mapSearchItemEntry = new HashMap<String, Object>( );
348 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY, Integer.parseInt( strIdDirectory ) );
349 mapSearchItemEntry.put( DirectorySearchItem.FIELD_ID_DIRECTORY_ENTRY, Integer.parseInt( strIdEntry ) );
350
351 List<Integer> listIntRecordField = engine.getSearchResults( mapSearchItemEntry );
352 List<RecordField> listRecordField = new ArrayList<RecordField>( );
353
354 for ( Integer idDirectoryRecord : listIntRecordField )
355 {
356 RecordFieldFilter recordFilter = new RecordFieldFilter( );
357 recordFilter.setIdDirectory( Integer.parseInt( strIdDirectory ) );
358 recordFilter.setIdEntry( Integer.parseInt( strIdEntry ) );
359 recordFilter.setIdRecord( idDirectoryRecord );
360 listRecordField.addAll( RecordFieldHome.getRecordFieldList( recordFilter, plugin ) );
361 }
362
363 HashMap<String, String> mapResult = new HashMap<String, String>( );
364
365 for ( RecordField recordField : listRecordField )
366 {
367
368 mapResult.put( recordField.getValue( ), recordField.getValue( ) );
369 }
370
371 for ( String key : mapResult.keySet( ) )
372 {
373 result.append( key + "%" );
374 }
375 }
376
377 JSONObject jo = new JSONObject( );
378
379 try
380 {
381 jo.put( JSON_QUERY_RESULT, result.toString( ) );
382 }
383 catch( JSONException e )
384 {
385 AppLogService.error( e.getMessage( ), e );
386 }
387
388 return jo.toString( );
389 }
390
391
392
393
394
395
396
397
398 public String processIndexing( boolean bCreate )
399 {
400 StringBuffer sbLogs = new StringBuffer( );
401 IndexWriter writer = null;
402 MutableBoolean bCreateIndex = new MutableBoolean( bCreate );
403
404 try
405 {
406 sbLogs.append( "\r\nIndexing all contents ...\r\n" );
407 writer = _directorySearchFactory.getIndexWriter( bCreateIndex );
408
409 Date start = new Date( );
410
411 sbLogs.append( "\r\n<strong>Indexer : " );
412 sbLogs.append( _indexer.getName( ) );
413 sbLogs.append( " - " );
414 sbLogs.append( _indexer.getDescription( ) );
415 sbLogs.append( "</strong>\r\n" );
416 _indexer.processIndexing( writer, bCreateIndex.getValue( ), sbLogs );
417
418 Date end = new Date( );
419
420 sbLogs.append( "Duration of the treatment : " );
421 sbLogs.append( end.getTime( ) - start.getTime( ) );
422 sbLogs.append( " milliseconds\r\n" );
423 }
424 catch( Exception e )
425 {
426 sbLogs.append( " caught a " );
427 sbLogs.append( e.getClass( ) );
428 sbLogs.append( "\n with message: " );
429 sbLogs.append( e.getMessage( ) );
430 sbLogs.append( "\r\n" );
431 AppLogService.error( "Indexing error : " + e.getMessage( ), e );
432 }
433 finally
434 {
435 try
436 {
437 if ( writer != null )
438 {
439 writer.close( );
440 }
441 }
442 catch( IOException e )
443 {
444 AppLogService.error( e.getMessage( ), e );
445 }
446 }
447
448 return sbLogs.toString( );
449 }
450
451
452
453
454
455
456
457
458
459
460
461 public void addIndexerAction( int nIdRecord, int nIdTask, Plugin plugin )
462 {
463 IRecordService recordService = SpringContextService.getBean( RecordService.BEAN_SERVICE );
464 Record record = recordService.findByPrimaryKey( nIdRecord, plugin );
465
466 if ( ( record != null ) && ( record.getDirectory( ) != null ) )
467 {
468 int nDirectoryId = record.getDirectory( ).getIdDirectory( );
469 Directory directory = DirectoryHome.findByPrimaryKey( nDirectoryId, plugin );
470
471 if ( ( directory != null ) && directory.isIndexed( ) )
472 {
473 IndexerAction indexerAction = new IndexerAction( );
474 indexerAction.setIdRecord( nIdRecord );
475 indexerAction.setIdTask( nIdTask );
476 IndexerActionHome.create( indexerAction, plugin );
477 }
478 }
479 }
480
481
482
483
484
485
486
487
488
489 public void removeIndexerAction( int nIdAction, Plugin plugin )
490 {
491 IndexerActionHome.remove( nIdAction, plugin );
492 }
493
494
495
496
497
498
499
500
501
502
503 public List<IndexerAction> getAllIndexerActionByTask( int nIdTask, Plugin plugin )
504 {
505 IndexerActionFilter filter = new IndexerActionFilter( );
506 filter.setIdTask( nIdTask );
507
508 return IndexerActionHome.getList( filter, plugin );
509 }
510
511
512
513
514
515
516
517
518 public IndexSearcher getSearcher( ) throws IOException
519 {
520 return _directorySearchFactory.getIndexSearcher( );
521 }
522 }