/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jbpm.pvm.internal.cal; import java.io.Serializable; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; /** * a calendar that knows about business hours. */ public class BusinessCalendarImpl implements Serializable, BusinessCalendar { private static final long serialVersionUID = 1L; private static BusinessCalendarImpl instance = null; protected long oid = -1; protected int version = 0; protected TimeZone timeZone = TimeZone.getDefault(); /** array that contains the weekdays in the index as specified by {@link Calendar#SUNDAY} (=1), * {@link Calendar#MONDAY} (=2),... {@link Calendar#SATURDAY} (=7). */ protected Day[] days = null; protected Holiday[] holidays = null; protected long secondInMillis = 1000; protected long minuteInMillis = 60000; protected long hourInMillis = 3600000; protected long dayInMillis = 24*hourInMillis; protected long weekInMillis = 7*dayInMillis; protected long monthInMillis = 30*dayInMillis; protected long yearInMillis = 365*dayInMillis; protected long businessDayInMillis = 8*hourInMillis; protected long businessWeekInMillis = 40*hourInMillis; protected long businessMonthInMillis = 21*dayInMillis; protected long businessYearInMillis = 220*dayInMillis; /** constructor for persistence and creating an empty business calendar */ public BusinessCalendarImpl() { } public static synchronized BusinessCalendarImpl getInstance() { if (instance==null) { instance = new BusinessCalendarImpl(); } return instance; } public Date add(Date date, String duration) { return add(date, new Duration(duration)); } public Date add(Date date, Duration duration) { Date end = null; if (duration.isBusinessTime()) { DayPart dayPart = findDayPart(date); boolean isInbusinessHours = (dayPart!=null); if (! isInbusinessHours) { Object[] result = new Object[2]; findDay(date).findNextDayPartStart(0, date, result); date = (Date) result[0]; dayPart = (DayPart) result[1]; } long millis = convertToMillis(duration); end = dayPart.add(date, millis, duration.isBusinessTime()); } else { long millis = convertToMillis(duration); end = new Date(date.getTime()+millis); } return end; } public long convertToMillis(Duration duration){ long millis = duration.getMillis(); millis += duration.getSeconds() * secondInMillis; millis += duration.getMinutes() * minuteInMillis; millis += duration.getHours() * hourInMillis; if (duration.isBusinessTime()) { millis += duration.getDays() * businessDayInMillis; millis += duration.getWeeks() * businessWeekInMillis; millis += duration.getMonths() * businessMonthInMillis; millis += duration.getYears() * businessYearInMillis; } else { millis += duration.getDays() * dayInMillis; millis += duration.getWeeks() * weekInMillis; millis += duration.getMonths() * monthInMillis; millis += duration.getYears() * yearInMillis; } return millis; } public boolean isInBusinessHours(Date date) { return (findDayPart(date)!=null); } public boolean isHoliday(Date date) { if (holidays!=null) { for(Holiday holiday: holidays) { if (holiday.includes(date)) { return true; } } } return false; } protected Date findStartOfNextDay(Date date) { Calendar calendar = createCalendar(); calendar.setTime(date); calendar.add(Calendar.DATE, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); date = calendar.getTime(); while(isHoliday(date)) { calendar.setTime(date); calendar.add(Calendar.DATE, 1); date = calendar.getTime(); } return date; } public Calendar createCalendar() { return new GregorianCalendar(); } protected Day findDay(Date date) { Calendar calendar = createCalendar(); calendar.setTime(date); int weekDayIndex = calendar.get(Calendar.DAY_OF_WEEK); return days[weekDayIndex]; } protected DayPart findDayPart(Date date) { DayPart dayPart = null; if (! isHoliday(date)) { Day day = findDay(date); DayPart[] dayParts = day.getDayParts(); if (dayParts!=null) { for (int i=0; ((i < dayParts.length) && (dayPart==null)); i++) { DayPart candidate = dayParts[i]; if (candidate.includes(date)) { dayPart = candidate; } } } } return dayPart; } protected DayPart findNextDayPart(Date date) { DayPart nextDayPart = null; while(nextDayPart==null) { nextDayPart = findDayPart(date); if (nextDayPart==null) { date = findStartOfNextDay(date); Object result[] = new Object[2]; Day day = findDay(date); day.findNextDayPartStart(0, date, result); nextDayPart = (DayPart) result[1]; } } return nextDayPart; } // getters and setters ////////////////////////////////////////////////////// public long getBusinessDayInMillis() { return businessDayInMillis; } public void setBusinessDayInMillis(long businessDayInMillis) { this.businessDayInMillis = businessDayInMillis; } public long getBusinessMonthInMillis() { return businessMonthInMillis; } public void setBusinessMonthInMillis(long businessMonthInMillis) { this.businessMonthInMillis = businessMonthInMillis; } public long getBusinessWeekInMillis() { return businessWeekInMillis; } public void setBusinessWeekInMillis(long businessWeekInMillis) { this.businessWeekInMillis = businessWeekInMillis; } public long getBusinessYearInMillis() { return businessYearInMillis; } public void setBusinessYearInMillis(long businessYearInMillis) { this.businessYearInMillis = businessYearInMillis; } public long getDayInMillis() { return dayInMillis; } public void setDayInMillis(long dayInMillis) { this.dayInMillis = dayInMillis; } public Day[] getDays() { return days; } public void setDays(Day[] days) { this.days = days; } public Holiday[] getHolidays() { return holidays; } public void setHolidays(Holiday[] holidays) { this.holidays = holidays; } public long getHourInMillis() { return hourInMillis; } public void setHourInMillis(long hourInMillis) { this.hourInMillis = hourInMillis; } public long getMinuteInMillis() { return minuteInMillis; } public void setMinuteInMillis(long minuteInMillis) { this.minuteInMillis = minuteInMillis; } public long getMonthInMillis() { return monthInMillis; } public void setMonthInMillis(long monthInMillis) { this.monthInMillis = monthInMillis; } public long getSecondInMillis() { return secondInMillis; } public void setSecondInMillis(long secondInMillis) { this.secondInMillis = secondInMillis; } public TimeZone getTimeZone() { return timeZone; } public void setTimeZone(TimeZone timeZone) { this.timeZone = timeZone; } public long getWeekInMillis() { return weekInMillis; } public void setWeekInMillis(long weekInMillis) { this.weekInMillis = weekInMillis; } public long getYearInMillis() { return yearInMillis; } public void setYearInMillis(long yearInMillis) { this.yearInMillis = yearInMillis; } }