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.appointment.modules.resource.web;
35  
36  import java.sql.Date;
37  import java.time.LocalTime;
38  import java.util.ArrayList;
39  import java.util.Calendar;
40  import java.util.Collections;
41  import java.util.GregorianCalendar;
42  import java.util.HashMap;
43  import java.util.List;
44  import java.util.Locale;
45  import java.util.Map;
46  import java.util.Map.Entry;
47  
48  import javax.servlet.http.HttpServletRequest;
49  
50  import org.apache.commons.lang.StringUtils;
51  
52  import fr.paris.lutece.plugins.appointment.business.slot.Slot;
53  import fr.paris.lutece.plugins.appointment.modules.resource.business.AppointmentResourceHome;
54  import fr.paris.lutece.plugins.appointment.modules.resource.business.calendar.CalendarAppointmentResourceDTO;
55  import fr.paris.lutece.plugins.appointment.modules.resource.business.calendar.CalendarDayDTO;
56  import fr.paris.lutece.plugins.appointment.service.AppointmentService;
57  import fr.paris.lutece.plugins.appointment.service.FormService;
58  import fr.paris.lutece.plugins.appointment.service.SlotService;
59  import fr.paris.lutece.plugins.appointment.web.AppointmentFormJspBean;
60  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentDTO;
61  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
62  import fr.paris.lutece.plugins.resource.business.IResource;
63  import fr.paris.lutece.plugins.resource.service.ResourceService;
64  import fr.paris.lutece.plugins.resource.service.provider.IResourceProvider;
65  import fr.paris.lutece.portal.business.user.AdminUser;
66  import fr.paris.lutece.portal.service.template.AppTemplateService;
67  import fr.paris.lutece.portal.util.mvc.admin.MVCAdminJspBean;
68  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
69  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
70  import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
71  import fr.paris.lutece.util.html.HtmlTemplate;
72  import fr.paris.lutece.util.url.UrlItem;
73  
74  /**
75   * Appointment resource JSP Bean
76   */
77  @Controller( controllerJsp = AppointmentResourceJspBean.CONTROLLER_JSP, controllerPath = AppointmentResourceJspBean.CONTROLLER_PATH, right = AppointmentFormJspBean.RIGHT_MANAGEAPPOINTMENTFORM )
78  public class AppointmentResourceJspBean extends MVCAdminJspBean
79  {
80      /**
81       * The path of the JSP of the controller
82       */
83      public static final String CONTROLLER_PATH = "jsp/admin/plugins/appointment/modules/resource";
84  
85      /**
86       * The name of the JSP of the controller
87       */
88      public static final String CONTROLLER_JSP = "ManageAppointmentResources.jsp";
89      private static final long serialVersionUID = 3684357156472596848L;
90  
91      // Views
92      private static final String VIEW_USER_CALENDAR = "VIEW_USER_CALENDAR";
93      private static final String VIEW_RESOURCE_CALENDAR = "viewResourceCalendar";
94  
95      // Templates
96      private static final String TEMPLATE_RESOURCE_CALENDAR = "admin/plugins/appointment/modules/resource/resource_calendar.html";
97      private static final String TEMPLATE_VIEW_RESOURCE_CALENDAR = "admin/plugins/appointment/modules/resource/view_resource_calendar.html";
98      private static final String TEMPLATE_VIEW_USER_CALENDAR = "admin/plugins/appointment/modules/resource/view_user_calendar.html";
99      private static final String TEMPLATE_APPOINTMENT_DESCRIPTION = "admin/plugins/appointment/modules/resource/appointment_description.html";
100 
101     // URL
102     private static final String CONTROLLER_JSP_URL = CONTROLLER_PATH + "/" + CONTROLLER_JSP;
103 
104     // Marks
105     private static final String MARK_RESOURCE = "resource";
106     private static final String MARK_LIST_DAYS = "listDays";
107     private static final String MARK_LIST_DAYS_OF_WEEK = "list_days_of_week";
108     private static final String MARK_STARTING_TIME = "startingTime";
109     private static final String MARK_ENDING_TIME = "endingTime";
110     private static final String MARK_STARTING_HOUR = "startingHour";
111     private static final String MARK_STARTING_MINUTE = "startingMinute";
112     private static final String MARK_ENDING_HOUR = "endingHour";
113     private static final String MARK_ENDING_MINUTE = "endingMinute";
114     private static final String MARK_DURATION = "duration";
115     private static final String MARK_CALENDAR = "calendar";
116     private static final String MARK_APPOINTMENT = "appointment";
117 
118     // Parameters
119     private static final String PARAMETER_ID_RESOURCE = "id_resource";
120     private static final String PARAMETER_RESOURCE_TYPE = "resource_type";
121     private static final String PARAMETER_REFERER = "referer";
122     private static final String PARAMETER_FROM_URL = "fromUrl";
123     private static final String PARAMETER_OFFSET_WEEK = "offsetWeek";
124 
125     // Messages
126     private static final String MESSAGE_RESOURCE_CALENDAR_PAGE_TITLE = "module.appointment.resource.resource_calendar.pageTitle";
127     private static final String MESSAGE_USER_CALENDAR_PAGE_TITLE = "module.appointment.resource.user_calendar.pageTitle";
128 
129     /**
130      * List of i18n keys of days of week
131      */
132     private static final String [ ] MESSAGE_LIST_DAYS_OF_WEEK = {
133             "module.appointment.resource.manageCalendarSlots.labelMonday", "module.appointment.resource.manageCalendarSlots.labelTuesday",
134             "module.appointment.resource.manageCalendarSlots.labelWednesday", "module.appointment.resource.manageCalendarSlots.labelThursday",
135             "module.appointment.resource.manageCalendarSlots.labelFriday", "module.appointment.resource.manageCalendarSlots.labelSaturday",
136             "module.appointment.resource.manageCalendarSlots.labelSunday",
137     };
138 
139     /**
140      * Get the page to view the calendar of a user
141      * 
142      * @param request
143      *            the request
144      * @return The HTML code to display
145      */
146     @View( value = VIEW_USER_CALENDAR, defaultView = true )
147     public String getViewUserCalendar( HttpServletRequest request )
148     {
149         String strFromUrl = request.getParameter( PARAMETER_FROM_URL );
150 
151         if ( StringUtils.isEmpty( strFromUrl ) )
152         {
153             strFromUrl = request.getHeader( PARAMETER_REFERER );
154 
155             if ( StringUtils.isEmpty( strFromUrl ) )
156             {
157                 strFromUrl = AppointmentFormJspBean.getURLManageAppointmentForms( request );
158             }
159         }
160 
161         String strOffsetWeek = request.getParameter( PARAMETER_OFFSET_WEEK );
162 
163         int nOffsetWeek = 0;
164 
165         if ( StringUtils.isNotEmpty( strOffsetWeek ) )
166         {
167             nOffsetWeek = parseInt( strOffsetWeek );
168         }
169 
170         AdminUser adminUser = getUser( );
171 
172         IResource resource = ResourceService.getInstance( ).getResource( Integer.toString( adminUser.getUserId( ) ), AdminUser.RESOURCE_TYPE );
173 
174         Map<String, Object> model = getModel( );
175         model.put( MARK_CALENDAR, getResourceCalendar( request, resource, nOffsetWeek, getLocale( ) ) );
176         model.put( MARK_RESOURCE, resource );
177         model.put( PARAMETER_OFFSET_WEEK, nOffsetWeek );
178         model.put( PARAMETER_FROM_URL, strFromUrl );
179 
180         return getPage( MESSAGE_USER_CALENDAR_PAGE_TITLE, TEMPLATE_VIEW_USER_CALENDAR, model );
181     }
182 
183     /**
184      * Get the calendar of a resource
185      * 
186      * @param request
187      *            The request
188      * @return The HTML content to display
189      */
190     @View( VIEW_RESOURCE_CALENDAR )
191     public String getResourceCalendar( HttpServletRequest request )
192     {
193         String strIdResource = request.getParameter( PARAMETER_ID_RESOURCE );
194         String strResourceType = request.getParameter( PARAMETER_RESOURCE_TYPE );
195 
196         if ( StringUtils.isEmpty( strIdResource ) || StringUtils.isEmpty( strResourceType ) )
197         {
198             return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
199         }
200 
201         String strFromUrl = request.getParameter( PARAMETER_FROM_URL );
202 
203         if ( StringUtils.isEmpty( strFromUrl ) )
204         {
205             strFromUrl = request.getHeader( PARAMETER_REFERER );
206 
207             if ( StringUtils.isEmpty( strFromUrl ) )
208             {
209                 strFromUrl = AppointmentFormJspBean.getURLManageAppointmentForms( request );
210             }
211         }
212 
213         String strOffsetWeek = request.getParameter( PARAMETER_OFFSET_WEEK );
214 
215         int nOffsetWeek = 0;
216 
217         if ( StringUtils.isNotEmpty( strOffsetWeek ) )
218         {
219             nOffsetWeek = parseInt( strOffsetWeek );
220         }
221 
222         IResourceProvider provider = ResourceService.getInstance( ).getResourceProvider( strResourceType );
223 
224         if ( provider != null )
225         {
226             IResource resource = provider.getResource( strIdResource, strResourceType );
227 
228             if ( resource != null )
229             {
230                 Map<String, Object> model = getModel( );
231                 model.put( MARK_CALENDAR, getResourceCalendar( request, resource, nOffsetWeek, getLocale( ) ) );
232                 model.put( MARK_RESOURCE, resource );
233                 model.put( PARAMETER_OFFSET_WEEK, nOffsetWeek );
234                 model.put( PARAMETER_FROM_URL, strFromUrl );
235 
236                 return getPage( MESSAGE_RESOURCE_CALENDAR_PAGE_TITLE, TEMPLATE_VIEW_RESOURCE_CALENDAR, model );
237             }
238         }
239 
240         if ( StringUtils.isNotEmpty( strFromUrl ) )
241         {
242             return redirect( request, strFromUrl );
243         }
244 
245         return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
246     }
247 
248     /**
249      * Get the resource calendar for a week
250      * 
251      * @param request
252      *            The request
253      * @param resource
254      *            The resource
255      * @param nOffsetWeek
256      *            The week offset
257      * @param locale
258      *            The locale ...)
259      * @return The HTML content to display
260      */
261     public static String getResourceCalendar( HttpServletRequest request, IResource resource, int nOffsetWeek, Locale locale )
262     {
263 
264         Map<String, Object> model = new HashMap<String, Object>( );
265 
266         model.put( MARK_RESOURCE, resource );
267 
268         Date dateMonday = getDateMonday( nOffsetWeek );
269         Calendar calendar = new GregorianCalendar( );
270         calendar.setTime( dateMonday );
271 
272         calendar.add( Calendar.DAY_OF_WEEK, 7 );
273 
274         Date dateMax = new Date( calendar.getTimeInMillis( ) );
275 
276         List<Integer> listIdAppointments = AppointmentResourceHome.findIdAppointmentsByResourceAndDate( resource.getIdResource( ), resource.getResourceType( ),
277                 dateMonday, dateMax );
278 
279         List<AppointmentDTO> listAppointment = new ArrayList<AppointmentDTO>( listIdAppointments.size( ) );
280 
281         Map<Integer, List<CalendarAppointmentResourceDTO>> mapCalendarAppointmentResourceByDayOfWeek = new HashMap<Integer, List<CalendarAppointmentResourceDTO>>( );
282 
283         int nStartingHour = 0;
284         int nStartingMinute = 0;
285         int nEndingHour = 0;
286         int nEndingMinute = 0;
287         int nMinGlobalStartingTime = 9999;
288         int nMaxGlobalEndingTime = 0;
289         int nMinDuration = -1;
290 
291         for ( int i = 1; i < 8; i++ )
292         {
293             mapCalendarAppointmentResourceByDayOfWeek.put( i, new ArrayList<CalendarAppointmentResourceDTO>( ) );
294         }
295 
296         for ( int nIdAppointment : listIdAppointments )
297         {
298             AppointmentDTO appointment = AppointmentService.buildAppointmentDTOFromIdAppointment( nIdAppointment );
299             listAppointment.add( appointment );
300 
301             CalendarAppointmentResourceDTO/calendar/CalendarAppointmentResourceDTO.html#CalendarAppointmentResourceDTO">CalendarAppointmentResourceDTO calendarAppointmentResource = new CalendarAppointmentResourceDTO( appointment.getIdAppointment( ), appointment
302                     .getStartingDateTime( ).getHour( ), appointment.getStartingDateTime( ).getMinute( ), appointment.getEndingDateTime( ).getHour( ), appointment
303                     .getEndingDateTime( ).getMinute( ), getAppointmentRecap( appointment, locale ), appointment.getIdForm( ) );
304             long startThen = appointment.getStartingDateTime( ).getHour( ) * 60 + appointment.getStartingDateTime( ).getMinute( );
305             long endThen = appointment.getEndingDateTime( ).getHour( ) * 60 + appointment.getEndingDateTime( ).getMinute( );
306 
307             int nStartingTimeSlot = (int) startThen;
308 
309             if ( nStartingTimeSlot < nMinGlobalStartingTime )
310             {
311                 nMinGlobalStartingTime = nStartingTimeSlot;
312                 nStartingHour = appointment.getStartingDateTime( ).getHour( );
313                 nStartingMinute = appointment.getStartingDateTime( ).getMinute( );
314             }
315 
316             int nEndingTimeSlot = (int) endThen;
317 
318             if ( nEndingTimeSlot > nMaxGlobalEndingTime )
319             {
320                 nMaxGlobalEndingTime = nEndingTimeSlot;
321                 nEndingHour = appointment.getEndingDateTime( ).getHour( );
322                 nEndingMinute = appointment.getEndingDateTime( ).getMinute( );
323             }
324 
325             if ( ( calendarAppointmentResource.getDuration( ) < nMinDuration ) || ( nMinDuration == -1 ) )
326             {
327                 nMinDuration = calendarAppointmentResource.getDuration( );
328             }
329 
330             int nDayOfWeek = appointment.getStartingDateTime( ).getDayOfWeek( ).getValue( );
331             List<CalendarAppointmentResourceDTO> listCalendar = mapCalendarAppointmentResourceByDayOfWeek.get( nDayOfWeek );
332             listCalendar.add( calendarAppointmentResource );
333 
334         }
335 
336         List<CalendarDayDTO> listDays = new ArrayList<CalendarDayDTO>( 7 );
337 
338         for ( Entry<Integer, List<CalendarAppointmentResourceDTO>> entry : mapCalendarAppointmentResourceByDayOfWeek.entrySet( ) )
339         {
340             CalendarDayDTOns/appointment/modules/resource/business/calendar/CalendarDayDTO.html#CalendarDayDTO">CalendarDayDTO day = new CalendarDayDTO( );
341             Calendar calendarDay = new GregorianCalendar( );
342             calendarDay.setTime( dateMonday );
343             calendarDay.add( Calendar.DAY_OF_WEEK, entry.getKey( ) - 1 );
344             day.setDate( calendarDay.getTime( ) );
345 
346             List<CalendarAppointmentResourceDTO> listCalendarApp = entry.getValue( );
347             Collections.sort( listCalendarApp );
348             day.setListAppointmentResourceDTO( listCalendarApp );
349             listDays.add( day );
350         }
351 
352         Collections.sort( listDays );
353 
354         List<AppointmentFormDTO> listForm = FormService.buildAllActiveAppointmentForm( );
355         ;
356 
357         for ( AppointmentFormDTO form : listForm )
358         {
359 
360             int nOpeningTime = ( LocalTime.parse( form.getTimeStart( ) ).getHour( ) * 60 ) + LocalTime.parse( form.getTimeStart( ) ).getMinute( );
361 
362             if ( nOpeningTime < nMinGlobalStartingTime )
363             {
364                 nMinGlobalStartingTime = nOpeningTime;
365                 nStartingHour = LocalTime.parse( form.getTimeStart( ) ).getHour( );
366                 nStartingMinute = LocalTime.parse( form.getTimeStart( ) ).getMinute( );
367             }
368 
369             int nClosingTime = ( LocalTime.parse( form.getTimeEnd( ) ).getHour( ) * 60 ) + LocalTime.parse( form.getTimeEnd( ) ).getMinute( );
370 
371             if ( nClosingTime > nMaxGlobalEndingTime )
372             {
373                 nMaxGlobalEndingTime = nClosingTime;
374                 nEndingHour = LocalTime.parse( form.getTimeEnd( ) ).getHour( );
375                 nEndingMinute = LocalTime.parse( form.getTimeEnd( ) ).getMinute( );
376             }
377 
378             if ( ( form.getDurationAppointments( ) < nMinDuration ) || ( nMinDuration < 0 ) )
379             {
380                 nMinDuration = form.getDurationAppointments( );
381             }
382         }
383 
384         model.put( MARK_LIST_DAYS, listDays );
385         model.put( PARAMETER_OFFSET_WEEK, nOffsetWeek );
386         model.put( MARK_LIST_DAYS_OF_WEEK, MESSAGE_LIST_DAYS_OF_WEEK );
387         model.put( MARK_STARTING_TIME, nMinGlobalStartingTime );
388         model.put( MARK_ENDING_TIME, nMaxGlobalEndingTime );
389         model.put( MARK_DURATION, nMinDuration );
390         model.put( MARK_STARTING_HOUR, nStartingHour );
391         model.put( MARK_STARTING_MINUTE, nStartingMinute );
392         model.put( MARK_ENDING_HOUR, nEndingHour );
393         model.put( MARK_ENDING_MINUTE, nEndingMinute );
394 
395         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_RESOURCE_CALENDAR, locale, model );
396 
397         return template.getHtml( );
398     }
399 
400     /**
401      * Get the description of an appointment
402      * 
403      * @param appointment
404      *            The appointment
405      * @param locale
406      *            The locale
407      * @return The HTML code of the description of the appointment
408      */
409     private static String getAppointmentRecap( AppointmentDTO appointment, Locale locale )
410     {
411         Map<String, Object> model = new HashMap<String, Object>( );
412         model.put( MARK_APPOINTMENT, appointment );
413 
414         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_APPOINTMENT_DESCRIPTION, locale, model );
415 
416         return template.getHtml( );
417     }
418 
419     /**
420      * Get the URL of the calendar of a resource
421      * 
422      * @param strIdResource
423      *            The id of the resource
424      * @param strResourceType
425      *            the resource type
426      * @return The URL of the calendar of the resource. Note that the base URL is not prefixed to the URL.
427      */
428     public static String getUrlResourceCalendar( String strIdResource, String strResourceType )
429     {
430         UrlItem urlItem = new UrlItem( CONTROLLER_JSP_URL );
431         urlItem.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_RESOURCE_CALENDAR );
432         urlItem.addParameter( PARAMETER_ID_RESOURCE, strIdResource );
433         urlItem.addParameter( PARAMETER_RESOURCE_TYPE, strResourceType );
434 
435         return urlItem.getUrl( );
436     }
437 
438     /**
439      * Get the date of a Monday.
440      * 
441      * @param nOffsetWeek
442      *            The offset of the week (0 for the current week, 1 for the next one, ...)
443      * @return The date of the Monday of the requested week
444      */
445     private static Date getDateMonday( int nOffsetWeek )
446     {
447         Date date = new Date( System.currentTimeMillis( ) );
448         Calendar calendar = GregorianCalendar.getInstance( Locale.FRANCE );
449         calendar.setTime( date );
450         // We set the week to the requested one
451         calendar.add( Calendar.DAY_OF_MONTH, 7 * nOffsetWeek );
452 
453         // We get the current day of the week
454         int nCurrentDayOfWeek = calendar.get( Calendar.DAY_OF_WEEK );
455         // We add the day of the week to Monday on the calendar
456         calendar.add( Calendar.DAY_OF_WEEK, Calendar.MONDAY - nCurrentDayOfWeek );
457 
458         return new Date( calendar.getTimeInMillis( ) );
459     }
460 
461     /**
462      * Parse a string representing a positive or negative integer
463      * 
464      * @param strNumber
465      *            The string to parse
466      * @return The integer value of the number represented by the string, or 0 if the string could not be parsed
467      */
468     private int parseInt( String strNumber )
469     {
470         int nNumber = 0;
471 
472         if ( StringUtils.isEmpty( strNumber ) )
473         {
474             return nNumber;
475         }
476 
477         if ( strNumber.startsWith( "-" ) )
478         {
479             String strParseableNumber = strNumber.substring( 1 );
480 
481             if ( StringUtils.isNumeric( strParseableNumber ) )
482             {
483                 nNumber = Integer.parseInt( strParseableNumber ) * -1;
484             }
485         }
486         else
487             if ( StringUtils.isNumeric( strNumber ) )
488             {
489                 nNumber = Integer.parseInt( strNumber );
490             }
491 
492         return nNumber;
493     }
494 
495 }