001/*
002 *  Copyright 2015 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.explorer.calendars.helper;
017
018import java.util.ArrayList;
019import java.util.Arrays;
020import java.util.Calendar;
021import java.util.Date;
022import java.util.GregorianCalendar;
023import java.util.List;
024
025import org.ametys.plugins.explorer.calendars.CalendarEvent;
026import org.ametys.runtime.config.Config;
027
028/**
029 * Helper for recurrent event operation
030 */
031public final class RecurrentEventHelper
032{
033    private RecurrentEventHelper()
034    {
035        // Helper class
036    }
037    
038    /**
039     * Get the next occurrence date
040     * @param event the calendar event
041     * @param date the occurrence date
042     * @return the next occurrence date
043     */
044    public static Date getNextDate(CalendarEvent event, Date date)
045    {
046        Date nextDate = null;
047        switch (event.getRecurrenceType())
048        {
049            case ALL_DAY:
050                nextDate = _nextAllDayDate(date);
051                break;
052            case ALL_WORKING_DAY:
053                nextDate = _nextAllWorkingDayDate(date);
054                break;
055            case WEEKLY:
056                nextDate = _nextWeeklyDate(date);
057                break;
058            case BIWEEKLY:
059                nextDate = _nextBiweeklyDate(date);
060                break;
061            case MONTHLY:
062                nextDate = _nextMonthlyDate(date, event);
063                break;
064            default:
065                break;
066        }
067        
068        return nextDate;
069    }
070    
071    private static Date _nextAllDayDate(Date date)
072    {
073        GregorianCalendar gcNextDate = new GregorianCalendar();
074        gcNextDate.setTime(date);
075        gcNextDate.add(Calendar.DATE, 1);
076 
077        return  gcNextDate.getTime();
078    }
079    
080    /**
081     * get the list of working days
082     * @return a list of integer, matching {@link java.util.Calendar} days
083     */
084    public static List<Integer> getWorkingDays()
085    {
086        List<Integer> result = new ArrayList<>();
087        String workingDayAsString = Config.getInstance().getValue("org.ametys.plugins.explorer.calendar.event.working.day");
088        List<String> workingDaysStrings = Arrays.asList(workingDayAsString.split(","));
089        for (String workkingDayString : workingDaysStrings)
090        {
091            result.add(Integer.valueOf(workkingDayString));
092        }
093        return result;
094    }
095
096    private static Date _nextAllWorkingDayDate(Date date)
097    {
098        String workingDayAsString = Config.getInstance().getValue("org.ametys.plugins.explorer.calendar.event.working.day");
099        GregorianCalendar gcNextDate = new GregorianCalendar();
100        gcNextDate.setTime(date);
101        
102        int dayId = gcNextDate.get(Calendar.DAY_OF_WEEK);
103        
104        int nbDay = 1;
105        int nextDayId = (dayId % 7) + 1;
106        List<String> workingDay = Arrays.asList(workingDayAsString.split(","));
107        while (!workingDay.contains(String.valueOf(nextDayId)))
108        {
109            nextDayId = (nextDayId % 7) + 1;
110            nbDay++;
111        }
112        
113        gcNextDate.add(Calendar.DATE, nbDay);
114        
115        return gcNextDate.getTime();
116    }
117    
118    private static Date _nextWeeklyDate(Date date)
119    {
120        GregorianCalendar gcNextDate = new GregorianCalendar();
121        gcNextDate.setTime(date);
122        gcNextDate.add(Calendar.DATE, 7);
123 
124        return  gcNextDate.getTime();
125    }
126    
127    private static Date _nextBiweeklyDate(Date date)
128    {
129        GregorianCalendar gcNextDate = new GregorianCalendar();
130        gcNextDate.setTime(date);
131        gcNextDate.add(Calendar.DATE, 14);
132 
133        return  gcNextDate.getTime();
134    }
135    
136    private static Date _nextMonthlyDate(Date date, CalendarEvent event)
137    {
138        GregorianCalendar gcStartDate = new GregorianCalendar();
139        gcStartDate.setTime(event.getStartDate());
140        int dayOfMonth = gcStartDate.get(Calendar.DAY_OF_MONTH);
141        
142        GregorianCalendar gcNextDate = new GregorianCalendar();
143        gcNextDate.setTime(date);
144        gcNextDate.add(Calendar.MONTH, 1);
145        int nextDayOfMonth = gcNextDate.get(Calendar.DAY_OF_MONTH);
146        int nextDayMaxOfMonth = gcNextDate.getActualMaximum(Calendar.DAY_OF_MONTH);
147
148        if (nextDayOfMonth < dayOfMonth)
149        {
150            if (dayOfMonth < nextDayMaxOfMonth)
151            {
152                gcNextDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
153            }
154            else
155            {
156                gcNextDate.set(Calendar.DAY_OF_MONTH, nextDayMaxOfMonth);
157            }
158        }
159        
160        return  gcNextDate.getTime();
161    }
162}