⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alarmentry.java

📁 一个Java的类似cron的日程安排提醒程序。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *  com/jtheory/jdring/AlarmEntry.java
 *  Copyright (C) 1999 - 2004 jtheory creations, Olivier Dedieu et al.
 *
 *  This library is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Library General Public License as published
 *  by the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This library 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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

package com.jtheory.jdring;

import java.util.Calendar;
import java.util.Date;
import java.util.Arrays;

/**
 * This class represents the attributes of an alarm.
 *
 * @author  Rob Whelan, Olivier Dedieu, David Sims, Simon B閏ot, Jim Lerner
 * @version 1.4.1, 2004/04/02
 */
public class AlarmEntry implements Comparable, java.io.Serializable {
    private int[] minutes = {-1};
    private static int minMinute = 0;
    private static int maxMinute = 59;
    
    private int[] hours = {-1};
    private static int minHour = 0;
    private static int maxHour = 23;
    
    private int[] daysOfMonth = {-1};
    private static int minDayOfMonth = 1;
    // maxDayOfMonth varies by month
    
    private int[] months = {-1};
    private static int minMonth = 0;
    private static int maxMonth = 11;
    
    private int[] daysOfWeek = {-1};
    private static int minDayOfWeek = 1;
    private static int maxDayOfWeek = 7;
    
    private int year = -1; // no support for a list of years -- must be * or specified
    
    private String name;
    private static int UNIQUE = 0; // used to generate names if they are null
    
    private boolean ringInNewThread = false;  // default: false
    
    private boolean isRelative;
    public boolean isRepeating;
    public long alarmTime;
    private long lastUpdateTime;
    private transient AlarmListener listener;
    private transient boolean debug = false;
    
    private void debug(String s) {
        if (debug)
            System.out.println("[" + Thread.currentThread().getName() + "] AlarmEntry "+name+": " + s);
    }
    
    /**
     * Creates a new AlarmEntry.  Fixed date format: this alarm will happen once, at
     * the timestamp given.
     *
     * @param date the alarm date to be added.
     * @param listener the alarm listener.
     * @exception PastDateException if the alarm date is in the past
     * (or less than 1 second away from the current date).
     */
    public AlarmEntry(String _name, Date _date, AlarmListener _listener)
    throws PastDateException {
        
        setName(_name);
        listener = _listener;
        Calendar alarm = Calendar.getInstance();
        alarm.setTime(_date);
        minutes = new int[] { alarm.get(Calendar.MINUTE) };
        hours = new int[] { alarm.get(Calendar.HOUR_OF_DAY) };
        daysOfMonth = new int[] { alarm.get(Calendar.DAY_OF_MONTH) };
        months = new int[] { alarm.get(Calendar.MONTH) };
        year = alarm.get( Calendar.YEAR );
        
        isRepeating = false;
        isRelative = false;
        alarmTime = _date.getTime();
        checkAlarmTime();
    }
    /** @deprecated for backwards compatibility, w/o name param: */
    public AlarmEntry(Date _date, AlarmListener _listener)
    throws PastDateException {
        this(null, _date, _listener);
    }
    
