Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2009, Red Hat Middleware LLC, and individual contributors
   * as indicated by the @author tags. See the copyright.txt file 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.jboss.as.ejb3.timerservice.schedule;
 
 
 import java.util.Date;
 import static org.jboss.as.ejb3.EjbMessages.MESSAGES;
 import static org.jboss.as.ejb3.EjbLogger.ROOT_LOGGER;
CalendarBasedTimeout

Author(s):
Jaikiran Pai
Version:
$Revision: $
 
 public class CalendarBasedTimeout {


    
The javax.ejb.ScheduleExpression from which this CalendarBasedTimeout was created
 
     private ScheduleExpression scheduleExpression;

    
 
     private Second second;

    
 
     private Minute minute;

    
 
     private Hour hour;

    
 
     private DayOfWeek dayOfWeek;

    
 
     private DayOfMonth dayOfMonth;

    
 
     private Month month;

    
 
     private Year year;

    
The first timeout relative to the time when this CalendarBasedTimeout was created from a javax.ejb.ScheduleExpression
 
     private Calendar firstTimeout;

    
The timezone being used for this CalendarBasedTimeout
 
     private TimeZone timezone;

    
Creates a CalendarBasedTimeout from the passed schedule.

This constructor parses the passed javax.ejb.ScheduleExpression and sets up its internal representation of the same.

Parameters:
schedule The schedule
    public CalendarBasedTimeout(ScheduleExpression schedule) {
        if (schedule == null) {
            throw .invalidScheduleExpression(this.getClass().getName());
        }
        // make sure that the schedule doesn't have null values for its various attributes
        this.nullCheckScheduleAttributes(schedule);
        // store the original expression from which this
        // CalendarBasedTimeout was created. Since the ScheduleExpression
        // is mutable, we will have to store a clone copy of the schedule,
        // so that any subsequent changes after the CalendarBasedTimeout construction,
        // do not affect this internal schedule expression.
        this. = this.clone(schedule);
        // Start parsing the values in the ScheduleExpression
        this. = new Second(schedule.getSecond());
        this. = new Minute(schedule.getMinute());
        this. = new Hour(schedule.getHour());
        this. = new DayOfWeek(schedule.getDayOfWeek());
        this. = new DayOfMonth(schedule.getDayOfMonth());
        this. = new Month(schedule.getMonth());
        this. = new Year(schedule.getYear());
        if (schedule.getTimezone() != null && schedule.getTimezone().trim().isEmpty() == false) {
            // If the timezone ID wasn't valid, then Timezone.getTimeZone returns
            // GMT, which may not always be desirable.
            // So we first check to see if the timezone id specified is available in
            // timezone ids in the system. If it's available then we log a WARN message
            // and fallback on the server's timezone.
            String timezoneId = schedule.getTimezone();
            String[] availableTimeZoneIDs = TimeZone.getAvailableIDs();
            if (availableTimeZoneIDs != null && Arrays.asList(availableTimeZoneIDs).contains(timezoneId)) {
                this. = TimeZone.getTimeZone(timezoneId);
            } else {
                .unknownTimezoneId(timezoneId, TimeZone.getDefault().getID());
                // use server's timezone
                this. = TimeZone.getDefault();
            }
        } else {
            this. = TimeZone.getDefault();
        }
        // Now that we have parsed the values from the ScheduleExpression,
        // determine and set the first timeout (relative to the current time)
        // of this CalendarBasedTimeout
        this.setFirstTimeout();
    }
    public Calendar getNextTimeout() {
        Calendar now = new GregorianCalendar(this.);
        now.setTime(new Date());
        return this.getNextTimeout(now);
    }

    

Returns:
    public Calendar getFirstTimeout() {
        return this.;
    }
    private void setFirstTimeout() {
        this. = new GregorianCalendar(this.);
        Date start = this..getStart();
        if (start != null) {
            this..setTime(start);
        } else {
            this..set(.this..getFirst());
            this..set(.this..getFirst());
            this..set(.this..getFirst());
            this..set(., 0);
        }
        this. = this.computeNextSecond(this.);
        if (this. == null) {
            return;
        }
        this. = this.computeNextMinute(this.);
        if (this. == null) {
            return;
        }
        this. = this.computeNextHour(this.);
        if (this. == null) {
            return;
        }
        this. = this.computeNextMonth(this.);
        if (this. == null) {
            return;
        }
        this. = this.computeNextDate(this.);
        if (this. == null) {
            return;
        }
        this. = this.computeNextYear(this.);
        // one final check
        if (this. != null && this.noMoreTimeouts(this.)) {
            this. = null;
        }
    }

    
Returns the original javax.ejb.ScheduleExpression from which this CalendarBasedTimeout was created.

Returns:
        return this.;
    }
    public Calendar getNextTimeout(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Calendar nextCal = this.copy(currentCal);
        Date start = this..getStart();
        if (start != null && currentCal.getTime().before(start)) {
            nextCal.setTime(start);
        } else {
            // increment the current second by 1
            nextCal.add(., 1);
            nextCal.set(., 0);
        }
        nextCal.setFirstDayOfWeek(.);
        nextCal = this.computeNextSecond(nextCal);
        if (nextCal == null) {
            return null;
        }
        nextCal = this.computeNextMinute(nextCal);
        if (nextCal == null) {
            return null;
        }
        nextCal = this.computeNextHour(nextCal);
        if (nextCal == null) {
            return null;
        }
        nextCal = this.computeNextMonth(nextCal);
        if (nextCal == null) {
            return null;
        }
        nextCal = this.computeNextDate(nextCal);
        if (nextCal == null) {
            return null;
        }
        nextCal = this.computeNextYear(nextCal);
        if (nextCal == null) {
            return null;
        }
        // one final check
        if (this.noMoreTimeouts(nextCal)) {
            return null;
        }
        return nextCal;
    }
    private Calendar computeNextSecond(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Integer nextSecond = this..getNextMatch(currentCal);
        if (nextSecond == null) {
            return null;
        }
        int currentSecond = currentCal.get(.);
        // if the current second is a match, then nothing else to
        // do. Just return back the calendar
        if (currentSecond == nextSecond) {
            return currentCal;
        }
        Calendar nextCal = this.copy(currentCal);
        // At this point, a suitable "next" second has been identified.
        // There can be 2 cases
        // 1) The "next" second is greater than the current second : This
        // implies that the next second is within the "current" minute.
        // 2) The "next" second is lesser than the current second : This implies
        // that the next second is in the next minute (i.e. current minute needs to
        // be advanced to next minute).
        // handle case#1
        if (nextSecond > currentSecond) {
            nextCal.set(.nextSecond);
            return nextCal;
        }
        // case#2
        if (nextSecond < currentSecond) {
            nextCal.set(.nextSecond);
            // advance the minute to next minute
            nextCal.add(., 1);
            return nextCal;
        }
        return null;
    }
    private Calendar computeNextMinute(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Integer nextMinute = this..getNextMatch(currentCal);
        if (nextMinute == null) {
            return null;
        }
        int currentMinute = currentCal.get(.);
        // if the current minute is a match, then nothing else to
        // do. Just return back the calendar
        if (currentMinute == nextMinute) {
            return currentCal;
        }
        Calendar nextCal = this.copy(currentCal);
        // At this point, a suitable "next" minute has been identified.
        // There can be 2 cases
        // 1) The "next" minute is greater than the current minute : This
        // implies that the next minute is within the "current" hour.
        // 2) The "next" minute is lesser than the current minute : This implies
        // that the next minute is in the next hour (i.e. current hour needs to
        // be advanced to next hour).
        // handle case#1
        if (nextMinute > currentMinute) {
            // set the chosen minute
            nextCal.set(.nextMinute);
            // since we are moving to a different minute (as compared to the current minute),
            // we should reset the second, to its first possible value
            nextCal.set(.this..getFirst());
            return nextCal;
        }
        // case#2
        if (nextMinute < currentMinute) {
            // since we are advancing the hour, we should
            // restart from the first eligible second
            nextCal.set(.this..getFirst());
            // set the chosen minute
            nextCal.set(.nextMinute);
            // advance the hour to next hour
            nextCal.add(., 1);
            return nextCal;
        }
        return null;
    }
    private Calendar computeNextHour(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Integer nextHour = this..getNextMatch(currentCal);
        if (nextHour == null) {
            return null;
        }
        int currentHour = currentCal.get(.);
        // if the current hour is a match, then nothing else to
        // do. Just return back the calendar
        if (currentHour == nextHour) {
            return currentCal;
        }
        Calendar nextCal = this.copy(currentCal);
        // At this point, a suitable "next" hour has been identified.
        // There can be 2 cases
        // 1) The "next" hour is greater than the current hour : This
        // implies that the next hour is within the "current" day.
        // 2) The "next" hour is lesser than the current hour : This implies
        // that the next hour is in the next day (i.e. current day needs to
        // be advanced to next day).
        // handle case#1
        if (nextHour > currentHour) {
            // set the chosen day of hour
            nextCal.set(.nextHour);
            // since we are moving to a different hour (as compared to the current hour),
            // we should reset the second and minute appropriately, to their first possible
            // values
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            return nextCal;
        }
        // case#2
        if (nextHour < currentHour) {
            // set the chosen hour
            nextCal.set(.nextHour);
            // since we are moving to a different hour (as compared to the current hour),
            // we should reset the second and minute appropriately, to their first possible
            // values
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            // advance to next day
            nextCal.add(., 1);
            return nextCal;
        }
        return null;
    }
    private Calendar computeNextDayOfWeek(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Integer nextDayOfWeek = this..getNextMatch(currentCal);
        if (nextDayOfWeek == null) {
            return null;
        }
        int currentDayOfWeek = currentCal.get(.);
        // if the current day-of-week is a match, then nothing else to
        // do. Just return back the calendar
        if (currentDayOfWeek == nextDayOfWeek) {
            return currentCal;
        }
        Calendar nextCal = this.copy(currentCal);
        // At this point, a suitable "next" day-of-week has been identified.
        // There can be 2 cases
        // 1) The "next" day-of-week is greater than the current day-of-week : This
        // implies that the next day-of-week is within the "current" week.
        // 2) The "next" day-of-week is lesser than the current day-of-week : This implies
        // that the next day-of-week is in the next week (i.e. current week needs to
        // be advanced to next week).
        // handle case#1
        if (nextDayOfWeek > currentDayOfWeek) {
            // set the chosen day-of-week
            int dayDiff = nextDayOfWeek - currentDayOfWeek;
            nextCal.add(.dayDiff);
            // since we are moving to a different day-of-week (as compared to the current day-of-week),
            // we should reset the second, minute and hour appropriately, to their first possible
            // values
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            return nextCal;
        }
        // case#2
        if (nextDayOfWeek < currentDayOfWeek) {
            // set the chosen day-of-week
            nextCal.set(.nextDayOfWeek);
            // advance to next week
            nextCal.add(., 1);
            // since we are moving to a different day-of-week (as compared to the current day-of-week),
            // we should reset the second, minute and hour appropriately, to their first possible
            // values
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            return nextCal;
        }
        return null;
    }
    private Calendar computeNextMonth(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Integer nextMonth = this..getNextMatch(currentCal);
        if (nextMonth == null) {
            return null;
        }
        int currentMonth = currentCal.get(.);
        // if the current month is a match, then nothing else to
        // do. Just return back the calendar
        if (currentMonth == nextMonth) {
            return currentCal;
        }
        Calendar nextCal = this.copy(currentCal);
        // At this point, a suitable "next" month has been identified.
        // There can be 2 cases
        // 1) The "next" month is greater than the current month : This
        // implies that the next month is within the "current" year.
        // 2) The "next" month is lesser than the current month : This implies
        // that the next month is in the next year (i.e. current year needs to
        // be advanced to next year).
        // handle case#1
        if (nextMonth > currentMonth) {
            // since we are moving to a different month (as compared to the current month),
            // we should reset the second, minute, hour, day-of-week and dayofmonth appropriately, to their first possible
            // values
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(., 1);
            // set the chosen month
            nextCal.set(.nextMonth);
            return nextCal;
        }
        // case#2
        if (nextMonth < currentMonth) {
            // set the chosen month
            nextCal.set(.nextMonth);
            // since we are moving to a different month (as compared to the current month),
            // we should reset the second, minute, hour, day-of-week and dayofmonth appropriately, to their first possible
            // values
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(.this..getFirst());
            nextCal.set(., 1);
            // advance to next year
            nextCal.add(., 1);
            return nextCal;
        }
        return null;
    }
    private Calendar computeNextDate(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        if (this.isDayOfMonthWildcard()) {
            return this.computeNextDayOfWeek(currentCal);
        }
        if (this.isDayOfWeekWildcard()) {
            return this.computeNextDayOfMonth(currentCal);
        }
        // both day-of-month and day-of-week are *non-wildcards*
        Calendar nextDayOfMonthCal = this.computeNextDayOfMonth(currentCal);
        Calendar nextDayOfWeekCal = this.computeNextDayOfWeek(currentCal);
        if (nextDayOfMonthCal == null) {
            return nextDayOfWeekCal;
        }
        if (nextDayOfWeekCal == null) {
            return nextDayOfMonthCal;
        }
        return nextDayOfWeekCal.getTime().before(nextDayOfMonthCal.getTime()) ? nextDayOfWeekCal : nextDayOfMonthCal;
    }
    private Calendar computeNextDayOfMonth(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Integer nextDayOfMonth = this..getNextMatch(currentCal);
        if (nextDayOfMonth == null) {
            return null;
        }
        int currentDayOfMonth = currentCal.get(.);
        // if the current day-of-month is a match, then nothing else to
        // do. Just return back the calendar
        if (currentDayOfMonth == nextDayOfMonth) {
            return currentCal;
        }
        Calendar nextCal = this.copy(currentCal);
        if (nextDayOfMonth > currentDayOfMonth) {
            if (this.monthHasDate(nextCalnextDayOfMonth)) {
                // set the chosen day-of-month
                nextCal.set(.nextDayOfMonth);
                // since we are moving to a different day-of-month (as compared to the current day-of-month),
                // we should reset the second, minute and hour appropriately, to their first possible
                // values
                nextCal.set(.this..getFirst());
                nextCal.set(.this..getFirst());
                nextCal.set(.this..getFirst());
            } else {
                nextCal = this.advanceTillMonthHasDate(nextCalnextDayOfMonth);
            }
        } else if (nextDayOfMonth < currentDayOfMonth) {
            nextCal.add(., 1);
            nextCal = this.computeNextMonth(nextCal);
            if (nextCal == null) {
                return null;
            }
            nextDayOfMonth = this..getFirstMatch(nextCal);
            if (nextDayOfMonth == null) {
                return null;
            }
            // make sure the month can handle the date
            nextCal = this.advanceTillMonthHasDate(nextCalnextDayOfMonth);
        }
        return nextCal;
    }
    private Calendar computeNextYear(Calendar currentCal) {
        if (this.noMoreTimeouts(currentCal)) {
            return null;
        }
        Integer nextYear = this..getNextMatch(currentCal);
        if (nextYear == null || nextYear > .) {
            return null;
        }
        int currentYear = currentCal.get(.);
        // if the current year is a match, then nothing else to
        // do. Just return back the calendar
        if (currentYear == nextYear) {
            return currentCal;
        }
        // If the next year is lesser than the current year, then
        // we have no more timeouts for the calendar expression
        if (nextYear < currentYear) {
            return null;
        }
        Calendar nextCal = this.copy(currentCal);
        // at this point we have chosen a year which is greater than the current
        // year.
        // set the chosen year
        nextCal.set(.nextYear);
        // since we are moving to a different year (as compared to the current year),
        // we should reset all other calendar attribute expressions appropriately, to their first possible
        // values
        nextCal.set(.this..getFirst());
        nextCal.set(.this..getFirst());
        nextCal.set(.this..getFirst());
        nextCal.set(.this..getFirstMatch());
        nextCal.set(., 1);
        nextCal = this.computeNextDate(nextCal);
        if (nextCal == null) {
            return null;
        }
        return nextCal;
    }
    private Calendar advanceTillMonthHasDate(Calendar calInteger date) {
        Calendar copy = this.copy(cal);
        // make sure the month can handle the date
        while (monthHasDate(copydate) == false) {
            if (copy.get(.) > .) {
                return null;
            }
            // this month can't handle the date, so advance month to next month
            // and get the next suitable matching month
            copy.add(., 1);
            copy = this.computeNextMonth(copy);
            if (copy == null) {
                return null;
            }
            date = this..getFirstMatch(copy);
            if (date == null) {
                return null;
            }
            copy.set(.this..getFirst());
            copy.set(.this..getFirst());
            copy.set(.this..getFirst());
        }
        copy.set(.date);
        return copy;
    }
    private Calendar copy(Calendar cal) {
        Calendar copy = new GregorianCalendar(cal.getTimeZone());
        copy.setTime(cal.getTime());
        return copy;
    }
    private boolean monthHasDate(Calendar calint date) {
        Calendar tmpCal = new GregorianCalendar(cal.getTimeZone());
        tmpCal.set(.cal.get(.));
        tmpCal.set(.cal.get(.));
        tmpCal.set(., 1);
        int maximumPossibleDateForTheMonth = tmpCal.getActualMaximum(.);
        if (date > maximumPossibleDateForTheMonth) {
            return false;
        }
        return true;
    }
    private boolean isAfterEnd(Calendar cal) {
        Date end = this..getEnd();
        if (end == null) {
            return false;
        }
        // check that the next timeout isn't past the end date
        return cal.getTime().after(end);
    }
    private boolean noMoreTimeouts(Calendar cal) {
        if (cal.get(.) > . || isAfterEnd(cal)) {
            return true;
        }
        return false;
    }
    private boolean isDayOfWeekWildcard() {
        return this..getDayOfWeek().equals("*");
    }
    private boolean isDayOfMonthWildcard() {
        return this..getDayOfMonth().equals("*");
    }
    private void nullCheckScheduleAttributes(ScheduleExpression schedule) {
        if (schedule.getSecond() == null) {
            throw .invalidScheduleExpressionSecond(schedule);
        }
        if (schedule.getMinute() == null) {
            throw .invalidScheduleExpressionMinute(schedule);
        }
        if (schedule.getHour() == null) {
            throw .invalidScheduleExpressionHour(schedule);
        }
        if (schedule.getDayOfMonth() == null) {
            throw .invalidScheduleExpressionDayOfMonth(schedule);
        }
        if (schedule.getDayOfWeek() == null) {
            throw .invalidScheduleExpressionDayOfWeek(schedule);
        }
        if (schedule.getMonth() == null) {
            throw .invalidScheduleExpressionMonth(schedule);
        }
        if (schedule.getYear() == null) {
            throw .invalidScheduleExpressionYear(schedule);
        }
    }
    private ScheduleExpression clone(ScheduleExpression schedule) {
        // clone the schedule
        ScheduleExpression clonedSchedule = new ScheduleExpression();
        clonedSchedule.second(schedule.getSecond());
        clonedSchedule.minute(schedule.getMinute());
        clonedSchedule.hour(schedule.getHour());
        clonedSchedule.dayOfWeek(schedule.getDayOfWeek());
        clonedSchedule.dayOfMonth(schedule.getDayOfMonth());
        clonedSchedule.month(schedule.getMonth());
        clonedSchedule.year(schedule.getYear());
        clonedSchedule.timezone(schedule.getTimezone());
        clonedSchedule.start(schedule.getStart());
        clonedSchedule.end(schedule.getEnd());
        return clonedSchedule;
    }
New to GrepCode? Check out our FAQ X