View Javadoc
1   /*
2    * Copyright (c) 2002-2022, 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.appointment.web;
35  
36  import java.io.IOException;
37  import java.time.LocalDate;
38  import java.time.LocalTime;
39  import java.util.ArrayList;
40  import java.util.HashMap;
41  import java.util.List;
42  import java.util.Map;
43  import java.util.StringJoiner;
44  import java.util.stream.Collectors;
45  
46  import javax.servlet.http.HttpServletRequest;
47  import org.apache.commons.collections.CollectionUtils;
48  import org.apache.commons.fileupload.FileItem;
49  import org.apache.commons.lang3.StringUtils;
50  import org.apache.commons.lang3.math.NumberUtils;
51  
52  import fr.paris.lutece.api.user.User;
53  import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
54  import fr.paris.lutece.plugins.appointment.business.form.Form;
55  import fr.paris.lutece.plugins.appointment.business.form.FormHome;
56  import fr.paris.lutece.plugins.appointment.business.message.FormMessage;
57  import fr.paris.lutece.plugins.appointment.business.message.FormMessageHome;
58  import fr.paris.lutece.plugins.appointment.business.slot.Slot;
59  import fr.paris.lutece.plugins.appointment.log.LogUtilities;
60  import fr.paris.lutece.plugins.appointment.service.AppointmentResourceIdService;
61  import fr.paris.lutece.plugins.appointment.service.AppointmentService;
62  import fr.paris.lutece.plugins.appointment.service.AppointmentUtilities;
63  import fr.paris.lutece.plugins.appointment.service.ClosingDayService;
64  import fr.paris.lutece.plugins.appointment.service.FormMessageService;
65  import fr.paris.lutece.plugins.appointment.service.FormService;
66  import fr.paris.lutece.plugins.appointment.service.SlotService;
67  import fr.paris.lutece.plugins.appointment.service.Utilities;
68  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
69  import fr.paris.lutece.portal.business.user.AdminUser;
70  import fr.paris.lutece.portal.service.accesscontrol.AccessControlService;
71  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
72  import fr.paris.lutece.portal.service.admin.AdminUserService;
73  import fr.paris.lutece.portal.service.i18n.I18nService;
74  import fr.paris.lutece.portal.service.image.ImageResource;
75  import fr.paris.lutece.portal.service.message.AdminMessage;
76  import fr.paris.lutece.portal.service.message.AdminMessageService;
77  import fr.paris.lutece.portal.service.rbac.RBACService;
78  import fr.paris.lutece.portal.service.util.AppLogService;
79  import fr.paris.lutece.portal.service.util.AppPathService;
80  import fr.paris.lutece.portal.service.util.AppPropertiesService;
81  import fr.paris.lutece.portal.service.workgroup.AdminWorkgroupService;
82  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
83  import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
84  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
85  import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
86  import fr.paris.lutece.portal.web.upload.MultipartHttpServletRequest;
87  import fr.paris.lutece.portal.web.util.LocalizedPaginator;
88  import fr.paris.lutece.util.ReferenceList;
89  import fr.paris.lutece.util.html.AbstractPaginator;
90  import fr.paris.lutece.util.url.UrlItem;
91  
92  /**
93   * This class provides the user interface to manage AppointmentForm features ( manage, create, modify, copy, remove )
94   * 
95   * @author L.Payen
96   * 
97   */
98  @Controller( controllerJsp = "ManageAppointmentForms.jsp", controllerPath = "jsp/admin/plugins/appointment/", right = AppointmentFormJspBean.RIGHT_MANAGEAPPOINTMENTFORM )
99  public class AppointmentFormJspBean extends AbstractAppointmentFormAndSlotJspBean
100 {
101 
102     /**
103      * Right to manage appointment forms
104      */
105     public static final String RIGHT_MANAGEAPPOINTMENTFORM = "APPOINTMENT_FORM_MANAGEMENT";
106     private static final long serialVersionUID = -615061018633136997L;
107 
108     // templates
109     private static final String TEMPLATE_MANAGE_APPOINTMENTFORMS = "/admin/plugins/appointment/appointmentform/manage_appointmentforms.html";
110     private static final String TEMPLATE_CREATE_APPOINTMENTFORM = "/admin/plugins/appointment/appointmentform/create_appointmentform.html";
111     private static final String TEMPLATE_MODIFY_APPOINTMENTFORM = "/admin/plugins/appointment/appointmentform/modify_appointmentform.html";
112     private static final String TEMPLATE_MODIFY_APPOINTMENTFORM_MESSAGES = "/admin/plugins/appointment/appointmentform/modify_appointmentform_messages.html";
113 
114     // Parameters
115     private static final String PARAMETER_ID_FORM = "id_form";
116     private static final String PARAMETER_BACK = "back";
117     private static final String PARAMETER_PAGE_INDEX = "page_index";
118     private static final String PARAMETER_FROM_DASHBOARD = "fromDashboard";
119     private static final String PARAMETER_ICON_RESSOURCE = "image_resource";
120     private static final String PARAMETER_DELETE_ICON = "deleteIcon";
121     private static final String PARAMETER_GEOLOC_ADDRESS = "geoloc_address";
122     private static final String PARAMETER_GEOLOC_LATITUDE = "geoloc_latitude";
123     private static final String PARAMETER_GEOLOC_LONGITUDE = "geoloc_longitude";
124     private static final String PARAMETER_ID_ACCESS_CONTROL = "id_accesscontrol";
125 
126     // Properties for page titles
127     private static final String PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTFORMS = "appointment.manage.appointmentforms.title";
128     private static final String PROPERTY_PAGE_TITLE_GENERAL_SETTINGS = "appointment.modifyAppointmentForm.titleAlterablesParameters";
129     private static final String PROPERTY_PAGE_TITLE_CREATE_APPOINTMENTFORM = "appointment.manage.appointmentforms.title";
130     private static final String PROPERTY_PAGE_TITLE_MODIFY_APPOINTMENTFORM_MESSAGES = "appointment.modifyAppointmentFormMessages.pageTitle";
131 
132     // Markers
133     private static final String MARK_WEBAPP_URL = "webapp_url";
134     private static final String MARK_APPOINTMENTFORM_LIST = "appointmentform_list";
135     private static final String MARK_PAGINATOR = "paginator";
136     private static final String MARK_NB_ITEMS_PER_PAGE = "nb_items_per_page";
137     private static final String MARK_FORM_MESSAGE = "formMessage";
138     private static final String MARK_NULL = "NULL";
139     private static final String MARK_FALSE = "false";
140     private static final String MARK_LOCALE_TINY = "locale";
141     private static final String MARK_FILE_CLOSING_DAYS = "fileClosingDays";
142     private static final String MARK_PERMISSION_CREATE = "permission_create";
143     private static final String MARK_BASE_URL = "baseUrl";
144     private static final String MARK_ACCESSCONTROL_REF_LIST = "accesscontrol_list";
145     private static final String MARK_ACCESSCONTROL_ID = "accesscontrol_id";
146 
147     // Jsp
148     private static final String JSP_MANAGE_APPOINTMENTFORMS = "jsp/admin/plugins/appointment/ManageAppointmentForms.jsp";
149 
150     // Properties
151     private static final String MESSAGE_CONFIRM_REMOVE_APPOINTMENTFORM = "appointment.message.confirmRemoveAppointmentForm";
152     public static final String PROPERTY_DEFAULT_LIST_APPOINTMENTFORM_PER_PAGE = "appointment.listAppointmentForms.itemsPerPage";
153     private static final String VALIDATION_ATTRIBUTES_PREFIX = "appointment.model.entity.appointmentform.attribute.";
154 
155     private static final String PROPERTY_COPY_OF_FORM = "appointment.manageAppointmentForms.Copy";
156     private static final String MESSAGE_ERROR_EMPTY_FILE = "appointment.message.error.closingDayErrorImport";
157     private static final String MESSAGE_ERROR_OPEN_SLOTS = "appointment.message.error.openSlots";
158     private static final String MESSAGE_INFO_IMPORTED_CLOSING_DAYS = "appointment.info.appointmentform.closingDayImport";
159     private static final String MESSAGE_ERROR_CANT_REMOVE_FORM = "appointment.message.cantRemove.form";
160     private static final String MESSAGE_ERROR_CANT_REMOVE_ACTIVE_FORM = "appointment.message.cantRemove.activate.form";
161 
162     // Views
163     private static final String VIEW_MANAGE_APPOINTMENTFORMS = "manageAppointmentForms";
164     private static final String VIEW_CREATE_APPOINTMENTFORM = "createAppointmentForm";
165     private static final String VIEW_MODIFY_APPOINTMENTFORM = "modifyAppointmentForm";
166     private static final String VIEW_MODIFY_FORM_MESSAGES = "modifyAppointmentFormMessages";
167     private static final String VIEW_PERMISSIONS_FORM = "permissions";
168 
169     // Actions
170     private static final String ACTION_CREATE_APPOINTMENTFORM = "createAppointmentForm";
171     private static final String ACTION_MODIFY_APPOINTMENTFORM = "modifyAppointmentForm";
172     private static final String ACTION_REMOVE_APPOINTMENTFORM = "removeAppointmentForm";
173     private static final String ACTION_CONFIRM_REMOVE_APPOINTMENTFORM = "confirmRemoveAppointmentForm";
174     private static final String ACTION_DO_CHANGE_FORM_ACTIVATION = "doChangeFormActivation";
175     private static final String ACTION_DO_MODIFY_FORM_MESSAGES = "doModifyAppointmentFormMessages";
176     private static final String ACTION_DO_COPY_FORM = "doCopyAppointmentForm";
177 
178     // Infos
179     private static final String INFO_APPOINTMENTFORM_CREATED = "appointment.info.appointmentform.created";
180     private static final String INFO_APPOINTMENTFORM_UPDATED = "appointment.info.appointmentform.updated";
181     private static final String INFO_APPOINTMENTFORM_REMOVED = "appointment.info.appointmentform.removed";
182     private static final String INFO_APPOINTMENTFORM_MESSAGES_MODIFIED = "appointment.info.appointmentFormMessages.updated";
183     private static final String ERROR_APPOINTMENTFORM_ENDING_VALIDITY_DATE_BEFORE_NOW = "appointment.error.appointmentform.endingValidityDateBeforeNow";
184 
185     private static final String DEFAULT_CURRENT_PAGE = "1";
186 
187     // Session variable to store working values
188     private int _nDefaultItemsPerPage;
189     private AppointmentFormDTO _appointmentFormDTO;
190     private String _strCurrentPageIndex;
191     private int _nItemsPerPage;
192 
193     /**
194      * Default constructor
195      */
196     public AppointmentFormJspBean( )
197     {
198         _nDefaultItemsPerPage = AppPropertiesService.getPropertyInt( PROPERTY_DEFAULT_LIST_APPOINTMENTFORM_PER_PAGE, 50 );
199     }
200 
201     /**
202      * Get the page to manage appointment forms
203      * 
204      * @param request
205      *            the request
206      * @return The HTML content to display
207      */
208     @View( value = VIEW_MANAGE_APPOINTMENTFORMS, defaultView = true )
209     public String getManageAppointmentForms( HttpServletRequest request )
210     {
211         AdminUser adminUser = getUser( );
212         _appointmentFormDTO = null;
213         _strCurrentPageIndex = AbstractPaginator.getPageIndex( request, AbstractPaginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex );
214         if ( _strCurrentPageIndex == null )
215         {
216             _strCurrentPageIndex = DEFAULT_CURRENT_PAGE;
217         }
218         _nItemsPerPage = AbstractPaginator.getItemsPerPage( request, AbstractPaginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage, _nDefaultItemsPerPage );
219 
220         UrlItem url = new UrlItem( JSP_MANAGE_APPOINTMENTFORMS );
221         String strUrl = url.getUrl( );
222         List<AppointmentFormDTO> listAppointmentForm = FormService.buildAllAppointmentFormLight( );
223         listAppointmentForm = (List<AppointmentFormDTO>) AdminWorkgroupService.getAuthorizedCollection( listAppointmentForm, (User) adminUser );
224         listAppointmentForm = listAppointmentForm.stream( ).sorted( ( a1, a2 ) -> a1.getTitle( ).compareTo( a2.getTitle( ) ) ).collect( Collectors.toList( ) );
225         LocalizedPaginator<AppointmentFormDTO> paginator = new LocalizedPaginator<>( listAppointmentForm, _nItemsPerPage, strUrl, PARAMETER_PAGE_INDEX,
226                 _strCurrentPageIndex, getLocale( ) );
227         AdminUser user = AdminUserService.getAdminUser( request );
228         Map<String, Object> model = getModel( );
229         model.put( MARK_NB_ITEMS_PER_PAGE, Integer.toString( _nItemsPerPage ) );
230         model.put( MARK_PAGINATOR, paginator );
231         model.put( MARK_BASE_URL, AppPathService.getProdUrl( request ) );
232         model.put( MARK_APPOINTMENTFORM_LIST, RBACService.getAuthorizedCollection( paginator.getPageItems( ), AppointmentResourceIdService.PERMISSION_VIEW_FORM,
233                 (User) AdminUserService.getAdminUser( request ) ) );
234         model.put( VIEW_PERMISSIONS_FORM, AppointmentUtilities.getPermissions( paginator.getPageItems( ), user ) );
235         model.put( MARK_PERMISSION_CREATE, String.valueOf(
236                 RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE_CREATE, "0", AppointmentResourceIdService.PERMISSION_CREATE_FORM, (User) user ) ) );
237         return getPage( PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTFORMS, TEMPLATE_MANAGE_APPOINTMENTFORMS, model );
238     }
239 
240     /**
241      * Returns the form to create an appointment form
242      *
243      * @param request
244      *            The HTTP request
245      * @return the HTML code of the appointment form
246      * @throws AccessDeniedException
247      *             If the user is not authorized to create appointment forms
248      */
249     @View( VIEW_CREATE_APPOINTMENTFORM )
250     public String getCreateAppointmentForm( HttpServletRequest request ) throws AccessDeniedException
251     {
252         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE_CREATE, "0", AppointmentResourceIdService.PERMISSION_CREATE_FORM,
253                 (User) AdminUserService.getAdminUser( request ) ) )
254         {
255             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_CREATE_FORM );
256         }
257         if ( _appointmentFormDTO == null || _appointmentFormDTO.getIdForm( ) != 0 )
258         {
259             _appointmentFormDTO = new AppointmentFormDTO( );
260         }
261 
262         Map<String, Object> model = getModel( );
263 
264         // Load all available Access Controllers
265         if ( AccessControlService.getInstance( ).isAvailable( ) )
266         {
267         	AdminUser adminUser = getUser( );
268         	ReferenceList referenceList = AccessControlService.getInstance( ).getAccessControlsEnabled( adminUser, getLocale( ) );
269         	model.put( MARK_ACCESSCONTROL_REF_LIST, referenceList );
270         }
271 
272         addElementsToModel( _appointmentFormDTO, getUser( ), getLocale( ), model );
273         return getPage( PROPERTY_PAGE_TITLE_CREATE_APPOINTMENTFORM, TEMPLATE_CREATE_APPOINTMENTFORM, model );
274     }
275 
276     /**
277      * Process the data capture form of a new appointment form
278      * 
279      * @param request
280      *            The HTTP Request
281      * @return The JSP URL of the process result
282      * @throws AccessDeniedException
283      *             If the user is not authorized to create appointment forms
284      */
285     @Action( ACTION_CREATE_APPOINTMENTFORM )
286     public String doCreateAppointmentForm( HttpServletRequest request ) throws AccessDeniedException
287     {
288         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE_CREATE, "0", AppointmentResourceIdService.PERMISSION_CREATE_FORM,
289                 (User) AdminUserService.getAdminUser( request ) ) )
290         {
291             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_CREATE_FORM );
292         }
293         if ( _appointmentFormDTO == null )
294         {
295             _appointmentFormDTO = new AppointmentFormDTO( );
296         }
297         populate( _appointmentFormDTO, request );
298         populateAddress( _appointmentFormDTO, request );
299         if ( !validateBean( _appointmentFormDTO, VALIDATION_ATTRIBUTES_PREFIX ) || !validateReservationRuleBean( request, VALIDATION_ATTRIBUTES_PREFIX )
300                 || !checkConstraints( _appointmentFormDTO ) )
301         {
302             return redirectView( request, VIEW_CREATE_APPOINTMENTFORM );
303         }
304         _appointmentFormDTO.setIcon( buildImageResource( (MultipartHttpServletRequest) request ) );
305         int nIdForm = FormService.createAppointmentForm( _appointmentFormDTO );
306 
307         // Set or remove (with '-1') the Access Controllers for the current form
308         if ( AccessControlService.getInstance( ).isAvailable( ) )
309         {
310         	int idAccessControl = NumberUtils.toInt( request.getParameter( PARAMETER_ID_ACCESS_CONTROL ), -1 );
311         	AccessControlService.getInstance( ).linkResourceToAccessControl( nIdForm, Form.RESOURCE_TYPE, idAccessControl );
312         }
313 
314         AppLogService.info( LogUtilities.buildLog( ACTION_CREATE_APPOINTMENTFORM, Integer.toString( nIdForm ), getUser( ) ) );
315         addInfo( INFO_APPOINTMENTFORM_CREATED, getLocale( ) );
316         return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
317     }
318 
319     /**
320      * Manages the removal form of a appointment form whose identifier is in the HTTP request
321      * 
322      * @param request
323      *            The HTTP request
324      * @return the HTML code to confirm
325      * @throws AccessDeniedException
326      *             If the user is not authorized to delete this appointment form
327      */
328     @Action( ACTION_CONFIRM_REMOVE_APPOINTMENTFORM )
329     public String getConfirmRemoveAppointmentForm( HttpServletRequest request ) throws AccessDeniedException
330     {
331         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
332         if ( StringUtils.isEmpty( strIdForm ) )
333         {
334             return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
335         }
336         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_DELETE_FORM,
337                 (User) AdminUserService.getAdminUser( request ) ) )
338         {
339             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_DELETE_FORM );
340         }
341         int nIdForm = Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) );
342         UrlItem url = new UrlItem( getActionUrl( ACTION_REMOVE_APPOINTMENTFORM ) );
343         url.addParameter( PARAMETER_ID_FORM, nIdForm );
344         String strMessageUrl = AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_REMOVE_APPOINTMENTFORM, url.getUrl( ),
345                 AdminMessage.TYPE_CONFIRMATION );
346         return redirect( request, strMessageUrl );
347     }
348 
349     /**
350      * Handles the removal form of an appointment form
351      * 
352      * @param request
353      *            The HTTP request
354      * @return the JSP URL to display the form to manage appointment forms
355      * @throws AccessDeniedException
356      *             If the user is not authorized to delete this appointment form
357      */
358     @Action( ACTION_REMOVE_APPOINTMENTFORM )
359     public String doRemoveAppointmentForm( HttpServletRequest request ) throws AccessDeniedException
360     {
361         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
362         if ( StringUtils.isEmpty( strIdForm ) )
363         {
364             return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
365         }
366         int nIdForm = Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) );
367         Form form = FormHome.findByPrimaryKey( nIdForm );
368 
369         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, request.getParameter( PARAMETER_ID_FORM ),
370                 AppointmentResourceIdService.PERMISSION_DELETE_FORM, (User) AdminUserService.getAdminUser( request ) ) )
371         {
372             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_DELETE_FORM );
373         }
374 
375         if ( form.getIsActive( ) )
376         {
377 
378             addError( MESSAGE_ERROR_CANT_REMOVE_ACTIVE_FORM, getLocale( ) );
379             return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
380         }
381         if ( CollectionUtils.isNotEmpty( AppointmentService.findListAppointmentByIdForm( nIdForm ) ) )
382         {
383             addError( MESSAGE_ERROR_CANT_REMOVE_FORM, getLocale( ) );
384             return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
385         }
386 
387         // Remove any Access Controller linked to this form
388         if ( AccessControlService.getInstance( ).isAvailable( ) )
389         {
390         	// The links between this form & the Access Controllers will be removed with the '-1' value
391         	AccessControlService.getInstance( ).linkResourceToAccessControl( nIdForm, Form.RESOURCE_TYPE, -1 );
392         }
393 
394         FormService.removeForm( nIdForm );
395         AppLogService.info( LogUtilities.buildLog( ACTION_REMOVE_APPOINTMENTFORM, strIdForm, getUser( ) ) );
396         addInfo( INFO_APPOINTMENTFORM_REMOVED, getLocale( ) );
397         return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
398     }
399 
400     /**
401      * Returns the form to update info about a appointment form
402      * 
403      * @param request
404      *            The HTTP request
405      * @return The HTML form to update info
406      * @throws AccessDeniedException
407      *             If the user is not authorized to modify this appointment form
408      */
409     @View( VIEW_MODIFY_APPOINTMENTFORM )
410     public String getModifyAppointmentForm( HttpServletRequest request ) throws AccessDeniedException
411     {
412         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
413         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_MODIFY_FORM,
414                 (User) AdminUserService.getAdminUser( request ) ) )
415         {
416             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_FORM );
417         }
418         int nIdForm = Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) );
419         if ( ( _appointmentFormDTO == null ) || ( nIdForm != _appointmentFormDTO.getIdForm( ) ) )
420         {
421         	_appointmentFormDTO = FormService.buildAppointmentForm( nIdForm, 0 );
422         }
423         Map<String, Object> model = getModel( );
424 
425         // Load all available Access Controllers
426         if ( AccessControlService.getInstance( ).isAvailable( ) )
427         {
428         	ReferenceList referenceList = AccessControlService.getInstance( ).getAccessControlsEnabled( getUser( ), getLocale( ) );
429         	model.put( MARK_ACCESSCONTROL_REF_LIST, referenceList );
430         	model.put( MARK_ACCESSCONTROL_ID,
431         			AccessControlService.getInstance( ).findAccessControlForResource( nIdForm, Form.RESOURCE_TYPE ) );
432         }
433 
434         addElementsToModel( _appointmentFormDTO, getUser( ), getLocale( ), model );
435         return getPage( PROPERTY_PAGE_TITLE_GENERAL_SETTINGS, TEMPLATE_MODIFY_APPOINTMENTFORM, model );
436     }
437 
438     /**
439      * Process the change form of a appointment form
440      * 
441      * @param request
442      *            The HTTP request
443      * @return The JSP URL of the process result
444      * @throws AccessDeniedException
445      *             If the user is not authorized to modify this appointment form
446      */
447     @Action( ACTION_MODIFY_APPOINTMENTFORM )
448     public String doModifyAppointmentForm( HttpServletRequest request ) throws AccessDeniedException
449     {
450         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
451         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_MODIFY_FORM,
452                 (User) AdminUserService.getAdminUser( request ) ) )
453         {
454             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_FORM );
455         }
456         int nIdForm = Integer.parseInt( strIdForm );
457         if ( ( _appointmentFormDTO == null ) || ( nIdForm != _appointmentFormDTO.getIdForm( ) ) )
458         {
459             _appointmentFormDTO = FormService.buildAppointmentFormLight( nIdForm );
460         }
461         populate( _appointmentFormDTO, request );
462         populateAddress( _appointmentFormDTO, request );
463         AppointmentFormDTO appointmentFormDb = FormService.buildAppointmentForm( nIdForm, 0 );
464         String strDeleteIcon = ( request.getParameter( PARAMETER_DELETE_ICON ) == null ) ? MARK_FALSE : request.getParameter( PARAMETER_DELETE_ICON );
465         MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
466         if ( Boolean.parseBoolean( strDeleteIcon ) && ( _appointmentFormDTO.getIcon( ).getImage( ) != null ) )
467         {
468             ImageResource img = new ImageResource( );
469             img.setImage( null );
470             img.setMimeType( null );
471             _appointmentFormDTO.setIcon( img );
472         }
473         else
474         {
475             ImageResource imageResource = buildImageResource( mRequest );
476             if ( !StringUtils.equals( MARK_NULL, imageResource.getMimeType( ) ) )
477             {
478                 _appointmentFormDTO.setIcon( imageResource );
479             }
480         }
481         // Import of the closing days file
482         importClosingDayFile( mRequest, nIdForm );
483         setParametersDays( _appointmentFormDTO, appointmentFormDb );
484         if ( !validateBean( _appointmentFormDTO, VALIDATION_ATTRIBUTES_PREFIX ) || !checkStartingAndEndingValidityDate( _appointmentFormDTO )
485                 || !checkControlMaxAppointmentsPerUser( _appointmentFormDTO ) )
486         {
487         	return redirect( request, VIEW_MODIFY_APPOINTMENTFORM, PARAMETER_ID_FORM, nIdForm );
488         }
489 
490         // Modify or remove the Access Controllers linked to this form
491         if ( AccessControlService.getInstance( ).isAvailable( ) )
492         {
493         	int idAccessControl = NumberUtils.toInt( request.getParameter( PARAMETER_ID_ACCESS_CONTROL ), -1 );
494         	AccessControlService.getInstance( ).linkResourceToAccessControl( nIdForm, Form.RESOURCE_TYPE, idAccessControl );
495         }
496 
497         _appointmentFormDTO.setIsActive( appointmentFormDb.getIsActive( ) );
498         FormService.updateGlobalParameters( _appointmentFormDTO );
499         _appointmentFormDTO = null;
500         AppLogService.info( LogUtilities.buildLog( ACTION_MODIFY_APPOINTMENTFORM, strIdForm, getUser( ) ) );
501         addInfo( INFO_APPOINTMENTFORM_UPDATED, getLocale( ) );
502         return redirect( request, VIEW_MODIFY_APPOINTMENTFORM, PARAMETER_ID_FORM, nIdForm );
503     }
504 
505     /**
506      * Change the enabling of an appointment form
507      * 
508      * @param request
509      *            The request
510      * @return The next URL to redirect to
511      * @throws AccessDeniedException
512      *             If the user is not authorized to change the activation of this appointment form
513      */
514     @Action( ACTION_DO_CHANGE_FORM_ACTIVATION )
515     public String doChangeFormActivation( HttpServletRequest request ) throws AccessDeniedException
516     {
517         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
518         if ( StringUtils.isEmpty( strIdForm ) )
519         {
520             return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
521         }
522         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_CHANGE_STATE,
523                 (User) AdminUserService.getAdminUser( request ) ) )
524         {
525             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_CHANGE_STATE );
526         }
527         int nIdForm = Integer.parseInt( strIdForm );
528         Form form = FormService.findFormLightByPrimaryKey( nIdForm );
529         if ( form != null )
530         {
531             if ( !form.getIsActive( ) )
532             {
533                 if ( form.getStartingValidityDate( ) == null )
534                 {
535                     form.setStartingValidityDate( LocalDate.now( ) );
536                 }
537                 if ( ( form.getEndingValidityDate( ) != null ) && ( form.getEndingValidityDate( ).isBefore( LocalDate.now( ) ) ) )
538                 {
539                     addError( ERROR_APPOINTMENTFORM_ENDING_VALIDITY_DATE_BEFORE_NOW, getLocale( ) );
540                     if ( Boolean.TRUE.equals( Boolean.valueOf( request.getParameter( PARAMETER_FROM_DASHBOARD ) ) ) )
541                     {
542                         return redirect( request, AppPathService.getBaseUrl( request ) + AppPathService.getAdminMenuUrl( ) );
543                     }
544                     else
545                     {
546                         return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
547                     }
548                 }
549             }
550             form.setIsActive( !form.getIsActive( ) );
551             FormService.updateForm( form );
552             AppLogService.info( LogUtilities.buildLog( ACTION_DO_CHANGE_FORM_ACTIVATION, strIdForm, getUser( ) ) );
553         }
554         if ( Boolean.TRUE.equals( Boolean.valueOf( request.getParameter( PARAMETER_FROM_DASHBOARD ) ) ) )
555         {
556             return redirect( request, AppPathService.getBaseUrl( request ) + AppPathService.getAdminMenuUrl( ) );
557         }
558         return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
559     }
560 
561     /**
562      * Do copy a form
563      * 
564      * @param request
565      *            the request
566      * @return the JSP URL to display the form to manage appointment forms
567      * @throws AccessDeniedException
568      */
569     @Action( ACTION_DO_COPY_FORM )
570     public String doCopyAppointmentForm( HttpServletRequest request ) throws AccessDeniedException
571     {
572         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE_CREATE, "0", AppointmentResourceIdService.PERMISSION_CREATE_FORM,
573                 (User) AdminUserService.getAdminUser( request ) ) )
574         {
575             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_CREATE_FORM );
576         }
577         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
578         if ( StringUtils.isEmpty( strIdForm ) )
579         {
580             return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
581         }
582         int nIdForm = Integer.parseInt( strIdForm );
583         Form formToCopy = FormService.findFormLightByPrimaryKey( nIdForm );
584         if ( formToCopy != null )
585         {
586             String newNameForCopy = I18nService.getLocalizedString( PROPERTY_COPY_OF_FORM, request.getLocale( ) ) + formToCopy.getTitle( );
587             int nIdCopyForm = FormService.copyForm( nIdForm, newNameForCopy );
588             AppLogService.info( LogUtilities.buildLog( ACTION_DO_COPY_FORM, String.valueOf( nIdCopyForm ), getUser( ) ) );
589         }
590         return getManageAppointmentForms( request );
591     }
592 
593     /**
594      * Get the page to modify an appointment form message
595      * 
596      * @param request
597      *            The request
598      * @return The HTML content to display
599      * @throws AccessDeniedException
600      *             If the user is not authorized to modify this appointment form
601      */
602     @View( VIEW_MODIFY_FORM_MESSAGES )
603     public String getModifyAppointmentFormMessages( HttpServletRequest request ) throws AccessDeniedException
604     {
605         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
606         if ( StringUtils.isEmpty( strIdForm ) )
607         {
608             return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
609         }
610         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_MODIFY_FORM,
611                 (User) AdminUserService.getAdminUser( request ) ) )
612         {
613             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_FORM );
614         }
615         int nIdForm = Integer.parseInt( strIdForm );
616         FormMessage formMessage = FormMessageService.findFormMessageByIdForm( nIdForm );
617         Map<String, Object> model = new HashMap<>( );
618         model.put( MARK_FORM_MESSAGE, formMessage );
619         model.put( MARK_WEBAPP_URL, AppPathService.getBaseUrl( request ) );
620         model.put( MARK_LOCALE, getLocale( ) );
621         model.put( MARK_LOCALE_TINY, getLocale( ) );
622         return getPage( PROPERTY_PAGE_TITLE_MODIFY_APPOINTMENTFORM_MESSAGES, TEMPLATE_MODIFY_APPOINTMENTFORM_MESSAGES, model );
623     }
624 
625     /**
626      * Do modify an appointment form messages
627      * 
628      * @param request
629      *            The request
630      * @return The next URL to redirect to
631      * @throws AccessDeniedException
632      *             If the user is not authorized to modify this appointment form
633      */
634     @Action( ACTION_DO_MODIFY_FORM_MESSAGES )
635     public String doModifyAppointmentFormMessages( HttpServletRequest request ) throws AccessDeniedException
636     {
637         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
638         if ( StringUtils.isNotEmpty( strIdForm ) && StringUtils.isNumeric( strIdForm ) && ( request.getParameter( PARAMETER_BACK ) == null ) )
639         {
640             if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_MODIFY_FORM,
641                     (User) AdminUserService.getAdminUser( request ) ) )
642             {
643                 throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_FORM );
644             }
645             int nIdForm = Integer.parseInt( strIdForm );
646             UrlItem url = new UrlItem( getViewFullUrl( VIEW_MODIFY_FORM_MESSAGES ) );
647             url.addParameter( PARAMETER_ID_FORM, nIdForm );
648             FormMessage formMessage = FormMessageService.findFormMessageByIdForm( nIdForm );
649             populate( formMessage, request );
650             FormMessageHome.update( formMessage );
651             AppLogService.info( LogUtilities.buildLog( ACTION_DO_MODIFY_FORM_MESSAGES, strIdForm, getUser( ) ) );
652             addInfo( INFO_APPOINTMENTFORM_MESSAGES_MODIFIED, getLocale( ) );
653         }
654         return redirectView( request, VIEW_MANAGE_APPOINTMENTFORMS );
655     }
656 
657     /**
658      * Get the URL to manage appointment forms
659      * 
660      * @param request
661      *            The request
662      * @return The URL to manage appointment forms
663      */
664     public static String getURLManageAppointmentForms( HttpServletRequest request )
665     {
666         UrlItem urlItem = new UrlItem( AppPathService.getBaseUrl( request ) + JSP_MANAGE_APPOINTMENTFORMS );
667         urlItem.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_MANAGE_APPOINTMENTFORMS );
668         return urlItem.getUrl( );
669     }
670 
671     /**
672      * Build an image resource (icon)
673      * 
674      * @param mRequest
675      *            the request
676      * @return the image resource
677      */
678     public static ImageResource buildImageResource( MultipartHttpServletRequest mRequest )
679     {
680         ImageResource img = new ImageResource( );
681         byte [ ] bytes = new byte [ ] { };
682         String strMimeType = MARK_NULL;
683         FileItem item = mRequest.getFile( PARAMETER_ICON_RESSOURCE );
684         if ( ( item != null ) && StringUtils.isNotEmpty( item.getName( ) ) )
685         {
686             bytes = item.get( );
687             strMimeType = item.getContentType( );
688         }
689         img.setImage( bytes );
690         img.setMimeType( strMimeType );
691         return img;
692     }
693 
694     /**
695      * Set the days to the appointment form DTO
696      * 
697      * @param appointmentForm
698      *            the appointmentForm DTO
699      * @param appointmentFormTmp
700      *            the appointmentForm temp DTO
701      */
702     private void setParametersDays( AppointmentFormDTOr/paris/lutece/plugins/appointment/web/dto/AppointmentFormDTO.html#AppointmentFormDTO">AppointmentFormDTO appointmentForm, AppointmentFormDTO appointmentFormTmp )
703     {
704         appointmentForm.setIsOpenMonday( appointmentFormTmp.getIsOpenMonday( ) );
705         appointmentForm.setIsOpenTuesday( appointmentFormTmp.getIsOpenTuesday( ) );
706         appointmentForm.setIsOpenWednesday( appointmentFormTmp.getIsOpenWednesday( ) );
707         appointmentForm.setIsOpenThursday( appointmentFormTmp.getIsOpenThursday( ) );
708         appointmentForm.setIsOpenFriday( appointmentFormTmp.getIsOpenFriday( ) );
709         appointmentForm.setIsOpenSaturday( appointmentFormTmp.getIsOpenSaturday( ) );
710         appointmentForm.setIsOpenSunday( appointmentFormTmp.getIsOpenSunday( ) );
711     }
712 
713     /**
714      * Import the file of the closing days
715      * 
716      * @param mRequest
717      *            the request
718      * @param nIdForm
719      *            the form Id
720      * @return false if there is an error during the import
721      */
722     private void importClosingDayFile( MultipartHttpServletRequest mRequest, int nIdForm )
723     {
724         String strPathFile = StringUtils.EMPTY;
725         FileItem item = mRequest.getFile( MARK_FILE_CLOSING_DAYS );
726         if ( item != null && StringUtils.isNotEmpty( item.getName( ) ) )
727         {
728             strPathFile = item.getName( );
729         }
730         if ( StringUtils.isEmpty( strPathFile ) )
731         {
732             return;
733         }
734 
735         List<LocalDate> listClosingDaysDb = ClosingDayService.findListDateOfClosingDayByIdForm( nIdForm );
736         List<LocalDate> listDateImported = new ArrayList<>( );
737         List<LocalDate> listDateToSave = new ArrayList<>( );
738         try
739         {
740             listDateImported = ClosingDayService.getImportClosingDays( item );
741         }
742         catch( IOException e )
743         {
744             AppLogService.error( "Error importing file", e );
745         }
746         if ( CollectionUtils.isEmpty( listDateImported ) )
747         {
748             addError( MESSAGE_ERROR_EMPTY_FILE, getLocale( ) );
749         }
750         else
751         {
752             List<Slot> listSlotsImpacted;
753             List<LocalDate> listDateWithError = new ArrayList<>( );
754             List<Slot> listSlotsToDelete = new ArrayList<>( );
755             List<Appointment> listAppointmentsImpacted;
756             for ( LocalDate closingDate : listDateImported )
757             {
758                 if ( !listClosingDaysDb.contains( closingDate ) )
759                 {
760                     listSlotsImpacted = SlotService.findSlotsByIdFormAndDateRange( nIdForm, closingDate.atStartOfDay( ), closingDate.atTime( LocalTime.MAX ) );
761                     // Check if there is appointments on this slots
762                     listAppointmentsImpacted = AppointmentService.findListAppointmentByListSlot( listSlotsImpacted );
763                     if ( CollectionUtils.isNotEmpty( listAppointmentsImpacted ) )
764                     {
765                         listDateWithError.add( closingDate );
766                     }
767                     else
768                     {
769                         listSlotsToDelete.addAll( listSlotsImpacted );
770                         listDateToSave.add( closingDate );
771                     }
772                 }
773             }
774             if ( CollectionUtils.isNotEmpty( listDateWithError ) )
775             {
776                 StringJoiner stbListDate = new StringJoiner( StringUtils.SPACE );
777                 for ( LocalDate dateWithError : listDateWithError )
778                 {
779                     stbListDate.add( Utilities.getFormatter( ).format( dateWithError ) ).add( "," );
780                 }
781                 String strListdate = stbListDate.toString( );
782                 strListdate = strListdate.substring( 0, strListdate.length( ) - 1 );
783                 Object [ ] tabEntryErrorDate = {
784                         strListdate
785                 };
786                 String strErrorMessageDateWithAppointments = I18nService.getLocalizedString( MESSAGE_ERROR_OPEN_SLOTS, tabEntryErrorDate, getLocale( ) );
787                 addError( strErrorMessageDateWithAppointments );
788             }
789             SlotService.deleteListSlots( listSlotsToDelete );
790             ClosingDayService.saveListClosingDay( nIdForm, listDateToSave );
791             addInfo( MESSAGE_INFO_IMPORTED_CLOSING_DAYS, getLocale( ) );
792         }
793     }
794 
795     private void populateAddress( AppointmentFormDTO appointmentForm, HttpServletRequest request )
796     {
797         String strGeolocAddress = request.getParameter( PARAMETER_GEOLOC_ADDRESS );
798         String strGeolocLatitude = request.getParameter( PARAMETER_GEOLOC_LATITUDE );
799         String strGeolocLongitude = request.getParameter( PARAMETER_GEOLOC_LONGITUDE );
800         if ( StringUtils.isNotBlank( strGeolocAddress ) && StringUtils.isNotBlank( strGeolocLatitude ) && StringUtils.isNotBlank( strGeolocLongitude ) )
801         {
802             appointmentForm.setAddress( strGeolocAddress );
803             appointmentForm.setLatitude( Double.valueOf( strGeolocLatitude ) );
804             appointmentForm.setLongitude( Double.valueOf( strGeolocLongitude ) );
805         }
806         else
807         {
808             appointmentForm.setAddress( null );
809             appointmentForm.setLatitude( null );
810             appointmentForm.setLongitude( null );
811         }
812     }
813 
814 }