View Javadoc
1   /*
2    * Copyright (c) 2002-2020, City of 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.participatorybudget.web;
35  
36  import java.io.IOException;
37  import java.text.SimpleDateFormat;
38  import java.util.regex.Matcher;
39  import java.util.regex.Pattern;
40  
41  import javax.servlet.ServletException;
42  import javax.servlet.http.HttpServlet;
43  import javax.servlet.http.HttpServletRequest;
44  import javax.servlet.http.HttpServletResponse;
45  
46  import org.apache.commons.lang.ArrayUtils;
47  import org.apache.commons.lang.StringUtils;
48  import org.apache.log4j.Logger;
49  import org.springframework.web.util.UriComponents;
50  import org.springframework.web.util.UriComponentsBuilder;
51  
52  import fr.paris.lutece.plugins.participatorybudget.business.MyInfosForm;
53  import fr.paris.lutece.plugins.participatorybudget.service.MyInfosService;
54  import fr.paris.lutece.portal.service.security.LuteceUser;
55  import fr.paris.lutece.portal.service.security.SecurityService;
56  import fr.paris.lutece.portal.service.util.AppPropertiesService;
57  
58  public class ProjectSolrSearch extends HttpServlet
59  {
60  
61      private static final long serialVersionUID = -806886865678792152L;
62      private static final String MARK_THEME = "theme";
63      private static final String MARK_ARRONDISSEMENT = "arrondissement";
64      private static final String MARK_ARROND_USER = "user_arrondissement";
65      private static final String MARK_CATEGORY = "categorie";
66      private static final String MARK_QUERY = "query";
67      private static final String MARK_BUDGET = "budget";
68      private static final String MARK_SORT = "sort";
69      private static final String MARK_SORT_ORDER = "sort_order";
70      private static final String MARK_SORT_ALPHABETIQUE = "alpha";
71      private static final String MARK_SORT_DATE = "date";
72      private static final String MARK_TYPE_SEARCH = "type_search";
73      private static final String SEARCH_SIMPLE = "simple";
74      private static final String SEARCH_AVANCEE = "avancee";
75      private static final String SEARCH_THEME = "theme";
76      private static final String SEARCH_ARRONDISSEMENT = "arrondissement";
77  
78      private static final Logger LOGGER = Logger.getLogger( ProjectSolrSearch.class );
79  
80      public static final String PROJECT = AppPropertiesService.getProperty( "participatorybudget.type.project" );
81      public static final String THEME = AppPropertiesService.getProperty( "participatorybudget.name.theme" );
82      public static final String LOCATION = AppPropertiesService.getProperty( "participatorybudget.name.location_text" );
83      public static final String BUDGET = AppPropertiesService.getProperty( "participatorybudget.name.budget" );
84  
85      /**
86       * Get Project specific parameters and call Solr Module.
87       *
88       * @param request
89       *            the request
90       * @param response
91       *            the response
92       * @throws ServletException
93       *             the servlet exception
94       * @throws IOException
95       *             Signals that an I/O exception has occurred.
96       */
97      @Override
98      protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
99      {
100         LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );
101         boolean byProject = false;
102         StringBuilder sbReq = new StringBuilder( "Portal.jsp?page=search-solr" );
103 
104         // Sorts
105         if ( StringUtils.isNotEmpty( request.getParameter( MARK_SORT ) ) )
106         {
107             sbReq.append( "&sort_name=" + request.getParameter( MARK_SORT ) );
108         }
109         if ( StringUtils.isNotEmpty( request.getParameter( MARK_SORT_ORDER ) ) )
110         {
111             sbReq.append( "&sort_order=" + request.getParameter( MARK_SORT_ORDER ) );
112         }
113 
114         // By Input search
115         if ( StringUtils.isNotEmpty( request.getParameter( MARK_QUERY ) ) )
116         {
117             String strQuery = request.getParameter( MARK_QUERY ).replaceAll( ":", "" );
118             sbReq.append( "&query=title:" + strQuery + " OR summary:" + strQuery + " OR identifiant_text:" + strQuery );
119             sbReq.append( "&fq=type:" + PROJECT );
120             byProject = true;
121         }
122         // By Budget
123         if ( StringUtils.isNotEmpty( request.getParameter( MARK_BUDGET ) ) )
124         {
125             sbReq.append( "&query=" + BUDGET + ":" + request.getParameter( MARK_BUDGET ) );
126             if ( !byProject )
127             {
128                 byProject = true;
129                 sbReq.append( "&fq=type:" + PROJECT );
130             }
131 
132         } // By Arrondissement
133         if ( StringUtils.isNotEmpty( getArrondissement( request, user ) ) && !request.getParameter( MARK_ARRONDISSEMENT ).isEmpty( ) )
134         {
135             sbReq.append( "&fq=" + LOCATION + ":" + getArrondissement( request, user ) );
136             if ( !byProject )
137             {
138                 byProject = true;
139 
140                 sbReq.append( "&fq=type:" + PROJECT );
141             }
142         }
143         else
144         {
145             if ( !byProject )
146                 sbReq.append( "&query=*:*&fq=type:" + PROJECT );
147         }
148         // By THEME
149 
150         LOGGER.debug( "Requête SOLR de date, redirection vers " + sbReq.toString( ) );
151 
152         UriComponents uriComponents = UriComponentsBuilder.fromUriString( sbReq.toString( ) ).build( );
153         String strEncodedUri = uriComponents.encode( "UTF-8" ).toUriString( );
154 
155         // Make the redirection
156         response.sendRedirect( strEncodedUri );
157     }
158 
159     /**
160      * Get Project specific parameters and call Solr Module.
161      *
162      * @param request
163      *            the request
164      * @param response
165      *            the response
166      * @throws ServletException
167      *             the servlet exception
168      * @throws IOException
169      *             Signals that an I/O exception has occurred.
170      */
171     protected void doGetOld( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
172     {
173         LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );
174         StringBuilder sbReq = new StringBuilder( "Portal.jsp?page=search-solr" );
175 
176         String sTypeSearch = request.getParameter( MARK_TYPE_SEARCH );
177         String sTypeSort = request.getParameter( MARK_SORT );
178 
179         StringBuilder sbFilter = new StringBuilder( "" );
180         StringBuilder sbSort = null;
181         String sQuery = request.getParameter( MARK_QUERY );
182 
183         if ( StringUtils.isNotEmpty( sTypeSort ) && MARK_SORT_ALPHABETIQUE.equals( sTypeSort ) )
184         {
185             // sort by title
186             sbSort = new StringBuilder( "&sort_name=title&sort_order=asc" );
187         }
188         else
189         {
190             // Sort by date
191             sTypeSort = MARK_SORT_DATE;
192             sbSort = new StringBuilder( "&sort_order=desc" );
193         }
194 
195         if ( ( StringUtils.isEmpty( sTypeSearch ) || SEARCH_SIMPLE.equals( sTypeSearch ) ) && user == null )
196         {
197             // simple search with facets
198             sTypeSearch = SEARCH_SIMPLE;
199             sQuery = sQuery.replaceAll( ":", "" );
200 
201             if ( StringUtils.isNotEmpty( sQuery ) && StringUtils.isNotEmpty( sQuery.trim( ) ) && StringUtils.isNotBlank( ( sQuery.trim( ) ) ) )
202             {
203                 sbReq.append( "&query=title:" + sQuery + " OR summary:" + sQuery + " OR identifiant_text:" + sQuery );
204             }
205             sbFilter.append( "&fq=type:" + PROJECT );
206 
207         }
208         else
209             if ( SEARCH_THEME.equals( sTypeSearch ) && user == null )
210             {
211 
212                 String sTheme = request.getParameter( MARK_THEME );
213                 if ( StringUtils.isNotEmpty( sTheme ) )
214                 {
215                     // sbReq.append( "&query=*:*" );
216                     sbFilter.append( "&fq=" + THEME + ":" + sTheme );
217                 }
218                 sbFilter.append( "&fq=type:" + PROJECT );
219             }
220             else
221                 if ( SEARCH_ARRONDISSEMENT.equals( sTypeSearch ) )
222                 {
223 
224                     sbFilter.append( "&fq=" + LOCATION + ":" + getArrondissement( request, user ) );
225                     sbFilter.append( "&fq=type:" + PROJECT );
226                 }
227                 else
228                     if ( SEARCH_AVANCEE.equals( sTypeSearch ) )
229                     {
230                         SimpleDateFormat sdfXml = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss'Z'" );
231                         String sTheme = request.getParameter( MARK_THEME );
232                         String [ ] categories = request.getParameterValues( MARK_CATEGORY );
233 
234                         String sShowDateStart = request.getParameter( "show_date_start" );
235                         String sShowDateEnd = request.getParameter( "show_date_end" );
236 
237                         if ( StringUtils.isNotEmpty( sTheme ) )
238                         {
239                             sbReq.append( "&query=" + THEME + ":" + sQuery );
240                         }
241                         sbFilter.append( "&fq=type:" + PROJECT );
242 
243                         if ( StringUtils.isNotEmpty( sQuery ) && ArrayUtils.isEmpty( categories ) )
244                         {
245                             sbReq.append( "&query=" + sQuery );
246                         }
247                         else
248                             if ( StringUtils.isNotEmpty( sQuery ) && !ArrayUtils.isEmpty( categories ) )
249                             {
250                                 sbReq.append( "&query=(" + sQuery );
251 
252                                 sbFilter.append( " AND categorie:(" );
253 
254                                 int i = 1;
255 
256                                 for ( String categorie : categories )
257                                 {
258                                     if ( i < categories.length )
259                                     {
260                                         sbFilter.append( categorie.replace( " ", "*" ) ).append( " OR " );
261                                     }
262                                     else
263                                     {
264                                         sbFilter.append( categorie.replace( " ", "*" ) );
265                                     }
266 
267                                     i++;
268                                 }
269 
270                                 sbFilter.append( "))" );
271                             }
272                             else
273                                 if ( !ArrayUtils.isEmpty( categories ) )
274                                 {
275                                     sbFilter.append( "&query=categorie:(" );
276 
277                                     int i = 1;
278 
279                                     for ( String categorie : categories )
280                                     {
281                                         if ( i < categories.length )
282                                         {
283                                             sbFilter.append( categorie.replace( " ", "*" ) ).append( " OR " );
284                                         }
285                                         else
286                                         {
287                                             sbFilter.append( categorie.replace( " ", "*" ) );
288                                         }
289 
290                                         i++;
291                                     }
292 
293                                     sbFilter.append( ")" );
294                                 }
295 
296                         if ( StringUtils.isNotEmpty( sShowDateStart ) )
297                         {
298                             // Timestamp showDateStart = DateUtils.getDate( sShowDateStart, true );
299                             // String sXmlShowDateStart = sdfXml.format( showDateStart );
300                             // sbFilter.append( "&fq=end_date:[" ).append( sXmlShowDateStart ).append( " TO *]" );
301                         }
302 
303                         if ( StringUtils.isNotEmpty( sShowDateEnd ) )
304                         {
305                             // Timestamp showDateEnd = DateUtils.getDate( sShowDateEnd, true );
306                             // String sXmlShowDateEnd = sdfXml.format( showDateEnd );
307 
308                             // sbFilter.append( "&fq=start_date:[* TO " ).append( sXmlShowDateEnd ).append( "]" );
309                         }
310                     }
311 
312         StringBuilder sbType = new StringBuilder( "&type_search=" + sTypeSearch );
313 
314         if ( sbFilter.toString( ).isEmpty( ) && StringUtils.isEmpty( sQuery ) )
315         {
316             // Create default filter
317             sbReq.append( "&query=*:*" );
318         }
319         else
320         {
321             sbReq.append( sbFilter.toString( ) );
322         }
323 
324         sbReq.append( sbSort.toString( ) );
325         sbReq.append( sbType.toString( ) );
326 
327         LOGGER.debug( "Requête SOLR de date, redirection vers " + sbReq.toString( ) );
328 
329         UriComponents uriComponents = UriComponentsBuilder.fromUriString( sbReq.toString( ) ).build( );
330         String strEncodedUri = uriComponents.encode( "UTF-8" ).toUriString( );
331 
332         // Make the redirection
333         response.sendRedirect( strEncodedUri );
334     }
335 
336     /**
337      * Get arrondissement
338      * 
339      * @param request
340      * @param user
341      * @return
342      */
343     private static String getArrondissement( HttpServletRequest request, LuteceUser user )
344     {
345         String strArrondissement = request.getParameter( MARK_ARRONDISSEMENT );
346         if ( ( StringUtils.isEmpty( strArrondissement ) || strArrondissement.equals( MARK_ARROND_USER ) ) && user != null )
347         {
348 
349             MyInfosForm myInfo = MyInfosService.loadUserInfos( user );
350             Pattern p = Pattern.compile( "75(020|00[1-9]|116|01[0-9])$" );
351             Matcher m = p.matcher( myInfo.getArrondissement( ) );
352             if ( m.matches( ) )
353                 strArrondissement = Integer.valueOf( myInfo.getArrondissement( ).substring( 2 ) ) + "e " + MARK_ARRONDISSEMENT;
354 
355         }
356         else
357             if ( strArrondissement != null && strArrondissement.equals( MARK_ARROND_USER ) && user == null )
358             {
359 
360                 strArrondissement = StringUtils.EMPTY;
361             }
362         return strArrondissement;
363     }
364 }