com.clican.pluto.common.calendar.BusinessCalendar.java Source code

Java tutorial

Introduction

Here is the source code for com.clican.pluto.common.calendar.BusinessCalendar.java

Source

/**
 * The Clican-Pluto software suit is Copyright 2009, Clican Company
 * and individual contributors, and is licensed under the GNU LGPL.
 *
 * @author wei.zhang
 *
 */
package com.clican.pluto.common.calendar;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
 * This class<code>BusinessCalendar</code> represents the calendar in work flow 
 * configured in spring configurations.
 * <p>
 * <pre>
 * Example:
 * <bean id="businessCalendar" class="com.jsw.common.calendar.BusinessCalendar" init-method="init">
 *      <property name="monday" value="9:00-12:00 and 13:00-18:00"/>
 *       <property name="tuesday" value="9:00-12:00 and 13:00-18:00"/>
 *      <property name="wednesday" value="9:00-12:00 and 13:00-18:00"/>
 *      <property name="thursday" value="9:00-12:00 and 13:00-18:00"/>
 *      <property name="friday" value="9:00-12:00 and 13:00-18:00"/>
 *      <property name="holidayList">
 *         <list>
 *            <value>01/07/2008-31/08/2008</value>
 *            <value>01/10/2008-07/10/2008</value>
 *         </list>
 *      </property>
 *   </bean>
 * </pre>
 * </p>
 * @author chulin.gui
 *
 */
