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.service;
35  
36  import java.time.LocalDate;
37  import java.time.LocalTime;
38  import java.util.ArrayList;
39  import java.util.HashMap;
40  import java.util.HashSet;
41  import java.util.List;
42  import java.util.stream.Collectors;
43  
44  import org.apache.commons.collections.CollectionUtils;
45  
46  import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinition;
47  import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinitionHome;
48  import fr.paris.lutece.plugins.appointment.business.planning.WorkingDay;
49  import fr.paris.lutece.plugins.appointment.service.listeners.WeekDefinitionManagerListener;
50  import fr.paris.lutece.util.ReferenceList;
51  
52  /**
53   * Service class of a week definition
54   * 
55   * @author Laurent Payen
56   *
57   */
58  public final class WeekDefinitionService
59  {
60  
61      /**
62       * Private constructor - this class does not need to be instantiated
63       */
64      private WeekDefinitionService( )
65      {
66      }
67  
68      /**
69       * Create a week definition in database
70       * 
71       * @param nIdForm
72       *            the form Id
73       * @param dateOfApply
74       *            the date of the week definition
75       * @return the week definition created
76       */
77      public static WeekDefinition createWeekDefinition( int nIdForm, LocalDate dateOfApply )
78      {
79          WeekDefinition weekDefinition = new WeekDefinition( );
80          fillInWeekDefinition( weekDefinition, nIdForm, dateOfApply );
81          WeekDefinitionHome.create( weekDefinition );
82          WeekDefinitionManagerListener.notifyListenersWeekDefinitionCreation( weekDefinition.getIdWeekDefinition( ) );
83          return weekDefinition;
84      }
85  
86      /**
87       * Remove the weekdefinition (and by cascade the working days and the time slots)
88       * 
89       * @param nIdWeekDefinition
90       *            the id of the week definition to delete
91       */
92      public static void removeWeekDefinition( int nIdWeekDefinition, int nIdForm )
93      {
94          WeekDefinitionHome.delete( nIdWeekDefinition );
95          WeekDefinitionManagerListener.notifyListenersWeekDefinitionRemoval( nIdForm );
96      }
97  
98      /**
99       * Save a week definition
100      * 
101      * @param weekDefinition
102      *            the week definition to save
103      * @return the week definition saved
104      */
105     public static WeekDefinition saveWeekDefinition( WeekDefinition weekDefinition )
106     {
107         return WeekDefinitionHome.create( weekDefinition );
108     }
109 
110     /**
111      * Update in database a week definition
112      * 
113      * @param nIdForm
114      *            the form Id
115      * @param dateOfApply
116      *            the date of the week definition
117      * @return the week definition updated
118      */
119     public static WeekDefinition updateWeekDefinition( int nIdForm, LocalDate dateOfApply )
120     {
121         WeekDefinition weekDefinition = WeekDefinitionHome.findByIdFormAndDateOfApply( nIdForm, dateOfApply );
122         if ( weekDefinition == null )
123         {
124             weekDefinition = createWeekDefinition( nIdForm, dateOfApply );
125         }
126         else
127         {
128             fillInWeekDefinition( weekDefinition, nIdForm, dateOfApply );
129             WeekDefinitionHome.update( weekDefinition );
130             WeekDefinitionManagerListener.notifyListenersWeekDefinitionChange( weekDefinition.getIdWeekDefinition( ) );
131         }
132         return weekDefinition;
133     }
134 
135     /**
136      * Fill the week definition object with the given parameters
137      * 
138      * @param weekDefinition
139      *            the week definition to fill in
140      * @param nIdForm
141      *            the form id
142      * @param dateOfApply
143      *            the date of the week definition
144      */
145     public static void fillInWeekDefinition( WeekDefinition weekDefinition, int nIdForm, LocalDate dateOfApply )
146     {
147         weekDefinition.setDateOfApply( dateOfApply );
148         weekDefinition.setIdForm( nIdForm );
149     }
150 
151     /**
152      * Fin all the week definition of a form
153      * 
154      * @param nIdForm
155      *            the form Id
156      * @return the list of all the week definition of the form
157      */
158     public static List<WeekDefinition> findListWeekDefinition( int nIdForm )
159     {
160         List<WeekDefinition> listWeekDefinition = WeekDefinitionHome.findByIdForm( nIdForm );
161         fillInListWeekDefinition( listWeekDefinition );
162         return listWeekDefinition;
163     }
164 
165     /**
166      * Fill all the week definitions with their working days
167      * 
168      * @param listWeekDefinition
169      *            the list of week definition
170      */
171     private static void fillInListWeekDefinition( List<WeekDefinition> listWeekDefinition )
172     {
173         for ( WeekDefinition weekDefinition : listWeekDefinition )
174         {
175             fillInWeekDefinition( weekDefinition );
176         }
177     }
178 
179     /**
180      * Fill a week definition with its working days
181      * 
182      * @param weekDefinition
183      *            the week definition to fill in
184      */
185     private static void fillInWeekDefinition( WeekDefinition weekDefinition )
186     {
187         weekDefinition.setListWorkingDay( WorkingDayService.findListWorkingDayByWeekDefinition( weekDefinition.getIdWeekDefinition( ) ) );
188     }
189 
190     /**
191      * Find a week definition of a form and a date of apply
192      * 
193      * @param nIdForm
194      *            the form Id
195      * @param dateOfApply
196      *            the date of apply of the week definition
197      * @return the week definition with the closest date of apply
198      */
199     public static WeekDefinition findWeekDefinitionByIdFormAndClosestToDateOfApply( int nIdForm, LocalDate dateOfApply )
200     {
201         // Get all the week definitions
202         List<WeekDefinition> listWeekDefinition = WeekDefinitionHome.findByIdForm( nIdForm );
203         List<LocalDate> listDate = new ArrayList<>( );
204         for ( WeekDefinition weekDefinition : listWeekDefinition )
205         {
206             listDate.add( weekDefinition.getDateOfApply( ) );
207         }
208         // Try to get the closest date in past of the date of apply
209         LocalDate closestDate = Utilities.getClosestDateInPast( listDate, dateOfApply );
210         WeekDefinition weekDefinition = null;
211         // If there is no closest date in past
212         if ( closestDate == null )
213         {
214             // if the list of week definitions is not null
215             if ( CollectionUtils.isNotEmpty( listWeekDefinition ) )
216             {
217                 // Get the next week definition in the future
218                 weekDefinition = listWeekDefinition.stream( ).min( ( w1, w2 ) -> w1.getDateOfApply( ).compareTo( w2.getDateOfApply( ) ) ).get( );
219             }
220         }
221         else
222         {
223             // There is a closest date in past
224             if ( CollectionUtils.isNotEmpty( listWeekDefinition ) )
225             {
226                 // Get the corresponding week definition
227                 weekDefinition = listWeekDefinition.stream( ).filter( x -> closestDate.isEqual( x.getDateOfApply( ) ) ).findAny( ).orElse( null );
228             }
229         }
230         if ( weekDefinition != null )
231         {
232             weekDefinition.setListWorkingDay( WorkingDayService.findListWorkingDayByWeekDefinition( weekDefinition.getIdWeekDefinition( ) ) );
233         }
234         return weekDefinition;
235     }
236 
237     /**
238      * Find the weekdefinition of a form on a specific date
239      * 
240      * @param nIdForm
241      *            the form Id
242      * @param dateOfApply
243      *            the date of the weekdefinition
244      * @return the weekdefinition object
245      */
246     public static WeekDefinition findWeekDefinitionByIdFormAndDateOfApply( int nIdForm, LocalDate dateOfApply )
247     {
248         WeekDefinition weekDefinition = WeekDefinitionHome.findByIdFormAndDateOfApply( nIdForm, dateOfApply );
249         return weekDefinition;
250     }
251 
252     /**
253      * Return, if it exists, the next week definition after a given date
254      * 
255      * @param nIdForm
256      *            the form id
257      * @param previousDateOfApply
258      *            the previous date of the previous week definition
259      * @return the next week definition if it exists, null otherwise
260      */
261     public static WeekDefinition findNextWeekDefinition( int nIdForm, LocalDate previousDateOfApply )
262     {
263         WeekDefinition nextWeekDefinition = null;
264         List<WeekDefinition> listWeekDefinition = WeekDefinitionHome.findByIdForm( nIdForm );
265         if ( CollectionUtils.isNotEmpty( listWeekDefinition ) )
266         {
267             listWeekDefinition = listWeekDefinition.stream( ).filter( x -> x.getDateOfApply( ).isAfter( previousDateOfApply ) ).collect( Collectors.toList( ) );
268             if ( CollectionUtils.isNotEmpty( listWeekDefinition ) )
269             {
270                 nextWeekDefinition = listWeekDefinition.stream( ).min( ( w1, w2 ) -> w1.getDateOfApply( ).compareTo( w2.getDateOfApply( ) ) ).get( );
271             }
272         }
273         return nextWeekDefinition;
274     }
275 
276     /**
277      * Find a week definition with its primary key
278      * 
279      * @param nIdWeekDefinition
280      *            the week definition id
281      * @return the week definition found
282      */
283     public static WeekDefinition findWeekDefinitionLightById( int nIdWeekDefinition )
284     {
285         return WeekDefinitionHome.findByPrimaryKey( nIdWeekDefinition );
286     }
287 
288     /**
289      * Find a week definition by its primary key and set its working days
290      * 
291      * @param nIdWeekDefinition
292      *            the week definition id
293      * @return the week definition and its working days
294      */
295     public static WeekDefinition findWeekDefinitionById( int nIdWeekDefinition )
296     {
297         WeekDefinition weekDefinition = WeekDefinitionHome.findByPrimaryKey( nIdWeekDefinition );
298         weekDefinition.setListWorkingDay( WorkingDayService.findListWorkingDayByWeekDefinition( weekDefinition.getIdWeekDefinition( ) ) );
299         return weekDefinition;
300     }
301 
302     /**
303      * Build a reference list of all the week definitions of a form
304      * 
305      * @param nIdForm
306      *            the form Id
307      * @return a reference list of all the week definitions of a form (Id of the week definition / date of apply of the week definition
308      */
309     public static ReferenceList findAllDateOfWeekDefinition( int nIdForm )
310     {
311         ReferenceList listDate = new ReferenceList( );
312         List<WeekDefinition> listWeekDefinition = WeekDefinitionHome.findByIdForm( nIdForm );
313         for ( WeekDefinition weekDefinition : listWeekDefinition )
314         {
315             listDate.addItem( weekDefinition.getIdWeekDefinition( ), weekDefinition.getDateOfApply( ).format( Utilities.getFormatter( ) ) );
316         }
317         return listDate;
318     }
319 
320     /**
321      * Find all the week definition of a form
322      * 
323      * @param nIdForm
324      *            the form id
325      * @return a HashMap with the date of apply in key and the week definition in value
326      */
327     public static HashMap<LocalDate, WeekDefinition> findAllWeekDefinition( int nIdForm )
328     {
329         HashMap<LocalDate, WeekDefinition> mapWeekDefinition = new HashMap<>( );
330         List<WeekDefinition> listWeekDefinition = WeekDefinitionHome.findByIdForm( nIdForm );
331         for ( WeekDefinition weekDefinition : listWeekDefinition )
332         {
333             weekDefinition.setListWorkingDay( WorkingDayService.findListWorkingDayByWeekDefinition( weekDefinition.getIdWeekDefinition( ) ) );
334             mapWeekDefinition.put( weekDefinition.getDateOfApply( ), weekDefinition );
335         }
336         return mapWeekDefinition;
337     }
338 
339     /**
340      * Return the min starting time of a list of week definitions
341      * 
342      * @param listWeekDefinition
343      *            the list of week definitions
344      * @return the mini starting time
345      */
346     public static LocalTime getMinStartingTimeOfAListOfWeekDefinition( List<WeekDefinition> listWeekDefinition )
347     {
348         LocalTime minStartingTime = null;
349         LocalTime startingTimeTemp;
350         for ( WeekDefinition weekDefinition : listWeekDefinition )
351         {
352             startingTimeTemp = getMinStartingTimeOfAWeekDefinition( weekDefinition );
353             if ( minStartingTime == null || startingTimeTemp.isBefore( minStartingTime ) )
354             {
355                 minStartingTime = startingTimeTemp;
356             }
357         }
358         return minStartingTime;
359     }
360 
361     /**
362      * Return the min starting time of a week definition
363      * 
364      * @param weekDefinition
365      *            the week definition
366      * @return the min starting time of the week definition
367      */
368     public static LocalTime getMinStartingTimeOfAWeekDefinition( WeekDefinition weekDefinition )
369     {
370         return WorkingDayService.getMinStartingTimeOfAListOfWorkingDay( weekDefinition.getListWorkingDay( ) );
371     }
372 
373     /**
374      * Return the max ending time of a list of week definitions
375      * 
376      * @param listWeekDefinition
377      *            the list of week definitions
378      * @return the max ending time of the list of week definitions
379      */
380     public static LocalTime getMaxEndingTimeOfAListOfWeekDefinition( List<WeekDefinition> listWeekDefinition )
381     {
382         LocalTime maxEndingTime = null;
383         LocalTime endingTimeTemp;
384         for ( WeekDefinition weekDefinition : listWeekDefinition )
385         {
386             endingTimeTemp = getMaxEndingTimeOfAWeekDefinition( weekDefinition );
387             if ( maxEndingTime == null || endingTimeTemp.isAfter( maxEndingTime ) )
388             {
389                 maxEndingTime = endingTimeTemp;
390             }
391         }
392         return maxEndingTime;
393     }
394 
395     /**
396      * Get the max ending time of a week definition
397      * 
398      * @param weekDefinition
399      *            the week definition
400      * @return the max ending time of the week definition
401      */
402     public static LocalTime getMaxEndingTimeOfAWeekDefinition( WeekDefinition weekDefinition )
403     {
404         return WorkingDayService.getMaxEndingTimeOfAListOfWorkingDay( weekDefinition.getListWorkingDay( ) );
405     }
406 
407     /**
408      * Get the min duration of a time slot of a list of week definition
409      * 
410      * @param listWeekDefinition
411      *            the list of the week definitions
412      * @return the min duration time slot
413      */
414     public static int getMinDurationTimeSlotOfAListOfWeekDefinition( List<WeekDefinition> listWeekDefinition )
415     {
416         int nMinDuration = 0;
417         int nDurationTemp;
418         for ( WeekDefinition weekDefinition : listWeekDefinition )
419         {
420             nDurationTemp = getMinDurationTimeSlotOfAWeekDefinition( weekDefinition );
421             if ( nMinDuration == 0 || nMinDuration > nDurationTemp )
422             {
423                 nMinDuration = nDurationTemp;
424             }
425         }
426         return nMinDuration;
427     }
428 
429     /**
430      * Get the min duration of a time slot of a week definition
431      * 
432      * @param weekDefinition
433      *            the week definition
434      * @return the min duration time slot
435      */
436     public static int getMinDurationTimeSlotOfAWeekDefinition( WeekDefinition weekDefinition )
437     {
438         return WorkingDayService.getMinDurationTimeSlotOfAListOfWorkingDay( weekDefinition.getListWorkingDay( ) );
439     }
440 
441     /**
442      * Get the working days integer enum values of a list of week definitions
443      * 
444      * @param listWeekDefinition
445      *            the list of week definitions
446      * @return a set of the working days (integer value in a week : 1-> Monday ...) // The fullCalendar library is zero-base (Sunday=0)
447      */
448     public static HashSet<String> getSetDaysOfWeekOfAListOfWeekDefinitionForFullCalendar( List<WeekDefinition> listWeekDefinition )
449     {
450         HashSet<String> setDayOfWeek = new HashSet<>( );
451         for ( WeekDefinition weekDefinition : listWeekDefinition )
452         {
453             setDayOfWeek.addAll( WorkingDayService.getSetDaysOfWeekOfAListOfWorkingDayForFullCalendar( weekDefinition.getListWorkingDay( ) ) );
454         }
455         return setDayOfWeek;
456     }
457 
458     /**
459      * Get the set of the open days of all the week definitons
460      * 
461      * @param listWeekDefinition
462      *            the list of week definitions
463      * @return the set of the open days
464      */
465     public static HashSet<Integer> getOpenDaysOfWeek( List<WeekDefinition> listWeekDefinition )
466     {
467         HashSet<Integer> setOpenDays = new HashSet<>( );
468         for ( WeekDefinition weekDefinition : listWeekDefinition )
469         {
470             for ( WorkingDay workingDay : weekDefinition.getListWorkingDay( ) )
471             {
472                 setOpenDays.add( workingDay.getDayOfWeek( ) );
473             }
474         }
475         return setOpenDays;
476     }
477 
478 }