    /**
     * Creates a new AlarmEntry.  Delay format: this alarm will happen once or
     * repeatedly, at increments of the number of minutes given.
     *
     * @param _name keeps the alarm unique from other alarms with the same schedule, and used for debugging.
     * @param delayMinutes the alarm delay in minutes (relative to now).
     * @param isRepetitive <code>true</code> if the alarm must be
     * reactivated, <code>false</code> otherwise.
     * @param listener the alarm listener.
     * @exception PastDateException if the alarm date is in the past
     * (or less than 1 second closed to the current date).
     */
    public AlarmEntry(String _name, int _delayMinutes, boolean _isRepeating, AlarmListener _listener)
    throws PastDateException {
        if (_delayMinutes < 1) {
            throw new PastDateException();
        }
        
        setName(_name);
        minutes = new int[] { _delayMinutes };
        listener = _listener;
        isRepeating = _isRepeating;
        
        isRelative = true;
        updateAlarmTime();
    }
    /** @deprecated for backwards compatibility, w/o name param: */
    public AlarmEntry(int _delayMinutes, boolean _isRepeating, AlarmListener _listener)
    throws PastDateException {
        this(null, _delayMinutes, _isRepeating, _listener);
    }
    
    
    /**
     * <p>Creates a new AlarmEntry.  Basic cron format - use each field to
     * restrict alarms to a specific minute, hour, etc. OR pass in -1 to allow
     * all values of that field.</p>
     *
     * <p>Params of (30, 13, -1, -1, 2, -1, listener) schedule an alarm for
     * 1:30pm every Monday.</p>
     *
     * <p>NOTE: if both dayOfMonth and dayOfWeek are restricted, each alarm will
     * be scheduled for the sooner match.</p>
     *
     * @param minute minute of the alarm. Allowed values 0-59.
     * @param hour hour of the alarm. Allowed values 0-23.
     * @param dayOfMonth day of month of the alarm (-1 if every
     * day). Allowed values 1-31.
     * @param month month of the alarm (-1 if every month). Allowed values
     * 0-11 (0 = January, 1 = February, ...). <code>java.util.Calendar</code>
     * constants can be used.
     * @param dayOfWeek day of week of the alarm (-1 if every day). This
     * attribute is exclusive with <code>dayOfMonth</code>. Allowed values 1-7
     * (1 = Sunday, 2 = Monday, ...). <code>java.util.Calendar</code> constants
     * can be used.
     * @param year year of the alarm. When this field is not set (i.e. -1)
     * the alarm is repetitive (i.e. it is rescheduled when reached).
     * @param listener the alarm listener.
     * @return the AlarmEntry.
     * @exception PastDateException if the alarm date is in the past
     * (or less than 1 second away from the current date).
     */
    public AlarmEntry(String _name, int _minute, int _hour, int _dayOfMonth, int _month,
            int _dayOfWeek, int _year, AlarmListener _listener)
    throws PastDateException {
        this(_name, new int[]{_minute}, new int[]{_hour}, new int[]{_dayOfMonth}, new int[]{_month},
                new int[]{_dayOfWeek}, _year, _listener);
    }
    /** @deprecated for backwards compatibility, w/o name param: */
    public AlarmEntry(int _minute, int _hour, int _dayOfMonth, int _month,
            int _dayOfWeek, int _year, AlarmListener _listener)
    throws PastDateException {
        this(null, _minute, _hour, _dayOfMonth, _month,
                _dayOfWeek, _year, _listener);
    }
    
    
    /**
     * <p>Creates a new AlarmEntry.  Extended cron format - supports lists
     * of values for each field, or {-1} to allow all values for that field.</p>
     *
     * <p>Params of (30, 13, -1, -1, 2, -1, listener) schedule an alarm for
     * 1:30pm every Monday.</p>
     *
     * <p>NOTE: if both dayOfMonth and dayOfWeek are restricted, each alarm will
     * be scheduled for the sooner match.</p>
     *
     * @param minutes valid minutes of the alarm. Allowed values
     * 0-59, or {-1} for all.
     * @param hours valid hours of the alarm. Allowed values 0-23,
     * or {-1} for all.
     * @param daysOfMonth valid days of month of the alarm.  Allowed
     * values 1-31, or {-1} for all.
     * @param months valid months of the alarm. Allowed values
     * 0-11 (0 = January, 1 = February, ...), or {-1} for all.
     * <code>java.util.Calendar</code> constants can be used.
     * @param daysOfWeek valid days of week of the alarm. This attribute
     * is exclusive with <code>dayOfMonth</code>. Allowed values 1-7
     * (1 = Sunday, 2 = Monday, ...), or {-1} for all.
     * <code>java.util.Calendar</code> constants can be used.
     * @param year year of the alarm. When this field is not set (i.e. -1)
     * the alarm is repetitive (i.e. it is rescheduled when reached).
     * @param listener the alarm listener.
     * @return the AlarmEntry.
     * @exception PastDateException if the alarm date is in the past
     * (or less than 1 second away from the current date).
     */
    public AlarmEntry(String _name, int[] _minutes, int[] _hours, int[] _daysOfMonth, int[] _months,
            int[] _daysOfWeek, int _year, AlarmListener _listener)
    throws PastDateException {
        
        setName(_name);
        minutes = _minutes;
        hours = _hours;
        daysOfMonth = _daysOfMonth;
        months = _months;
        daysOfWeek = _daysOfWeek;
        year = _year;
        listener = _listener;
        isRepeating = (_year == -1);
        isRelative = false;
        
        updateAlarmTime();
        checkAlarmTime();
    }
    /** @deprecated for backwards compatibility, w/o name param: */
    public AlarmEntry( int[] _minutes, int[] _hours, int[] _daysOfMonth, int[] _months,
            int[] _daysOfWeek, int _year, AlarmListener _listener)
    throws PastDateException {
        this(null, _minutes, _hours, _daysOfMonth, _months,
                _daysOfWeek, _year, _listener);
    }
    