public class BusinessCalendar implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 8371169448495697670L;

    /**
     * array that contains the weekdays in the index as specified by
     * {@link Calendar#SUNDAY} (=1), {@link Calendar#MONDAY} (=2),...
     * {@link Calendar#SATURDAY} (=7).
     */
    protected BusinessDay[] 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;

    private String monday;

    private String tuesday;

    private String wednesday;

    private String thursday;

    private String friday;

    private String saturday;

    private String sunday;

    private List<String> holidayList;

    public void setMonday(String monday) {
        this.monday = monday;
    }

    public void setTuesday(String tuesday) {
        this.tuesday = tuesday;
    }

    public void setWednesday(String wednesday) {
        this.wednesday = wednesday;
    }

    public void setThursday(String thursday) {
        this.thursday = thursday;
    }

    public void setFriday(String friday) {
        this.friday = friday;
    }

    public void setSaturday(String saturday) {
        this.saturday = saturday;
    }

    public void setSunday(String sunday) {
        this.sunday = sunday;
    }

    public void setHolidayList(List<String> holidayList) {
        this.holidayList = holidayList;
    }

    /**
     * Initial method 
     */
    public void init() {
        days = new BusinessDay[8];
        days[Calendar.SUNDAY] = parseDay(sunday);
        days[Calendar.MONDAY] = parseDay(monday);
        days[Calendar.TUESDAY] = parseDay(tuesday);
        days[Calendar.WEDNESDAY] = parseDay(wednesday);
        days[Calendar.THURSDAY] = parseDay(thursday);
        days[Calendar.FRIDAY] = parseDay(friday);
        days[Calendar.SATURDAY] = parseDay(saturday);

        holidays = new Holiday[holidayList.size()];
        for (int i = 0; i < holidayList.size(); i++) {
            holidays[i] = parseHoliday(holidayList.get(i));
        }
    }

    /**
     * parse variable days string.
     * @param dayExpr
     * @return
     */
    private BusinessDay parseDay(String dayExpr) {
        DateFormat hourFormat = new SimpleDateFormat("HH:mm");
        BusinessDay day = new BusinessDay();
        day.setBusinessCalendar(this);
        if (StringUtils.isNotEmpty(dayExpr)) {
            List<BusinessDayPart> dayParts = new ArrayList<BusinessDayPart>();
            int dayPartIndex = 0;
            for (String part : com.clican.pluto.common.util.StringUtils.tokenize(dayExpr, "and")) {
                try {
                    int separatorIndex = part.indexOf('-');
                    if (separatorIndex == -1)
                        throw new IllegalArgumentException("no dash (-)");
                    String fromText = part.substring(0, separatorIndex).trim().toLowerCase();
                    String toText = part.substring(separatorIndex + 1).trim().toLowerCase();

                    Date from = hourFormat.parse(fromText);
                    Date to = hourFormat.parse(toText);

                    Calendar calendar = new GregorianCalendar();
                    calendar.setTime(from);
                    int fromHour = calendar.get(Calendar.HOUR_OF_DAY);
                    int fromMinute = calendar.get(Calendar.MINUTE);

                    calendar.setTime(to);
                    int toHour = calendar.get(Calendar.HOUR_OF_DAY);
                    if (toHour == 0) {
                        toHour = 24;
                    }
                    int toMinute = calendar.get(Calendar.MINUTE);

                    BusinessDayPart dayPart = new BusinessDayPart();
                    dayPart.setDay(day);
                    dayPart.setIndex(dayPartIndex);
                    dayPart.setFromHour(fromHour);
                    dayPart.setFromMinute(fromMinute);
                    dayPart.setToHour(toHour);
                    dayPart.setToMinute(toMinute);
                    dayParts.add(dayPart);
                    dayPartIndex++;
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            BusinessDayPart[] dayPartArray = new BusinessDayPart[dayParts.size()];
            dayPartArray = dayParts.toArray(dayPartArray);
            day.setDayParts(dayPartArray);
        }
        return day;
    }

    /**
     * parse holiday string.
     * @param holidayExpr
     * @return
     */
    private Holiday parseHoliday(String holidayExpr) {
        DateFormat dayFormat = new SimpleDateFormat("dd/MM/yyyy");
        Holiday holiday = new Holiday();
        try {
            int dashIndex = holidayExpr.indexOf('-');
            String fromDateText = null;
            String toDateText = null;
            if (dashIndex != -1) {
                fromDateText = holidayExpr.substring(0, dashIndex).trim().toLowerCase();
                toDateText = holidayExpr.substring(dashIndex + 1).trim().toLowerCase();
            } else {
                fromDateText = holidayExpr.trim().toLowerCase();
                toDateText = fromDateText;
            }
            Date fromDate = dayFormat.parse(fromDateText);
            holiday.setFromDay(fromDate);
            Date toDate = dayFormat.parse(toDateText);
            holiday.setToDay(toDate);

            // now we are going to set the toDay to the end of the day, rather
            // then the beginning.
            // we take the start of the next day as the end of the toDay.
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(holiday.getToDay());
            calendar.add(Calendar.DATE, 1);
            Date toDay = calendar.getTime();
            holiday.setToDay(toDay);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return holiday;
    }

    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()) {
            BusinessDayPart 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 = (BusinessDayPart) 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 BusinessDay findDay(Date date) {
        Calendar calendar = createCalendar();
        calendar.setTime(date);
        int weekDayIndex = calendar.get(Calendar.DAY_OF_WEEK);
        return days[weekDayIndex];
    }

    protected BusinessDayPart findDayPart(Date date) {
        BusinessDayPart dayPart = null;
        if (!isHoliday(date)) {
            BusinessDay day = findDay(date);
            BusinessDayPart[] dayParts = day.getDayParts();
            if (dayParts != null) {
                for (int i = 0; ((i < dayParts.length) && (dayPart == null)); i++) {
                    BusinessDayPart candidate = dayParts[i];
                    if (candidate.includes(date)) {
                        dayPart = candidate;
                    }
                }
            }
        }
        return dayPart;
    }

    protected BusinessDayPart findNextDayPart(Date date) {
        BusinessDayPart nextDayPart = null;
        while (nextDayPart == null) {
            nextDayPart = findDayPart(date);
            if (nextDayPart == null) {
                date = findStartOfNextDay(date);
                Object result[] = new Object[2];
                BusinessDay day = findDay(date);
                day.findNextDayPartStart(0, date, result);
                nextDayPart = (BusinessDayPart) 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 BusinessDay[] getDays() {
        return days;
    }

    public void setDays(BusinessDay[] 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 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;
    }
}

// $Id$