View Javadoc
1   /*
2    * Copyright (c) 2002-2018, 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.modules.multiview.web;
35  
36  import java.util.ArrayList;
37  import java.util.Collections;
38  import java.util.List;
39  import java.util.Map;
40  import java.util.stream.Collectors;
41  
42  import javax.servlet.http.HttpServletRequest;
43  
44  import org.apache.commons.collections.CollectionUtils;
45  import org.apache.commons.lang3.StringUtils;
46  import org.apache.commons.lang3.math.NumberUtils;
47  
48  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.DirectoryRecordItem;
49  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.DirectoryRecordItemComparator;
50  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.DirectoryRecordItemComparatorConfig;
51  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.column.IRecordColumn;
52  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.column.RecordColumnFactory;
53  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.filter.IRecordFilter;
54  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.filter.RecordFilterFactory;
55  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.panel.IRecordPanel;
56  import fr.paris.lutece.plugins.directory.modules.multiview.business.record.panel.RecordPanelFactory;
57  import fr.paris.lutece.plugins.directory.modules.multiview.service.IDirectoryMultiviewService;
58  import fr.paris.lutece.plugins.directory.modules.multiview.service.search.IDirectoryMultiviewSearchService;
59  import fr.paris.lutece.plugins.directory.modules.multiview.util.DirectoryMultiviewConstants;
60  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.column.display.IRecordColumnDisplay;
61  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.column.display.RecordColumnDisplayFactory;
62  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.filter.display.IRecordFilterDisplay;
63  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.filter.display.RecordFilterDisplayFactory;
64  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.panel.display.IRecordPanelDisplay;
65  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.panel.display.factory.RecordPanelDisplayFactory;
66  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.util.RecordListPositionComparator;
67  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.util.RecordListTemplateBuilder;
68  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.util.RecordListUtil;
69  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
70  import fr.paris.lutece.portal.service.spring.SpringContextService;
71  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
72  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
73  import fr.paris.lutece.util.html.Paginator;
74  import fr.paris.lutece.util.url.UrlItem;
75  
76  /**
77   * This class provides the user interface to manage form features ( manage, create, modify, remove)
78   */
79  @Controller( controllerJsp = "ManageMultiDirectoryRecords.jsp", controllerPath = "jsp/admin/plugins/directory/modules/multiview/", right = "DIRECTORY_MULTIVIEW" )
80  public class MultiDirectoryJspBean extends AbstractJspBean
81  {
82      // Public properties
83      private static final String CONTROLLER_JSP_NAME = "ManageMultiDirectoryRecords.jsp";
84  
85      /**
86       * Generated serial version UID
87       */
88      private static final long serialVersionUID = -8417121042985481292L;
89  
90      // Templates
91      private static final String TEMPLATE_MANAGE_MULTI_DIRECTORY_RECORD = "admin/plugins/directory/modules/multiview/manage_multi_directory_record.html";
92  
93      // Properties
94      private static final String PROPERTY_MANAGE_DIRECTORY_RECORD_PAGE_TITLE = "module.directory.multiview.manage_directory_multirecord.pageTitle.label";
95  
96      // Views
97      private static final String VIEW_MULTIVIEW = "view_multiview";
98  
99      // Markers
100     private static final String MARK_LOCALE = "locale";
101     private static final String MARK_PAGINATOR = "paginator";
102     private static final String MARK_SEARCH_TEXT = "search_text";
103     private static final String MARK_RECORD_PANEL_LIST = "record_panel_list";
104     private static final String MARK_CURRENT_SELECTED_PANEL = "current_selected_panel";
105     private static final String MARK_RECORD_FILTER_LIST = "record_filter_list";
106     private static final String MARK_TABLE_TEMPLATE = "table_template";
107 
108     // JSP URL
109     private static final String JSP_MANAGE_MULTIVIEW = "jsp/admin/plugins/directory/modules/multiview/ManageMultiDirectoryRecords.jsp";
110 
111     // Parameters
112     private static final String PARAMETER_PAGE_INDEX = "page_index";
113 
114     // Constants
115     private static final String BASE_SORT_URL_PATTERN = JSP_MANAGE_MULTIVIEW + "?current_selected_panel=%s";
116 
117     // Session fields
118     private String _strSearchedText = StringUtils.EMPTY;
119     private String _strSelectedPanelTechnicalCode = StringUtils.EMPTY;
120     private transient List<IRecordColumn> _listRecordColumn;
121     private transient List<IRecordFilterDisplay> _listRecordFilterDisplay;
122     private transient List<IRecordColumnDisplay> _listRecordColumnDisplay;
123     private transient List<IRecordPanelDisplay> _listRecordPanelDisplay;
124     private transient IRecordPanelDisplay _recordPanelDisplayActive;
125     private transient DirectoryRecordItemComparatorConfig _directoryRecordItemComparatorConfig;
126     private final transient IDirectoryMultiviewService _directoryMultiviewService = SpringContextService.getBean( IDirectoryMultiviewService.BEAN_NAME );
127     private final transient IDirectoryMultiviewSearchService _directoryMultiviewSearchService = SpringContextService
128             .getBean( IDirectoryMultiviewSearchService.BEAN_NAME );
129 
130     /**
131      * Return management of directory record ( list of directory record ).
132      * 
133      * @param request
134      *            The Http request
135      * @throws AccessDeniedException
136      *             the {@link AccessDeniedException}
137      * @return IPluginActionResult
138      */
139     @View( value = VIEW_MULTIVIEW, defaultView = true )
140     public String getManageDirectoryRecord( HttpServletRequest request ) throws AccessDeniedException
141     {
142         // Retrieve the list of all filters, columns and panels if the pagination and the sort are not used
143         boolean bIsSessionLost = isSessionLost( );
144         if ( isPaginationAndSortNotUsed( request ) || bIsSessionLost )
145         {
146             initRecordRelatedLists( request );
147             _strSearchedText = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SEARCHED_TEXT );
148             manageSelectedPanel( );
149         }
150 
151         // Build the Column for the Panel and save their values for the active panel
152         buildRecordPanelDisplayWithData( request );
153 
154         // Sort the list of DirectoryRecordItem of the RecordPanel with the request information
155         sortDirectoryRecordItemList( request, _recordPanelDisplayActive.getDirectoryRecordItemList( ) );
156 
157         // Build the template of each record filter display
158         if ( isPaginationAndSortNotUsed( request ) || bIsSessionLost )
159         {
160             _listRecordFilterDisplay.stream( ).forEach( recordFilterDisplay -> recordFilterDisplay.buildTemplate( request ) );
161             Collections.sort( _listRecordFilterDisplay, new RecordListPositionComparator( ) );
162         }
163 
164         // Retrieve the list of all id of record of the active RecordListPanelDisplay
165         List<Integer> listIdRecord = RecordListUtil.getListIdRecordOfRecordPanel( _recordPanelDisplayActive );
166 
167         // Build the model
168         Map<String, Object> model = getPaginatedListModel( request, Paginator.PARAMETER_PAGE_INDEX, listIdRecord, JSP_MANAGE_MULTIVIEW,
169                 _strSelectedPanelTechnicalCode );
170         model.put( MARK_PAGINATOR, getPaginator( ) );
171         model.put( MARK_LOCALE, getLocale( ) );
172         model.put( MARK_SEARCH_TEXT, _strSearchedText );
173         model.put( MARK_RECORD_FILTER_LIST, _listRecordFilterDisplay );
174 
175         // Add the template of column to the model
176         String strSortUrl = String.format( BASE_SORT_URL_PATTERN, _strSelectedPanelTechnicalCode );
177         String strRedirectionDetailsBaseUrl = buildRedirectionDetailsBaseUrl( );
178         List<DirectoryRecordItem> listDirectoryRecordItemToDisplay = buildDirectoryRecordItemListToDisplay( );
179         String strTableTemplate = RecordListTemplateBuilder.buildTableTemplate( _listRecordColumnDisplay, listDirectoryRecordItemToDisplay, getLocale( ),
180                 strRedirectionDetailsBaseUrl, strSortUrl );
181         model.put( MARK_TABLE_TEMPLATE, strTableTemplate );
182 
183         // Add the list of all record panel
184         model.put( MARK_RECORD_PANEL_LIST, _listRecordPanelDisplay );
185         model.put( MARK_CURRENT_SELECTED_PANEL, _strSelectedPanelTechnicalCode );
186 
187         return getPage( PROPERTY_MANAGE_DIRECTORY_RECORD_PAGE_TITLE, TEMPLATE_MANAGE_MULTI_DIRECTORY_RECORD, model );
188     }
189 
190     /**
191      * Return the boolean which tell if the pagination and the sort are not used
192      * 
193      * @param request
194      *            The request to retrieve the information from
195      * @return the boolean which tell if the pagination and the sort are not used
196      */
197     private boolean isPaginationAndSortNotUsed( HttpServletRequest request )
198     {
199         return request.getParameter( PARAMETER_PAGE_INDEX ) == null
200                 && request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_COLUMN_POSITION ) == null;
201     }
202 
203     /**
204      * Return the boolean which tell if the session is lost
205      * 
206      * @return the boolean which tell if the session is lost
207      */
208     private boolean isSessionLost( )
209     {
210         return _listRecordColumn == null || _listRecordFilterDisplay == null || _listRecordColumnDisplay == null || _listRecordPanelDisplay == null
211                 || _recordPanelDisplayActive == null;
212     }
213 
214     /**
215      * Build the list of all columns, filters and record panels and all of their display equivalents
216      * 
217      * @param request
218      *            The request used to build the list of the records elements
219      */
220     private void initRecordRelatedLists( HttpServletRequest request )
221     {
222         List<IRecordFilter> listRecordFilter = new RecordFilterFactory( ).buildRecordFilterList( );
223         List<IRecordPanel> listRecordPanel = new RecordPanelFactory( ).buildRecordPanelList( );
224 
225         RecordColumnFactory recordColumnFactory = SpringContextService.getBean( RecordColumnFactory.BEAN_NAME );
226         _listRecordColumn = recordColumnFactory.buildRecordColumnList( );
227 
228         _listRecordFilterDisplay = new RecordFilterDisplayFactory( ).createRecordFilterDisplayList( request, listRecordFilter );
229         _listRecordColumnDisplay = new RecordColumnDisplayFactory( ).createRecordColumnDisplayList( _listRecordColumn );
230         _listRecordPanelDisplay = new RecordPanelDisplayFactory( ).createRecordPanelDisplayList( request, listRecordPanel );
231     }
232 
233     /**
234      * Retrieve the technical code of the selected panel and change the value of the previous selected one if it wasn't the same and reset the pagination in
235      * this case
236      */
237     private void manageSelectedPanel( )
238     {
239         IRecordPanelDisplay recordPanelDisplay = _directoryMultiviewService.findActiveRecordPanel( _listRecordPanelDisplay );
240         if ( recordPanelDisplay != null )
241         {
242             String strSelectedPanelTechnicalCode = recordPanelDisplay.getTechnicalCode( );
243             if ( StringUtils.isNotBlank( strSelectedPanelTechnicalCode ) && !_strSelectedPanelTechnicalCode.equals( strSelectedPanelTechnicalCode ) )
244             {
245                 _strSelectedPanelTechnicalCode = strSelectedPanelTechnicalCode;
246                 resetCurrentPaginatorPageIndex( );
247             }
248         }
249     }
250 
251     /**
252      * Build all the record panels by building their template and retrieve the data of their columns for the given list of filter and the specified text to
253      * search
254      */
255     private void buildRecordPanelDisplayWithData( HttpServletRequest request )
256     {
257         // Retrieve the list of all RecordFilter
258         List<IRecordFilter> listRecordFilter = _listRecordFilterDisplay.stream( ).map( IRecordFilterDisplay::getRecordFilter ).collect( Collectors.toList( ) );
259 
260         for ( IRecordPanelDisplay recordPanelDisplay : _listRecordPanelDisplay )
261         {
262             // Retrieve the RecordPanel from the RecordPanelDisplay
263             IRecordPanel recordPanel = recordPanelDisplay.getRecordPanel( );
264 
265             // Populate the RecordColumns from the information of the list of RecordFilterItem of the given RecordPanel
266             _directoryMultiviewService.populateRecordColumns( recordPanel, _listRecordColumn, listRecordFilter );
267 
268             // Filter the record with RBAC on directory
269             _directoryMultiviewService.filterByAuthorizedDirectory( recordPanel, request );
270 
271             if ( StringUtils.isNotBlank( _strSearchedText ) )
272             {
273                 _directoryMultiviewSearchService.filterBySearchedText( recordPanel, _strSearchedText );
274             }
275 
276             // Associate for each RecordColumnDisplay its RecordColumnValues if the panel is active
277             if ( recordPanelDisplay.isActive( ) )
278             {
279                 _recordPanelDisplayActive = recordPanelDisplay;
280             }
281 
282             // Build the template of the record list panel
283             recordPanelDisplay.buildTemplate( getLocale( ) );
284         }
285     }
286 
287     /**
288      * Build the list of DirectoryRecordItem to display for the given IRecordFilterPanelDisplay based on the number of items of the current paginator
289      * 
290      * @return list of DirectoryRecordItem to display for the given IRecordFilterPanelDisplay
291      */
292     private List<DirectoryRecordItem> buildDirectoryRecordItemListToDisplay( )
293     {
294         List<DirectoryRecordItem> listDirectoryRecordItemToDisplay = new ArrayList<>( );
295 
296         List<Integer> listIdRecordPaginated = getPaginator( ).getPageItems( );
297         List<DirectoryRecordItem> listDirectoryRecordItem = _recordPanelDisplayActive.getDirectoryRecordItemList( );
298         if ( listIdRecordPaginated != null && !listIdRecordPaginated.isEmpty( ) && listDirectoryRecordItem != null && !listDirectoryRecordItem.isEmpty( ) )
299         {
300             for ( DirectoryRecordItem directoryRecordItem : listDirectoryRecordItem )
301             {
302                 Integer nIdRecord = directoryRecordItem.getIdRecord( );
303                 if ( listIdRecordPaginated.contains( nIdRecord ) )
304                 {
305                     listDirectoryRecordItemToDisplay.add( directoryRecordItem );
306                 }
307             }
308         }
309 
310         return listDirectoryRecordItemToDisplay;
311     }
312 
313     /**
314      * Sort the given list of DirectoryRecordItem from the values contains in the request
315      * 
316      * @param request
317      *            The request to retrieve the values used for the sort
318      * @param listDirectoryRecordItem
319      *            The list of DirectoryRecordItem to sort
320      */
321     private void sortDirectoryRecordItemList( HttpServletRequest request, List<DirectoryRecordItem> listDirectoryRecordItem )
322     {
323         if ( request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_COLUMN_POSITION ) != null )
324         {
325             buildDirectoryRecordItemComparatorConfiguration( request );
326         }
327 
328         if ( listDirectoryRecordItem != null && !listDirectoryRecordItem.isEmpty( ) )
329         {
330             DirectoryRecordItemComparator directoryRecordItemComparator = new DirectoryRecordItemComparator( _directoryRecordItemComparatorConfig );
331             Collections.sort( listDirectoryRecordItem, directoryRecordItemComparator );
332         }
333     }
334 
335     /**
336      * Build the configuration to use for sort the DirectoryRecordItem with the information from the request
337      * 
338      * @param request
339      *            The request to retrieve the values for the sort from
340      */
341     private void buildDirectoryRecordItemComparatorConfiguration( HttpServletRequest request )
342     {
343         String strColumnToSortPosition = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_COLUMN_POSITION );
344         int nColumnToSortPosition = NumberUtils.toInt( strColumnToSortPosition, NumberUtils.INTEGER_MINUS_ONE );
345 
346         String strSortKey = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_ATTRIBUTE_NAME );
347 
348         String strAscSort = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_ASC_VALUE );
349         boolean bAscSort = Boolean.parseBoolean( strAscSort );
350 
351         _directoryRecordItemComparatorConfig = new DirectoryRecordItemComparatorConfig( nColumnToSortPosition, strSortKey, bAscSort );
352     }
353 
354     /**
355      * Build the base url to use for redirect to the page of the details of a record
356      * 
357      * @return the base url to use for redirect to the details page of a record
358      */
359     private String buildRedirectionDetailsBaseUrl( )
360     {
361         UrlItem urlRedirectionDetails = new UrlItem( MultiviewRecordDetailsJspBean.getMultiviewRecordDetailsBaseUrl( ) );
362 
363         if ( !CollectionUtils.isEmpty( _listRecordFilterDisplay ) )
364         {
365             for ( IRecordFilterDisplay recordFilterDisplay : _listRecordFilterDisplay )
366             {
367                 // Add all the filters values
368                 String strFilterValue = recordFilterDisplay.getValue( );
369                 if ( !StringUtils.isEmpty( strFilterValue ) )
370                 {
371                     String strFilterFullName = DirectoryMultiviewConstants.PARAMETER_URL_FILTER_PREFIX + recordFilterDisplay.getParameterName( );
372                     urlRedirectionDetails.addParameter( strFilterFullName, strFilterValue );
373                 }
374             }
375         }
376 
377         // Add the search text
378         if ( !StringUtils.isEmpty( _strSearchedText ) )
379         {
380             urlRedirectionDetails.addParameter( DirectoryMultiviewConstants.PARAMETER_SEARCHED_TEXT, _strSearchedText );
381         }
382 
383         // Add the selected panel technical code
384         urlRedirectionDetails.addParameter( DirectoryMultiviewConstants.PARAMETER_SELECTED_PANEL, _strSelectedPanelTechnicalCode );
385 
386         // Add sort filter data to the url
387         addFilterSortConfigToUrl( urlRedirectionDetails );
388 
389         return urlRedirectionDetails.getUrl( );
390     }
391 
392     /**
393      * Add the information for rebuild the used sort
394      * 
395      * @param urlRedirectionDetails
396      *            The UrlItem which represent the url to use for redirect to the records details page
397      */
398     private void addFilterSortConfigToUrl( UrlItem urlRedirectionDetails )
399     {
400         if ( _directoryRecordItemComparatorConfig != null )
401         {
402             String strSortPosition = Integer.toString( _directoryRecordItemComparatorConfig.getColumnToSortPosition( ) );
403             String strAttributeName = _directoryRecordItemComparatorConfig.getSortAttributeName( );
404             String strAscSort = String.valueOf( _directoryRecordItemComparatorConfig.isAscSort( ) );
405 
406             urlRedirectionDetails.addParameter( DirectoryMultiviewConstants.PARAMETER_SORT_COLUMN_POSITION, strSortPosition );
407             urlRedirectionDetails.addParameter( DirectoryMultiviewConstants.PARAMETER_SORT_ATTRIBUTE_NAME, strAttributeName );
408             urlRedirectionDetails.addParameter( DirectoryMultiviewConstants.PARAMETER_SORT_ASC_VALUE, strAscSort );
409         }
410     }
411 
412     /**
413      * Return the base url of the controller for the view which display the list of records
414      * 
415      * @return the base url of the controller for the view which display the list of records
416      */
417     protected static String getMultiviewBaseViewUrl( )
418     {
419         return CONTROLLER_JSP_NAME + "?view=" + VIEW_MULTIVIEW;
420     }
421 }