View Javadoc
1   /*
2    * Copyright (c) 2002-2017, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.directory.service.directorysearch;
35  
36  import fr.paris.lutece.portal.service.search.IndexationService;
37  import fr.paris.lutece.portal.service.search.LuceneSearchEngine;
38  import fr.paris.lutece.portal.service.util.AppLogService;
39  
40  import org.apache.lucene.document.DateTools;
41  import org.apache.lucene.document.Document;
42  import org.apache.lucene.index.Term;
43  import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
44  import org.apache.lucene.search.BooleanClause;
45  import org.apache.lucene.search.IndexSearcher;
46  import org.apache.lucene.search.Query;
47  import org.apache.lucene.search.ScoreDoc;
48  import org.apache.lucene.search.TermQuery;
49  import org.apache.lucene.search.TermRangeQuery;
50  import org.apache.lucene.search.TopDocs;
51  import org.apache.lucene.util.BytesRef;
52  
53  import java.util.ArrayList;
54  import java.util.Collection;
55  import java.util.Date;
56  import java.util.HashMap;
57  import java.util.List;
58  
59  /**
60   * LuceneSearchEngine
61   */
62  public class DirectoryLuceneSearchEngine implements IDirectorySearchEngine
63  {
64      /**
65       * {@inheritDoc}
66       */
67      @Override
68      public List<Integer> getSearchResults( HashMap<String, Object> mapQuery )
69      {
70          ArrayList<Integer> listResults = new ArrayList<Integer>( );
71          IndexSearcher searcher = null;
72  
73          try
74          {
75              searcher = DirectorySearchService.getInstance( ).getSearcher( );
76  
77              Collection<String> queries = new ArrayList<String>( );
78              Collection<String> fields = new ArrayList<String>( );
79              Collection<BooleanClause.Occur> flags = new ArrayList<BooleanClause.Occur>( );
80  
81              // contains id directory
82              if ( mapQuery.containsKey( DirectorySearchItem.FIELD_ID_DIRECTORY ) )
83              {
84                  Query queryIdDirectory = new TermQuery( new Term( DirectorySearchItem.FIELD_ID_DIRECTORY, Integer.toString( (Integer) mapQuery
85                          .get( DirectorySearchItem.FIELD_ID_DIRECTORY ) ) ) );
86                  queries.add( queryIdDirectory.toString( ) );
87                  fields.add( DirectorySearchItem.FIELD_ID_DIRECTORY );
88                  flags.add( BooleanClause.Occur.MUST );
89              }
90  
91              if ( mapQuery.containsKey( DirectorySearchItem.FIELD_ID_DIRECTORY_ENTRY ) )
92              {
93                  Query queryIdDirectory = new TermQuery( new Term( DirectorySearchItem.FIELD_ID_DIRECTORY_ENTRY, Integer.toString( (Integer) mapQuery
94                          .get( DirectorySearchItem.FIELD_ID_DIRECTORY_ENTRY ) ) ) );
95                  queries.add( queryIdDirectory.toString( ) );
96                  fields.add( DirectorySearchItem.FIELD_ID_DIRECTORY_ENTRY );
97                  flags.add( BooleanClause.Occur.MUST );
98              }
99  
100             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_ID_DIRECTORY_FIELD ) )
101             {
102                 Collection<String> queriesIdDirectoryField = new ArrayList<String>( );
103                 Collection<String> fieldsIdDirectoryField = new ArrayList<String>( );
104                 Collection<BooleanClause.Occur> flagsIdDirectoryField = new ArrayList<BooleanClause.Occur>( );
105 
106                 for ( Integer idField : (List<Integer>) mapQuery.get( DirectorySearchItem.FIELD_ID_DIRECTORY_FIELD ) )
107                 {
108                     Query queryIdDirectory = new TermQuery( new Term( DirectorySearchItem.FIELD_ID_DIRECTORY_FIELD, Integer.toString( idField ) ) );
109                     queriesIdDirectoryField.add( queryIdDirectory.toString( ) );
110                     fieldsIdDirectoryField.add( DirectorySearchItem.FIELD_ID_DIRECTORY_FIELD );
111                     flagsIdDirectoryField.add( BooleanClause.Occur.SHOULD );
112                 }
113 
114                 Query queryMultiIdDirectoryField = MultiFieldQueryParser.parse(
115                         queriesIdDirectoryField.toArray( new String [ queriesIdDirectoryField.size( )] ),
116                         queriesIdDirectoryField.toArray( new String [ fieldsIdDirectoryField.size( )] ),
117                         flagsIdDirectoryField.toArray( new BooleanClause.Occur [ flagsIdDirectoryField.size( )] ), IndexationService.getAnalyser( ) );
118 
119                 queries.add( queryMultiIdDirectoryField.toString( ) );
120                 fields.add( DirectorySearchItem.FIELD_ID_DIRECTORY_FIELD );
121                 flags.add( BooleanClause.Occur.MUST );
122             }
123 
124             // contains content
125             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_CONTENTS ) )
126             {
127                 Query queryContent = new TermQuery( new Term( DirectorySearchItem.FIELD_CONTENTS, (String) mapQuery.get( DirectorySearchItem.FIELD_CONTENTS ) ) );
128                 queries.add( queryContent.toString( ) );
129                 fields.add( DirectorySearchItem.FIELD_CONTENTS );
130                 flags.add( BooleanClause.Occur.MUST );
131             }
132 
133             // contains date
134             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_DATE ) )
135             {
136                 Query queryDate = new TermQuery( new Term( DirectorySearchItem.FIELD_DATE, DateTools.dateToString(
137                         (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE ), DateTools.Resolution.DAY ) ) );
138                 queries.add( queryDate.toString( ) );
139                 fields.add( DirectorySearchItem.FIELD_CONTENTS );
140                 flags.add( BooleanClause.Occur.MUST );
141             }
142 
143             // contains range date
144             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_BEGIN ) && mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_END ) )
145             {
146                 BytesRef strLowerTerm = new BytesRef( DateTools.dateToString( (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_BEGIN ),
147                         DateTools.Resolution.DAY ) );
148                 BytesRef strUpperTerm = new BytesRef( DateTools.dateToString( (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_END ),
149                         DateTools.Resolution.DAY ) );
150                 Query queryRangeDate = new TermRangeQuery( DirectorySearchItem.FIELD_DATE, strLowerTerm, strUpperTerm, true, true );
151                 queries.add( queryRangeDate.toString( ) );
152                 fields.add( DirectorySearchItem.FIELD_DATE );
153                 flags.add( BooleanClause.Occur.MUST );
154             }
155 
156             // record date creation
157             // contains date creation
158             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_CREATION ) )
159             {
160                 Query queryDate = new TermQuery( new Term( DirectorySearchItem.FIELD_DATE_CREATION, DateTools.dateToString(
161                         (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_CREATION ), DateTools.Resolution.DAY ) ) );
162                 queries.add( queryDate.toString( ) );
163                 fields.add( DirectorySearchItem.FIELD_DATE_CREATION );
164                 flags.add( BooleanClause.Occur.MUST );
165             }
166 
167             // contains range date
168             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_CREATION_BEGIN ) && mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_CREATION_END ) )
169             {
170                 BytesRef strLowerTerm = new BytesRef( DateTools.dateToString( (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_CREATION_BEGIN ),
171                         DateTools.Resolution.DAY ) );
172                 BytesRef strUpperTerm = new BytesRef( DateTools.dateToString( (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_CREATION_END ),
173                         DateTools.Resolution.DAY ) );
174                 Query queryRangeDate = new TermRangeQuery( DirectorySearchItem.FIELD_DATE_CREATION, strLowerTerm, strUpperTerm, true, true );
175                 queries.add( queryRangeDate.toString( ) );
176                 fields.add( DirectorySearchItem.FIELD_DATE_CREATION );
177                 flags.add( BooleanClause.Occur.MUST );
178             }
179 
180             // record date creation
181             // contains date creation
182             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_MODIFICATION ) )
183             {
184                 Query queryDate = new TermQuery( new Term( DirectorySearchItem.FIELD_DATE_MODIFICATION, DateTools.dateToString(
185                         (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_MODIFICATION ), DateTools.Resolution.DAY ) ) );
186                 queries.add( queryDate.toString( ) );
187                 fields.add( DirectorySearchItem.FIELD_DATE_MODIFICATION );
188                 flags.add( BooleanClause.Occur.MUST );
189             }
190 
191             // contains range modification date
192             if ( mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_MODIFICATION_BEGIN )
193                     && mapQuery.containsKey( DirectorySearchItem.FIELD_DATE_MODIFICATION_END ) )
194             {
195                 BytesRef strLowerTerm = new BytesRef( DateTools.dateToString( (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_MODIFICATION_BEGIN ),
196                         DateTools.Resolution.DAY ) );
197                 BytesRef strUpperTerm = new BytesRef( DateTools.dateToString( (Date) mapQuery.get( DirectorySearchItem.FIELD_DATE_MODIFICATION_END ),
198                         DateTools.Resolution.DAY ) );
199                 Query queryRangeDate = new TermRangeQuery( DirectorySearchItem.FIELD_DATE_MODIFICATION, strLowerTerm, strUpperTerm, true, true );
200                 queries.add( queryRangeDate.toString( ) );
201                 fields.add( DirectorySearchItem.FIELD_DATE_MODIFICATION );
202                 flags.add( BooleanClause.Occur.MUST );
203             }
204 
205             Query queryMulti = MultiFieldQueryParser.parse( queries.toArray( new String [ queries.size( )] ), fields.toArray( new String [ fields.size( )] ),
206                     flags.toArray( new BooleanClause.Occur [ flags.size( )] ), IndexationService.getAnalyser( ) );
207 
208             // Get results documents
209             TopDocs topDocs = searcher.search( queryMulti, LuceneSearchEngine.MAX_RESPONSES );
210             ScoreDoc [ ] hits = topDocs.scoreDocs;
211 
212             for ( int i = 0; i < hits.length; i++ )
213             {
214                 int docId = hits [i].doc;
215                 Document document = searcher.doc( docId );
216                 listResults.add( new DirectorySearchItem( document ).getIdDirectoryRecord( ) );
217             }
218         }
219         catch( Exception e )
220         {
221             AppLogService.error( e.getMessage( ), e );
222         }
223 
224         return listResults;
225     }
226 }