    /** 
     * Just make sure it's not null -- and if it is, make it unique.
     * @param _name
     */
    private void setName(String _name)
    {
        name = _name;
        if( name == null )
            name = "alarm" + (UNIQUE++);
    }
    
    public String getName() {
        return name;
    }
    
    /**
     * By default, the AlarmListeners for all alarms will be notified
     * in the same thread (so a long-running handleAlarm() implementation
     * will cause other alarms to wait until it completes).  Call this method
     * to notify the listener to this alarm in a new Thread, so other
     * alarms won't be delayed.
     */
    public void setRingInNewThead()
    {
        ringInNewThread = true;
    }
    public boolean isRingInNewThread()
    {
        return ringInNewThread;
    }
    
    
    /**
     * Checks that alarm is not in the past, or less than 1 second
     * away.
     *
     * @exception PastDateException if the alarm date is in the past
     * (or less than 1 second in the future).
     */
    void checkAlarmTime() throws PastDateException {
        long delay = alarmTime - System.currentTimeMillis();
        
        if (delay <= 1000) {
            throw new PastDateException();
        }
    }
    
    
    /**
     * Notifies the listener.
     */
    public void ringAlarm()
    {
        listener.handleAlarm(this);
    }
    
    /**
     * Updates this alarm entry to the next valid alarm time, AFTER the current time.
     */
    public void updateAlarmTime() {
        Calendar now = Calendar.getInstance();
        
        if (isRelative) {
            // relative only uses minutes field, with only a single value (NOT -1)
            alarmTime = now.getTime().getTime() + (minutes[0] * 60000);
            return;
        }
        
        Calendar alarm = (Calendar)now.clone();
        alarm.set( Calendar.SECOND, 0 );
        
        debug("now: " + now.getTime());
        
        //
        // the updates work in a cascade -- if next minute value is in the
        // following hour, hour is incremented.  If next valid hour value is
        // in the following day, day is incremented, and so on.
        //
        
        // increase alarm minutes
        int current = alarm.get( Calendar.MINUTE );
        int offset = 0;
        // force increment at least to next minute
        offset = getOffsetToNext( current, minMinute, maxMinute, minutes );
        alarm.add( Calendar.MINUTE, offset );
        debug( "after min: " + alarm.getTime() );
        
        // update alarm hours if necessary
        current = alarm.get( Calendar.HOUR_OF_DAY );  // (as updated by minute shift)
        offset = getOffsetToNextOrEqual( current, minHour, maxHour, hours );
        alarm.add( Calendar.HOUR_OF_DAY, offset );
        debug( "after hour (current:"+current+"): " + alarm.getTime() );
        
        //
        // If days of month AND days of week are restricted, we take whichever match
        // comes sooner.
        // If only one is restricted, take the first match for that one.
        // If neither is restricted, don't do anything.
        //
        if( daysOfMonth[0] != -1 && daysOfWeek[0] != -1 )
        {
            // BOTH are restricted - take earlier match
            Calendar dayOfWeekAlarm = (Calendar)alarm.clone();
            updateDayOfWeekAndMonth( dayOfWeekAlarm );
            
            Calendar dayOfMonthAlarm = (Calendar)alarm.clone();
            updateDayOfMonthAndMonth( dayOfMonthAlarm );
            
            // take the earlier one
            if( dayOfMonthAlarm.getTime().getTime() < dayOfWeekAlarm.getTime().getTime() )
            {
                alarm = dayOfMonthAlarm;
                debug( "after dayOfMonth CLOSER: " + alarm.getTime() );
            }
            else
            {
                alarm = dayOfWeekAlarm;
                debug( "after dayOfWeek CLOSER: " + alarm.getTime() );
            }
        }
        else if( daysOfWeek[0] != -1 ) // only dayOfWeek is restricted
        {
            // update dayInWeek and month if necessary
            updateDayOfWeekAndMonth( alarm );
            debug( "after dayOfWeek: " + alarm.getTime() );
        }
        else if( daysOfMonth[0] != -1 ) // only dayOfMonth is restricted
        {
            // update dayInMonth and month if necessary
            updateDayOfMonthAndMonth( alarm );
            debug( "after dayOfMonth: " + alarm.getTime() );
        }
        // else if neither is restricted (both[0] == -1), we don't need to do anything.
        
        
        debug("alarm: " + alarm.getTime());
        
        alarmTime = alarm.getTime().getTime();
        lastUpdateTime = System.currentTimeMillis();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -