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.io.UnsupportedEncodingException;
37  import java.net.URLEncoder;
38  import java.nio.charset.StandardCharsets;
39  import java.util.Collections;
40  import java.util.Enumeration;
41  import java.util.HashMap;
42  import java.util.LinkedHashMap;
43  import java.util.LinkedHashSet;
44  import java.util.List;
45  import java.util.Locale;
46  import java.util.Map;
47  import java.util.Map.Entry;
48  import java.util.Set;
49  import java.util.stream.Collectors;
50  
51  import javax.servlet.http.HttpServletRequest;
52  
53  import org.apache.commons.collections.CollectionUtils;
54  import org.apache.commons.collections.MapUtils;
55  import org.apache.commons.lang3.StringUtils;
56  import org.apache.commons.lang3.math.NumberUtils;
57  
58  import fr.paris.lutece.plugins.directory.business.Directory;
59  import fr.paris.lutece.plugins.directory.business.DirectoryAction;
60  import fr.paris.lutece.plugins.directory.business.DirectoryActionHome;
61  import fr.paris.lutece.plugins.directory.business.DirectoryHome;
62  import fr.paris.lutece.plugins.directory.business.IEntry;
63  import fr.paris.lutece.plugins.directory.business.Record;
64  import fr.paris.lutece.plugins.directory.business.RecordHome;
65  import fr.paris.lutece.plugins.directory.modules.multiview.service.DirectoryMultiviewPlugin;
66  import fr.paris.lutece.plugins.directory.modules.multiview.service.IDirectoryMultiviewAuthorizationService;
67  import fr.paris.lutece.plugins.directory.modules.multiview.util.DirectoryMultiviewConstants;
68  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.view.IRecordViewModelProcessor;
69  import fr.paris.lutece.plugins.directory.modules.multiview.web.record.view.RecordViewModelProcessorFactory;
70  import fr.paris.lutece.plugins.directory.service.DirectoryResourceIdService;
71  import fr.paris.lutece.plugins.directory.service.DirectoryService;
72  import fr.paris.lutece.plugins.directory.service.record.IRecordService;
73  import fr.paris.lutece.plugins.directory.service.record.RecordService;
74  import fr.paris.lutece.plugins.directory.utils.DirectoryUtils;
75  import fr.paris.lutece.portal.business.user.AdminUser;
76  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
77  import fr.paris.lutece.portal.service.plugin.Plugin;
78  import fr.paris.lutece.portal.service.rbac.RBACService;
79  import fr.paris.lutece.portal.service.spring.SpringContextService;
80  import fr.paris.lutece.portal.service.util.AppException;
81  import fr.paris.lutece.portal.service.util.AppLogService;
82  import fr.paris.lutece.portal.service.util.AppPropertiesService;
83  import fr.paris.lutece.portal.service.workflow.WorkflowService;
84  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
85  import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
86  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
87  import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
88  import fr.paris.lutece.util.ReferenceItem;
89  import fr.paris.lutece.util.ReferenceList;
90  import fr.paris.lutece.util.url.UrlItem;
91  
92  /**
93   * Controller page for the details of the record and the managing of the actions of the workflow
94   */
95  @Controller( controllerJsp = "ManageDirectoryRecordDetails.jsp", controllerPath = "jsp/admin/plugins/directory/modules/multiview/", right = "DIRECTORY_MULTIVIEW" )
96  public class MultiviewRecordDetailsJspBean extends AbstractJspBean
97  {
98      // Public properties
99      private static final String CONTROLLER_JSP_NAME_WITH_PATH = "jsp/admin/plugins/directory/modules/multiview/ManageDirectoryRecordDetails.jsp";
100 
101     // Generated serial UID
102     private static final long serialVersionUID = -9068496856640551669L;
103 
104     // Templates
105     private static final String TEMPLATE_VIEW_DIRECTORY_RECORD = "admin/plugins/directory/modules/multiview/view_directory_record.html";
106     private static final String TEMPLATE_RECORD_HISTORY = "admin/plugins/directory/modules/multiview/record_history.html";
107     private static final String TEMPLATE_TASK_FORM = "admin/plugins/directory/modules/multiview/task_form_workflow.html";
108 
109     // Views
110     private static final String VIEW_RECORD_DETAILS = "view_record_details";
111     private static final String VIEW_TASKS_FORM = "view_tasksForm";
112 
113     // Actions
114     private static final String ACTION_PROCESS_ACTION = "doProcessAction";
115     private static final String ACTION_SAVE_TASK_FORM = "doSaveTaskForm";
116     private static final String ACTION_CANCEL_TASK_FORM = "doCancelTaskForm";
117 
118     // Parameters
119     private static final String PARAMETER_ID_DIRECTORY_RECORD = "id_directory_record";
120     private static final String PARAMETER_ID_ACTION = "id_action";
121     private static final String PARAMETER_BACK_FROM_ACTION = "back_form_action";
122 
123     // Marks
124     private static final String MARK_LOCALE = "locale";
125     private static final String MARK_DIRECTORY = "directory";
126     private static final String MARK_ID_DIRECTORY_RECORD = "id_directory_record";
127     private static final String MARK_ID_ACTION = "id_action";
128     private static final String MARK_TASK_FORM = "tasks_form";
129     private static final String MARK_ENTRY_LIST = "entry_list";
130     private static final String MARK_MAP_ID_ENTRY_LIST_RECORD_FIELD = "map_id_entry_list_record_field";
131     private static final String MARK_ID_ENTRY_TYPE_IMAGE = "id_entry_type_image";
132     private static final String MARK_ID_ENTRY_TYPE_MYLUTECE_USER = "id_entry_type_mylutece_user";
133     private static final String MARK_ID_ENTRY_TYPE_GEOLOCATION = "id_entry_type_geolocation";
134     private static final String MARK_SHOW_DATE_CREATION_RECORD = "show_date_creation_record";
135     private static final String MARK_SHOW_DATE_MODIFICATION_RECORD = "show_date_modification_record";
136     private static final String MARK_RECORD = "record";
137     private static final String MARK_RESOURCE_ACTIONS = "resource_actions";
138     private static final String MARK_RESOURCE_HISTORY = "resource_history";
139     private static final String MARK_HISTORY_WORKFLOW_ENABLED = "history_workflow";
140     private static final String MARK_PERMISSION_VISUALISATION_MYLUTECE_USER = "permission_visualisation_mylutece_user";
141     private static final String MARK_LIST_FILTER_VALUES = "list_filter_values";
142 
143     // Properties
144     private static final String PROPERTY_ENTRY_TYPE_IMAGE = "directory.resource_rss.entry_type_image";
145     private static final String PROPERTY_ENTRY_TYPE_MYLUTECE_USER = "directory.entry_type.mylutece_user";
146     private static final String PROPERTY_ENTRY_TYPE_GEOLOCATION = "directory.entry_type.geolocation";
147 
148     // Messages
149     private static final String MESSAGE_ACCESS_DENIED = "Acces denied";
150     private static final String MESSAGE_MULTIVIEW_TITLE = "module.directory.multiview.pageTitle";
151 
152     // Variables
153     private Map<String, String> _mapFilterValues = new LinkedHashMap<>( );
154     private final transient IRecordService _recordService = SpringContextService.getBean( RecordService.BEAN_SERVICE );
155     private final transient IDirectoryMultiviewAuthorizationService _directoryMultiviewAuthorizationService = SpringContextService
156             .getBean( IDirectoryMultiviewAuthorizationService.BEAN_NAME );
157 
158     /**
159      * Return the page with the details of a record
160      * 
161      * @param request
162      *            The request used the retrieve the values of the selected parameters
163      * @return the page with the details of the record
164      * @throws AccessDeniedException
165      *             if the user is not authorize to access the details of the record
166      */
167     @View( value = VIEW_RECORD_DETAILS, defaultView = true )
168     public String getRecordDetails( HttpServletRequest request ) throws AccessDeniedException
169     {
170         AdminUser adminUser = getUser( );
171         Plugin pluginDirectoryMultiview = DirectoryMultiviewPlugin.getPlugin( );
172 
173         int nIdRecord = NumberUtils.toInt( request.getParameter( PARAMETER_ID_DIRECTORY_RECORD ), NumberUtils.INTEGER_MINUS_ONE );
174         Record record = _recordService.findByPrimaryKey( nIdRecord, pluginDirectoryMultiview );
175 
176         boolean bRBACAuthorization = RBACService.isAuthorized( Directory.RESOURCE_TYPE, String.valueOf( record.getDirectory( ).getIdDirectory( ) ),
177                 DirectoryResourceIdService.PERMISSION_VISUALISATION_RECORD, adminUser );
178         boolean bAuthorizedRecord = _directoryMultiviewAuthorizationService.isUserAuthorizedOnRecord( request, nIdRecord );
179 
180         if ( record == null || record.getDirectory( ) == null || !bRBACAuthorization || !bAuthorizedRecord )
181         {
182             throw new AccessDeniedException( MESSAGE_ACCESS_DENIED );
183         }
184 
185         // Build the base model for the page of the details of a Record
186         Map<String, Object> model = buildRecordDetailsModel( request, record );
187 
188         // Build the model of all ModelProcessors
189         RecordViewModelProcessorFactory recordViewModelProcessorFactory = new RecordViewModelProcessorFactory( );
190         List<IRecordViewModelProcessor> listRecordViewModelProcesor = recordViewModelProcessorFactory.buildRecordViewModelProcessorList( );
191         if ( !CollectionUtils.isEmpty( listRecordViewModelProcesor ) )
192         {
193             Locale locale = getLocale( );
194             for ( IRecordViewModelProcessor recordViewModelProcessor : listRecordViewModelProcesor )
195             {
196                 recordViewModelProcessor.populateModel( request, model, nIdRecord, locale );
197             }
198         }
199 
200         // Fill the map which store the values of all filters and search previously selected if we are not coming from an action
201         if ( request.getParameter( PARAMETER_BACK_FROM_ACTION ) == null )
202         {
203             _mapFilterValues = fillFilterMapValues( request );
204         }
205         populateModelWithFilterValues( _mapFilterValues, model );
206 
207         return getPage( MESSAGE_MULTIVIEW_TITLE, TEMPLATE_VIEW_DIRECTORY_RECORD, model );
208     }
209 
210     /**
211      * Build the model of the page which display the details of a Record
212      * 
213      * @param request
214      *            The request on which the parameters must be retrieve
215      * @param record
216      *            The record on which the model must be built
217      * @return the model associate for the details of the given record
218      */
219     private Map<String, Object> buildRecordDetailsModel( HttpServletRequest request, Record record )
220     {
221         AdminUser adminUser = getUser( );
222         Locale locale = getLocale( );
223         Plugin pluginDirectoryMultiview = DirectoryMultiviewPlugin.getPlugin( );
224 
225         Directory directory = DirectoryHome.findByPrimaryKey( record.getDirectory( ).getIdDirectory( ), pluginDirectoryMultiview );
226         List<IEntry> listEntry = DirectoryUtils.getFormEntries( directory.getIdDirectory( ), pluginDirectoryMultiview, adminUser );
227 
228         List<DirectoryAction> listActionsForDirectoryEnable = DirectoryActionHome.selectActionsRecordByFormState( Directory.STATE_ENABLE,
229                 pluginDirectoryMultiview, locale );
230         List<DirectoryAction> listActionsForDirectoryDisable = DirectoryActionHome.selectActionsRecordByFormState( Directory.STATE_DISABLE,
231                 pluginDirectoryMultiview, locale );
232 
233         listActionsForDirectoryEnable = (List<DirectoryAction>) RBACService
234                 .getAuthorizedActionsCollection( listActionsForDirectoryEnable, directory, adminUser );
235         listActionsForDirectoryDisable = (List<DirectoryAction>) RBACService.getAuthorizedActionsCollection( listActionsForDirectoryDisable, directory,
236                 adminUser );
237         int nIdRecord = record.getIdRecord( );
238 
239         Map<String, Object> mapRecordDetailsModel = new HashMap<>( );
240         mapRecordDetailsModel.put( MARK_RECORD, record );
241         mapRecordDetailsModel.put( MARK_ENTRY_LIST, listEntry );
242         mapRecordDetailsModel.put( MARK_DIRECTORY, directory );
243         mapRecordDetailsModel.put( MARK_LOCALE, locale );
244         mapRecordDetailsModel.put( MARK_ID_ENTRY_TYPE_GEOLOCATION, AppPropertiesService.getPropertyInt( PROPERTY_ENTRY_TYPE_GEOLOCATION, 16 ) );
245         mapRecordDetailsModel.put( MARK_ID_ENTRY_TYPE_IMAGE, AppPropertiesService.getPropertyInt( PROPERTY_ENTRY_TYPE_IMAGE, 10 ) );
246         mapRecordDetailsModel.put( MARK_ID_ENTRY_TYPE_MYLUTECE_USER, AppPropertiesService.getPropertyInt( PROPERTY_ENTRY_TYPE_MYLUTECE_USER, 19 ) );
247         mapRecordDetailsModel.put( MARK_PERMISSION_VISUALISATION_MYLUTECE_USER, RBACService.isAuthorized( Directory.RESOURCE_TYPE,
248                 Integer.toString( directory.getIdDirectory( ) ), DirectoryResourceIdService.PERMISSION_VISUALISATION_MYLUTECE_USER, adminUser ) );
249         mapRecordDetailsModel.put( MARK_MAP_ID_ENTRY_LIST_RECORD_FIELD,
250                 DirectoryUtils.getMapIdEntryListRecordField( listEntry, nIdRecord, pluginDirectoryMultiview ) );
251 
252         mapRecordDetailsModel.put( MARK_SHOW_DATE_CREATION_RECORD, directory.isDateShownInResultRecord( ) );
253         mapRecordDetailsModel.put( MARK_SHOW_DATE_MODIFICATION_RECORD, directory.isDateModificationShownInResultRecord( ) );
254 
255         // Get asynchronous file names
256         boolean bGetFileName = true;
257         int nIdWorkflow = directory.getIdWorkflow( );
258         WorkflowService workflowService = WorkflowService.getInstance( );
259         boolean bHistoryEnabled = workflowService.isAvailable( ) && ( nIdWorkflow != DirectoryUtils.CONSTANT_ID_NULL );
260 
261         mapRecordDetailsModel.put(
262                 MARK_RESOURCE_ACTIONS,
263                 DirectoryService.getInstance( ).getResourceAction( record, directory, listEntry, adminUser, listActionsForDirectoryEnable,
264                         listActionsForDirectoryDisable, bGetFileName, pluginDirectoryMultiview ) );
265         mapRecordDetailsModel.put( MARK_HISTORY_WORKFLOW_ENABLED, bHistoryEnabled );
266         mapRecordDetailsModel.put( MARK_RESOURCE_HISTORY, workflowService.getDisplayDocumentHistory( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE,
267                 directory.getIdWorkflow( ), request, locale, mapRecordDetailsModel, TEMPLATE_RECORD_HISTORY ) );
268 
269         return mapRecordDetailsModel;
270     }
271 
272     /**
273      * Populate the given model with the data associated to the filters from the request
274      * 
275      * @param mapFilterNameValues
276      *            The map which contains the name of all parameters used to filter and their values
277      * @param model
278      *            The given model to populate
279      */
280     private void populateModelWithFilterValues( Map<String, String> mapFilterNameValues, Map<String, Object> model )
281     {
282         if ( !MapUtils.isEmpty( mapFilterNameValues ) )
283         {
284             ReferenceList referenceListFilterValues = new ReferenceList( );
285 
286             for ( Entry<String, String> entryFilterNameValue : mapFilterNameValues.entrySet( ) )
287             {
288                 ReferenceItem referenceItem = new ReferenceItem( );
289                 referenceItem.setCode( entryFilterNameValue.getKey( ) );
290                 referenceItem.setName( entryFilterNameValue.getValue( ) );
291 
292                 referenceListFilterValues.add( referenceItem );
293             }
294 
295             model.put( MARK_LIST_FILTER_VALUES, referenceListFilterValues );
296         }
297     }
298 
299     /**
300      * Fill the map which contains the values of all filters with the data of the request
301      * 
302      * @param request
303      *            The request used to retrieve the values of the parameters of the filters
304      * @return the map which associate for each filter parameter its value
305      */
306     private Map<String, String> fillFilterMapValues( HttpServletRequest request )
307     {
308         Map<String, String> mapFilterValues = new LinkedHashMap<>( );
309 
310         Set<String> setFilterParameterName = new LinkedHashSet<>( );
311         Enumeration<String> enumerationParameterName = request.getParameterNames( );
312 
313         if ( enumerationParameterName != null )
314         {
315             List<String> listFilterParameterName = Collections.list( enumerationParameterName );
316             setFilterParameterName = listFilterParameterName.stream( )
317                     .filter( strParameterName -> strParameterName.startsWith( DirectoryMultiviewConstants.PARAMETER_URL_FILTER_PREFIX ) )
318                     .collect( Collectors.toSet( ) );
319         }
320 
321         if ( !CollectionUtils.isEmpty( setFilterParameterName ) )
322         {
323             for ( String strFilterParameterName : setFilterParameterName )
324             {
325                 mapFilterValues.put( strFilterParameterName.split( DirectoryMultiviewConstants.PARAMETER_URL_FILTER_PREFIX ) [1],
326                         request.getParameter( strFilterParameterName ) );
327             }
328         }
329 
330         String strParameterSearchedText = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SEARCHED_TEXT );
331         if ( !StringUtils.isBlank( strParameterSearchedText ) )
332         {
333             mapFilterValues.put( DirectoryMultiviewConstants.PARAMETER_SEARCHED_TEXT, strParameterSearchedText );
334         }
335 
336         String strSelectedTechnicalCode = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SELECTED_PANEL );
337         if ( !StringUtils.isBlank( strSelectedTechnicalCode ) )
338         {
339             mapFilterValues.put( DirectoryMultiviewConstants.PARAMETER_CURRENT_SELECTED_PANEL, strSelectedTechnicalCode );
340         }
341 
342         if ( request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_COLUMN_POSITION ) != null )
343         {
344             addSortConfigParameterValues( request );
345         }
346 
347         return mapFilterValues;
348     }
349 
350     /**
351      * Fill the map which contains the values of all filters with informations of the sort to use
352      * 
353      * @param request
354      *            The request to use to retrieve the value of the sort
355      */
356     private void addSortConfigParameterValues( HttpServletRequest request )
357     {
358         String strPositionToSort = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_COLUMN_POSITION );
359         String strAttributeName = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_ATTRIBUTE_NAME );
360         String strAscSort = request.getParameter( DirectoryMultiviewConstants.PARAMETER_SORT_ASC_VALUE );
361 
362         _mapFilterValues.put( DirectoryMultiviewConstants.PARAMETER_SORT_COLUMN_POSITION, strPositionToSort );
363         _mapFilterValues.put( DirectoryMultiviewConstants.PARAMETER_SORT_ATTRIBUTE_NAME, strAttributeName );
364         _mapFilterValues.put( DirectoryMultiviewConstants.PARAMETER_SORT_ASC_VALUE, strAscSort );
365     }
366 
367     /**
368      * Process workflow action on record
369      * 
370      * @param request
371      *            the HttpServletRequest
372      * @return the task form if exists, or the manage record view otherwise.
373      */
374     @Action( value = ACTION_PROCESS_ACTION )
375     public String doProcessWorkflowAction( HttpServletRequest request )
376     {
377         // Get parameters from request
378         int nIdRecord = NumberUtils.toInt( request.getParameter( PARAMETER_ID_DIRECTORY_RECORD ), NumberUtils.INTEGER_MINUS_ONE );
379         int nIdAction = NumberUtils.toInt( request.getParameter( PARAMETER_ID_ACTION ), NumberUtils.INTEGER_MINUS_ONE );
380 
381         Locale locale = getLocale( );
382         WorkflowService workflowService = WorkflowService.getInstance( );
383         if ( workflowService.isDisplayTasksForm( nIdAction, locale ) )
384         {
385             Map<String, String> model = new LinkedHashMap<>( );
386             model.put( PARAMETER_ID_DIRECTORY_RECORD, String.valueOf( nIdRecord ) );
387             model.put( PARAMETER_ID_ACTION, String.valueOf( nIdAction ) );
388 
389             return redirect( request, VIEW_TASKS_FORM, model );
390         }
391 
392         Plugin pluginDirectoryMultiview = getPlugin( );
393         Record record = _recordService.findByPrimaryKey( nIdRecord, pluginDirectoryMultiview );
394 
395         try
396         {
397             if ( record != null )
398             {
399                 boolean bIsAutomaticAction = Boolean.FALSE;
400                 int nIdDirectory = record.getDirectory( ).getIdDirectory( );
401                 workflowService.doProcessAction( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdAction, nIdDirectory, request, locale, bIsAutomaticAction );
402 
403                 // Update record modification date
404                 _recordService.update( record, pluginDirectoryMultiview );
405             }
406             else
407             {
408                 AppLogService.error( "Error processing action for id record '" + nIdRecord + "' - cause : the record doesn't exist " );
409             }
410         }
411         catch( AppException e )
412         {
413             AppLogService.error( "Error processing action for id record '" + nIdRecord + "' - cause : " + e.getMessage( ), e );
414         }
415 
416         // Redirect to the correct view
417         return manageRedirection( request );
418     }
419 
420     /**
421      * Returns the task form associate to the workflow action
422      *
423      * @param request
424      *            The Http request
425      * @return The HTML form the task form associate to the workflow action
426      */
427     @View( value = VIEW_TASKS_FORM )
428     public String getTaskForm( HttpServletRequest request )
429     {
430         int nIdRecord = NumberUtils.toInt( request.getParameter( PARAMETER_ID_DIRECTORY_RECORD ), NumberUtils.INTEGER_MINUS_ONE );
431         int nIdAction = NumberUtils.toInt( request.getParameter( PARAMETER_ID_ACTION ), NumberUtils.INTEGER_MINUS_ONE );
432 
433         if ( nIdAction == NumberUtils.INTEGER_MINUS_ONE || nIdRecord == NumberUtils.INTEGER_MINUS_ONE )
434         {
435             return redirectView( request, VIEW_RECORD_DETAILS );
436         }
437 
438         String strHtmlTasksForm = WorkflowService.getInstance( )
439                 .getDisplayTasksForm( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdAction, request, getLocale( ) );
440 
441         Map<String, Object> model = getModel( );
442         model.put( MARK_ID_DIRECTORY_RECORD, nIdRecord );
443         model.put( MARK_ID_ACTION, nIdAction );
444         model.put( MARK_TASK_FORM, strHtmlTasksForm );
445 
446         return getPage( MESSAGE_MULTIVIEW_TITLE, TEMPLATE_TASK_FORM, model );
447     }
448 
449     /**
450      * Process workflow action
451      *
452      * @param request
453      *            The Http request
454      * @return The Jsp URL of the process result
455      */
456     @Action( value = ACTION_SAVE_TASK_FORM )
457     public String doSaveTaskForm( HttpServletRequest request )
458     {
459         int nIdRecord = NumberUtils.toInt( request.getParameter( PARAMETER_ID_DIRECTORY_RECORD ), NumberUtils.INTEGER_MINUS_ONE );
460         int nIdAction = NumberUtils.toInt( request.getParameter( PARAMETER_ID_ACTION ), NumberUtils.INTEGER_MINUS_ONE );
461 
462         Record record = RecordHome.findByPrimaryKey( nIdRecord, getPlugin( ) );
463         int nIdDirectory = ( record != null && record.getDirectory( ) != null ) ? record.getDirectory( ).getIdDirectory( ) : NumberUtils.INTEGER_MINUS_ONE;
464 
465         WorkflowService workflowService = WorkflowService.getInstance( );
466         if ( workflowService.canProcessAction( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdAction, nIdDirectory, request, false ) )
467         {
468             try
469             {
470                 String strError = workflowService.doSaveTasksForm( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdAction, nIdDirectory, request, getLocale( ) );
471                 if ( strError != null )
472                 {
473                     addError( strError );
474                     return redirect( request, VIEW_TASKS_FORM, PARAMETER_ID_DIRECTORY_RECORD, nIdRecord, PARAMETER_ID_ACTION, nIdAction );
475                 }
476             }
477             catch( AppException e )
478             {
479                 AppLogService.error( "Error processing action for record " + nIdRecord, e );
480             }
481         }
482         else
483         {
484             return redirectView( request, VIEW_TASKS_FORM );
485         }
486 
487         return manageRedirection( request );
488     }
489 
490     /**
491      * Cancel an action of the workflow
492      * 
493      * @param request
494      *            The HttpServletRequest
495      * @return the Jsp URL to return
496      */
497     @Action( value = ACTION_CANCEL_TASK_FORM )
498     public String doCancelTaskForm( HttpServletRequest request )
499     {
500         Map<String, String> mapParameters = new LinkedHashMap<>( );
501         mapParameters.put( PARAMETER_ID_DIRECTORY_RECORD, request.getParameter( PARAMETER_ID_DIRECTORY_RECORD ) );
502         mapParameters.put( PARAMETER_BACK_FROM_ACTION, Boolean.TRUE.toString( ) );
503 
504         return redirect( request, VIEW_RECORD_DETAILS, mapParameters );
505     }
506 
507     /**
508      * Redirect to the appropriate view
509      * 
510      * @param request
511      *            The HttpServletRequest to retrieve data from
512      * @return redirect to the appropriate view
513      */
514     private String manageRedirection( HttpServletRequest request )
515     {
516         String strWorkflowActionRedirection = request.getParameter( DirectoryMultiviewConstants.PARAMETER_WORKFLOW_ACTION_REDIRECTION );
517         if ( StringUtils.isNotBlank( strWorkflowActionRedirection ) )
518         {
519             MultiviewDirectoryWorkflowRedirectionEnum workflowActionRedirectionEnum = MultiviewDirectoryWorkflowRedirectionEnum
520                     .getEnumNameByValue( strWorkflowActionRedirection );
521             switch( workflowActionRedirectionEnum )
522             {
523                 case LIST:
524                     return redirectToRecordList( request );
525                 case DETAILS:
526                     return redirectToRecordView( request );
527                 default:
528                     return defaultRedirection( request );
529             }
530         }
531         else
532         {
533             return defaultRedirection( request );
534         }
535     }
536 
537     /**
538      * Redirect to the page of the list of all records
539      * 
540      * @param request
541      *            The HttpServletRequest to retrieve data from
542      * @return redirect to the page with the list of all records
543      */
544     private String redirectToRecordList( HttpServletRequest request )
545     {
546         return redirect( request, buildRedirecUrlWithFilterValues( ) );
547     }
548 
549     /**
550      * Redirect to the page of a record
551      * 
552      * @param request
553      *            The HttpServletRequest to retrieve data from
554      * @return redirect to the page of the record
555      */
556     private String redirectToRecordView( HttpServletRequest request )
557     {
558         return defaultRedirection( request );
559     }
560 
561     /**
562      * Return to the default view which is the page of the record
563      * 
564      * @param request
565      *            The HttpServletRequest to retrieve data from
566      * @return redirect to the default view which is the page of the record
567      */
568     private String defaultRedirection( HttpServletRequest request )
569     {
570         try
571         {
572             int nIdRecord = Integer.parseInt( request.getParameter( PARAMETER_ID_DIRECTORY_RECORD ) );
573 
574             Map<String, String> mapParameters = new LinkedHashMap<>( );
575             mapParameters.put( PARAMETER_ID_DIRECTORY_RECORD, String.valueOf( nIdRecord ) );
576             mapParameters.put( PARAMETER_BACK_FROM_ACTION, Boolean.TRUE.toString( ) );
577 
578             return redirect( request, VIEW_RECORD_DETAILS, mapParameters );
579         }
580         catch( NumberFormatException exception )
581         {
582             AppLogService.error( "The given id directory record is not valid !" );
583 
584             return redirect( request, buildRedirecUrlWithFilterValues( ) );
585         }
586     }
587 
588     /**
589      * Build the url with the values of the filter selected on the list view
590      * 
591      * @return the url with the values of the filter selected on the list view
592      */
593     private String buildRedirecUrlWithFilterValues( )
594     {
595         UrlItem urlRedirectWithFilterValues = new UrlItem( MultiDirectoryJspBean.getMultiviewBaseViewUrl( ) );
596 
597         if ( !MapUtils.isEmpty( _mapFilterValues ) )
598         {
599             for ( Entry<String, String> entryFilterNameValue : _mapFilterValues.entrySet( ) )
600             {
601                 String strFilterName = entryFilterNameValue.getKey( );
602                 String strFilterValue = entryFilterNameValue.getValue( );
603                 try
604                 {
605                     strFilterValue = URLEncoder.encode( strFilterValue, StandardCharsets.UTF_8.name( ) );
606                 }
607                 catch( UnsupportedEncodingException exception )
608                 {
609                     AppLogService.debug( "Failed to encode url parameter value !" );
610                 }
611 
612                 urlRedirectWithFilterValues.addParameter( strFilterName, strFilterValue );
613             }
614         }
615 
616         return urlRedirectWithFilterValues.getUrl( );
617     }
618 
619     /**
620      * Return the default view base url for the MultiviewRecordDetailsJspBean
621      * 
622      * @return the default view base url for the MultiviewRecordDetailsJspBean
623      */
624     protected static String getMultiviewRecordDetailsBaseUrl( )
625     {
626         UrlItem urlRecordDetailsBase = new UrlItem( CONTROLLER_JSP_NAME_WITH_PATH );
627         urlRecordDetailsBase.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_RECORD_DETAILS );
628 
629         return urlRecordDetailsBase.getUrl( );
630     }
631 }