KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jtheory > jdring > AlarmEntry


1 /*
2  * com/jtheory/jdring/AlarmEntry.java
3  * Copyright (C) 1999 - 2004 jtheory creations, Olivier Dedieu et al.
4  *
5  * This library is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU Library General Public License as published
7  * by the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  */

20
21 package com.jtheory.jdring;
22
23 import java.util.Calendar JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.Arrays JavaDoc;
26
27 /**
28  * This class represents the attributes of an alarm.
29  *
30  * @author Rob Whelan, Olivier Dedieu, David Sims, Simon Bécot, Jim Lerner
31  * @version 1.4.1, 2004/04/02
32  */

33 public class AlarmEntry implements Comparable JavaDoc, java.io.Serializable JavaDoc {
34     private int[] minutes = {-1};
35     private static int minMinute = 0;
36     private static int maxMinute = 59;
37     
38     private int[] hours = {-1};
39     private static int minHour = 0;
40     private static int maxHour = 23;
41     
42     private int[] daysOfMonth = {-1};
43     private static int minDayOfMonth = 1;
44     // maxDayOfMonth varies by month
45

46     private int[] months = {-1};
47     private static int minMonth = 0;
48     private static int maxMonth = 11;
49     
50     private int[] daysOfWeek = {-1};
51     private static int minDayOfWeek = 1;
52     private static int maxDayOfWeek = 7;
53     
54     private int year = -1; // no support for a list of years -- must be * or specified
55

56     private String JavaDoc name;
57     private static int UNIQUE = 0; // used to generate names if they are null
58

59     private boolean ringInNewThread = false; // default: false
60

61     private boolean isRelative;
62     public boolean isRepeating;
63     public long alarmTime;
64     private long lastUpdateTime;
65     private transient AlarmListener listener;
66     private transient boolean debug = false;
67     
68     private void debug(String JavaDoc s) {
69         if (debug)
70             System.out.println("[" + Thread.currentThread().getName() + "] AlarmEntry "+name+": " + s);
71     }
72     
73     /**
74      * Creates a new AlarmEntry. Fixed date format: this alarm will happen once, at
75      * the timestamp given.
76      *
77      * @param date the alarm date to be added.
78      * @param listener the alarm listener.
79      * @exception PastDateException if the alarm date is in the past
80      * (or less than 1 second away from the current date).
81      */

82     public AlarmEntry(String JavaDoc _name, Date JavaDoc _date, AlarmListener _listener)
83     throws PastDateException {
84         
85         setName(_name);
86         listener = _listener;
87         Calendar JavaDoc alarm = Calendar.getInstance();
88         alarm.setTime(_date);
89         minutes = new int[] { alarm.get(Calendar.MINUTE) };
90         hours = new int[] { alarm.get(Calendar.HOUR_OF_DAY) };
91         daysOfMonth = new int[] { alarm.get(Calendar.DAY_OF_MONTH) };
92         months = new int[] { alarm.get(Calendar.MONTH) };
93         year = alarm.get( Calendar.YEAR );
94         
95         isRepeating = false;
96         isRelative = false;
97         alarmTime = _date.getTime();
98         checkAlarmTime();
99     }
100     /** @deprecated for backwards compatibility, w/o name param: */
101     public AlarmEntry(Date JavaDoc _date, AlarmListener _listener)
102     throws PastDateException {
103         this(null, _date, _listener);
104     }
105     
106     /**
107      * Creates a new AlarmEntry. Delay format: this alarm will happen once or
108      * repeatedly, at increments of the number of minutes given.
109      *
110      * @param _name keeps the alarm unique from other alarms with the same schedule, and used for debugging.
111      * @param delayMinutes the alarm delay in minutes (relative to now).
112      * @param isRepetitive <code>true</code> if the alarm must be
113      * reactivated, <code>false</code> otherwise.
114      * @param listener the alarm listener.
115      * @exception PastDateException if the alarm date is in the past
116      * (or less than 1 second closed to the current date).
117      */

118     public AlarmEntry(String JavaDoc _name, int _delayMinutes, boolean _isRepeating, AlarmListener _listener)
119     throws PastDateException {
120         if (_delayMinutes < 1) {
121             throw new PastDateException();
122         }
123         
124         setName(_name);
125         minutes = new int[] { _delayMinutes };
126         listener = _listener;
127         isRepeating = _isRepeating;
128         
129         isRelative = true;
130         updateAlarmTime();
131     }
132     /** @deprecated for backwards compatibility, w/o name param: */
133     public AlarmEntry(int _delayMinutes, boolean _isRepeating, AlarmListener _listener)
134     throws PastDateException {
135         this(null, _delayMinutes, _isRepeating, _listener);
136     }
137     
138     
139     /**
140      * <p>Creates a new AlarmEntry. Basic cron format - use each field to
141      * restrict alarms to a specific minute, hour, etc. OR pass in -1 to allow
142      * all values of that field.</p>
143      *
144      * <p>Params of (30, 13, -1, -1, 2, -1, listener) schedule an alarm for
145      * 1:30pm every Monday.</p>
146      *
147      * <p>NOTE: if both dayOfMonth and dayOfWeek are restricted, each alarm will
148      * be scheduled for the sooner match.</p>
149      *
150      * @param minute minute of the alarm. Allowed values 0-59.
151      * @param hour hour of the alarm. Allowed values 0-23.
152      * @param dayOfMonth day of month of the alarm (-1 if every
153      * day). Allowed values 1-31.
154      * @param month month of the alarm (-1 if every month). Allowed values
155      * 0-11 (0 = January, 1 = February, ...). <code>java.util.Calendar</code>
156      * constants can be used.
157      * @param dayOfWeek day of week of the alarm (-1 if every day). This
158      * attribute is exclusive with <code>dayOfMonth</code>. Allowed values 1-7
159      * (1 = Sunday, 2 = Monday, ...). <code>java.util.Calendar</code> constants
160      * can be used.
161      * @param year year of the alarm. When this field is not set (i.e. -1)
162      * the alarm is repetitive (i.e. it is rescheduled when reached).
163      * @param listener the alarm listener.
164      * @return the AlarmEntry.
165      * @exception PastDateException if the alarm date is in the past
166      * (or less than 1 second away from the current date).
167      */

168     public AlarmEntry(String JavaDoc _name, int _minute, int _hour, int _dayOfMonth, int _month,
169             int _dayOfWeek, int _year, AlarmListener _listener)
170     throws PastDateException {
171         this(_name, new int[]{_minute}, new int[]{_hour}, new int[]{_dayOfMonth}, new int[]{_month},
172                 new int[]{_dayOfWeek}, _year, _listener);
173     }
174     /** @deprecated for backwards compatibility, w/o name param: */
175     public AlarmEntry(int _minute, int _hour, int _dayOfMonth, int _month,
176             int _dayOfWeek, int _year, AlarmListener _listener)
177     throws PastDateException {
178         this(null, _minute, _hour, _dayOfMonth, _month,
179                 _dayOfWeek, _year, _listener);
180     }
181     
182     
183     /**
184      * <p>Creates a new AlarmEntry. Extended cron format - supports lists
185      * of values for each field, or {-1} to allow all values for that field.</p>
186      *
187      * <p>Params of (30, 13, -1, -1, 2, -1, listener) schedule an alarm for
188      * 1:30pm every Monday.</p>
189      *
190      * <p>NOTE: if both dayOfMonth and dayOfWeek are restricted, each alarm will
191      * be scheduled for the sooner match.</p>
192      *
193      * @param minutes valid minutes of the alarm. Allowed values
194      * 0-59, or {-1} for all.
195      * @param hours valid hours of the alarm. Allowed values 0-23,
196      * or {-1} for all.
197      * @param daysOfMonth valid days of month of the alarm. Allowed
198      * values 1-31, or {-1} for all.
199      * @param months valid months of the alarm. Allowed values
200      * 0-11 (0 = January, 1 = February, ...), or {-1} for all.
201      * <code>java.util.Calendar</code> constants can be used.
202      * @param daysOfWeek valid days of week of the alarm. This attribute
203      * is exclusive with <code>dayOfMonth</code>. Allowed values 1-7
204      * (1 = Sunday, 2 = Monday, ...), or {-1} for all.
205      * <code>java.util.Calendar</code> constants can be used.
206      * @param year year of the alarm. When this field is not set (i.e. -1)
207      * the alarm is repetitive (i.e. it is rescheduled when reached).
208      * @param listener the alarm listener.
209      * @return the AlarmEntry.
210      * @exception PastDateException if the alarm date is in the past
211      * (or less than 1 second away from the current date).
212      */

213     public AlarmEntry(String JavaDoc _name, int[] _minutes, int[] _hours, int[] _daysOfMonth, int[] _months,
214             int[] _daysOfWeek, int _year, AlarmListener _listener)
215     throws PastDateException {
216         
217         setName(_name);
218         minutes = _minutes;
219         hours = _hours;
220         daysOfMonth = _daysOfMonth;
221         months = _months;
222         daysOfWeek = _daysOfWeek;
223         year = _year;
224         listener = _listener;
225         isRepeating = (_year == -1);
226         isRelative = false;
227         
228         updateAlarmTime();
229         checkAlarmTime();
230     }
231     /** @deprecated for backwards compatibility, w/o name param: */
232     public AlarmEntry( int[] _minutes, int[] _hours, int[] _daysOfMonth, int[] _months,
233             int[] _daysOfWeek, int _year, AlarmListener _listener)
234     throws PastDateException {
235         this(null, _minutes, _hours, _daysOfMonth, _months,
236                 _daysOfWeek, _year, _listener);
237     }
238     
239     /**
240      * Just make sure it's not null -- and if it is, make it unique.
241      * @param _name
242      */

243     private void setName(String JavaDoc _name)
244     {
245         name = _name;
246         if( name == null )
247             name = "alarm" + (UNIQUE++);
248     }
249     
250     public String JavaDoc getName() {
251         return name;
252     }
253     
254     /**
255      * By default, the AlarmListeners for all alarms will be notified
256      * in the same thread (so a long-running handleAlarm() implementation
257      * will cause other alarms to wait until it completes). Call this method
258      * to notify the listener to this alarm in a new Thread, so other
259      * alarms won't be delayed.
260      */

261     public void setRingInNewThead()
262     {
263         ringInNewThread = true;
264     }
265     public boolean isRingInNewThread()
266     {
267         return ringInNewThread;
268     }
269     
270     
271     /**
272      * Checks that alarm is not in the past, or less than 1 second
273      * away.
274      *
275      * @exception PastDateException if the alarm date is in the past
276      * (or less than 1 second in the future).
277      */

278     void checkAlarmTime() throws PastDateException {
279         long delay = alarmTime - System.currentTimeMillis();
280         
281         if (delay <= 1000) {
282             throw new PastDateException();
283         }
284     }
285     
286     
287     /**
288      * Notifies the listener.
289      */

290     public void ringAlarm()
291     {
292         listener.handleAlarm(this);
293     }
294     
295     /**
296      * Updates this alarm entry to the next valid alarm time, AFTER the current time.
297      */

298     public void updateAlarmTime() {
299         Calendar JavaDoc now = Calendar.getInstance();
300         
301         if (isRelative) {
302             // relative only uses minutes field, with only a single value (NOT -1)
303
alarmTime = now.getTime().getTime() + (minutes[0] * 60000);
304             return;
305         }
306         
307         Calendar JavaDoc alarm = (Calendar JavaDoc)now.clone();
308         alarm.set( Calendar.SECOND, 0 );
309         
310         debug("now: " + now.getTime());
311         
312         //
313
// the updates work in a cascade -- if next minute value is in the
314
// following hour, hour is incremented. If next valid hour value is
315
// in the following day, day is incremented, and so on.
316
//
317

318         // increase alarm minutes
319
int current = alarm.get( Calendar.MINUTE );
320         int offset = 0;
321         // force increment at least to next minute
322
offset = getOffsetToNext( current, minMinute, maxMinute, minutes );
323         alarm.add( Calendar.MINUTE, offset );
324         debug( "after min: " + alarm.getTime() );
325         
326         // update alarm hours if necessary
327
current = alarm.get( Calendar.HOUR_OF_DAY ); // (as updated by minute shift)
328
offset = getOffsetToNextOrEqual( current, minHour, maxHour, hours );
329         alarm.add( Calendar.HOUR_OF_DAY, offset );
330         debug( "after hour (current:"+current+"): " + alarm.getTime() );
331         
332         //
333
// If days of month AND days of week are restricted, we take whichever match
334
// comes sooner.
335
// If only one is restricted, take the first match for that one.
336
// If neither is restricted, don't do anything.
337
//
338
if( daysOfMonth[0] != -1 && daysOfWeek[0] != -1 )
339         {
340             // BOTH are restricted - take earlier match
341
Calendar JavaDoc dayOfWeekAlarm = (Calendar JavaDoc)alarm.clone();
342             updateDayOfWeekAndMonth( dayOfWeekAlarm );
343             
344             Calendar JavaDoc dayOfMonthAlarm = (Calendar JavaDoc)alarm.clone();
345             updateDayOfMonthAndMonth( dayOfMonthAlarm );
346             
347             // take the earlier one
348
if( dayOfMonthAlarm.getTime().getTime() < dayOfWeekAlarm.getTime().getTime() )
349             {
350                 alarm = dayOfMonthAlarm;
351                 debug( "after dayOfMonth CLOSER: " + alarm.getTime() );
352             }
353             else
354             {
355                 alarm = dayOfWeekAlarm;
356                 debug( "after dayOfWeek CLOSER: " + alarm.getTime() );
357             }
358         }
359         else if( daysOfWeek[0] != -1 ) // only dayOfWeek is restricted
360
{
361             // update dayInWeek and month if necessary
362
updateDayOfWeekAndMonth( alarm );
363             debug( "after dayOfWeek: " + alarm.getTime() );
364         }
365         else if( daysOfMonth[0] != -1 ) // only dayOfMonth is restricted
366
{
367             // update dayInMonth and month if necessary
368
updateDayOfMonthAndMonth( alarm );
369             debug( "after dayOfMonth: " + alarm.getTime() );
370         }
371         // else if neither is restricted (both[0] == -1), we don't need to do anything.
372

373         
374         debug("alarm: " + alarm.getTime());
375         
376         alarmTime = alarm.getTime().getTime();
377         lastUpdateTime = System.currentTimeMillis();
378     }
379     
380     /**
381      * daysInMonth can't use simple offsets like the other fields, because the
382      * number of days varies per month (think of an alarm that executes on every
383      * 31st). Instead we advance month and dayInMonth together until we're on a
384      * matching value pair.
385      */

386     void updateDayOfMonthAndMonth( Calendar JavaDoc alarm )
387     {
388         int currentMonth = alarm.get( Calendar.MONTH );
389         int currentDayOfMonth = alarm.get( Calendar.DAY_OF_MONTH );
390         int offset = 0;
391         
392         // loop until we have a valid day AND month (if current is invalid)
393
while( !isIn(currentMonth, months) || !isIn(currentDayOfMonth, daysOfMonth) )
394         {
395             // if current month is invalid, advance to 1st day of next valid month
396
if( !isIn(currentMonth, months) )
397             {
398                 offset = getOffsetToNextOrEqual( currentMonth, minMonth, maxMonth, months );
399                 alarm.add( Calendar.MONTH, offset );
400                 alarm.set( Calendar.DAY_OF_MONTH, 1 );
401                 currentDayOfMonth = 1;
402             }
403             
404             // advance to the next valid day of month, if necessary
405
if( !isIn(currentDayOfMonth, daysOfMonth) )
406             {
407                 int maxDayOfMonth = alarm.getActualMaximum( Calendar.DAY_OF_MONTH );
408                 offset = getOffsetToNextOrEqual( currentDayOfMonth, minDayOfMonth, maxDayOfMonth, daysOfMonth );
409                 alarm.add( Calendar.DAY_OF_MONTH, offset );
410             }
411             
412             currentMonth = alarm.get( Calendar.MONTH );
413             currentDayOfMonth = alarm.get( Calendar.DAY_OF_MONTH );
414         }
415     }
416     
417     
418     void updateDayOfWeekAndMonth( Calendar JavaDoc alarm )
419     {
420         int currentMonth = alarm.get( Calendar.MONTH );
421         int currentDayOfWeek = alarm.get( Calendar.DAY_OF_WEEK );
422         int offset = 0;
423         
424         // loop until we have a valid day AND month (if current is invalid)
425
while( !isIn(currentMonth, months) || !isIn(currentDayOfWeek, daysOfWeek) )
426         {
427             // if current month is invalid, advance to 1st day of next valid month
428
if( !isIn(currentMonth, months) )
429             {
430                 offset = getOffsetToNextOrEqual( currentMonth, minMonth, maxMonth, months );
431                 alarm.add( Calendar.MONTH, offset );
432                 alarm.set( Calendar.DAY_OF_MONTH, 1 );
433                 currentDayOfWeek = alarm.get( Calendar.DAY_OF_WEEK );
434             }
435             
436             // advance to the next valid day of week, if necessary
437
if( !isIn(currentDayOfWeek, daysOfWeek) )
438             {
439                 offset = getOffsetToNextOrEqual( currentDayOfWeek, minDayOfWeek, maxDayOfWeek, daysOfWeek );
440                 alarm.add( Calendar.DAY_OF_YEAR, offset );
441             }
442             
443             currentDayOfWeek = alarm.get( Calendar.DAY_OF_WEEK );
444             currentMonth = alarm.get( Calendar.MONTH );
445         }
446     }
447     
448     
449     
450     // ----------------------------------------------------------------------
451
// General utility methods
452
// ----------------------------------------------------------------------
453

454     /**
455      * if values = {-1}
456      * offset is 1 (because next value definitely matches)
457      * if current < last(values)
458      * offset is diff to next valid value
459      * if current >= last(values)
460      * offset is diff to values[0], wrapping from max to min
461      */

462     static int getOffsetToNext( int current, int min, int max, int[] values )
463     {
464         int offset = 0;
465         
466         // find the distance to the closest valid value > current (wrapping if neccessary)
467

468         // {-1} means * -- offset is 1 because current++ is valid value
469
if (values[0] == -1 )
470         {
471             offset = 1;
472         }
473         else
474         {
475             // need to wrap
476
if( current >= last(values) )
477             {
478                 int next = values[0];
479                 offset = (max-current+1) + (next-min);
480             }
481             else // current < max(values) -- find next valid value after current
482
{
483                 findvalue:
484                 for( int i=0; i<values.length; i++ )
485                 {
486                     if( current < values[i] )
487                     {
488                         offset = values[i] - current;
489                         break findvalue;
490                     }
491                 }
492             } // end current < max(values)
493
}
494         
495         return offset;
496     }
497     
498     /**
499      * if values = {-1} or current is valid
500      * offset is 0.
501      * if current < last(values)
502      * offset is diff to next valid value
503      * if current >= last(values)
504      * offset is diff to values[0], wrapping from max to min
505      */

506     static int getOffsetToNextOrEqual( int current, int min, int max, int[] values )
507     {
508         int offset = 0;
509         int[] safeValues = null;
510         
511         // find the distance to the closest valid value >= current (wrapping if necessary)
512

513         // {-1} means * -- offset is 0 if current is valid value
514
if (values[0] == -1 || isIn(current, values) )
515         {
516             offset = 0;
517         }
518         else
519         {
520             safeValues = discardValuesOverMax( values, max );
521             
522             // need to wrap
523
if( current > last(safeValues) )
524             {
525                 int next = safeValues[0];
526                 offset = (max-current+1) + (next-min);
527             }
528             else // current <= max(values) -- find next valid value
529
{
530                 findvalue:
531                 for( int i=0; i<values.length; i++ )
532                 {
533                     if( current < safeValues[i] )
534                     {
535                         offset = safeValues[i] - current;
536                         break findvalue;
537                     }
538                 }
539             } // end current <= max(values)
540
}
541         
542         return offset;
543     }
544     
545     /**
546      * handles -1 in values as * and returns true
547      * otherwise returns true iff given value is in the array
548      */

549     static boolean isIn( int find, int[] values )
550     {
551         if( values[0] == -1 )
552         {
553             return true;
554         }
555         else
556         {
557             for( int i=0; i<values.length; i++ )
558             {
559                 if( find == values[i] )
560                     return true;
561             }
562             return false;
563         }
564     }
565     
566     /**
567      * @return the last int in the array
568      */

569     static int last( int[] intArray )
570     {
571         return intArray[ intArray.length - 1 ];
572     }
573     
574     /**
575      * Assumes inputted values are not null, have at least one value, and are in
576      * ascending order.
577      * @return copy of values without any trailing values that exceed the max
578      */

579     static int[] discardValuesOverMax( int[] values, int max )
580     {
581         int[] safeValues = null;
582         for( int i=0; i<values.length; i++ )
583         {
584             if( values[i] > max )
585             {
586                 safeValues = new int[i];
587                 System.arraycopy( values, 0, safeValues, 0, i );
588                 return safeValues;
589             }
590         }
591         return values;
592     }
593
594     
595     private static String JavaDoc arrToString( int[] intArray )
596     {
597         if( intArray == null )
598             return "null";
599         if( intArray.length == 0 )
600             return "{}";
601         
602         String JavaDoc s = "{";
603         for( int i=0; i<intArray.length-1; i++ )
604         {
605             s += intArray[i] + ", ";
606         }
607         s += intArray[intArray.length-1] + "}";
608         
609         return s;
610     }
611     
612     // ----------------------------------------------------------------------
613
// Comparable interface
614
// ----------------------------------------------------------------------
615

616     /**
617      * Compares this AlarmEntry with the specified AlarmEntry for order.
618      * One twist -- if the alarmTime matches, this alarm will STILL place
619      * itself before the other based on the lastUpdateTime. If the other
620      * alarm has been rung more recently, this one should get priority.
621      *
622      * @param obj the AlarmEntry with which to compare.
623      * @return a negative integer, zero, or a positive integer as this
624      * AlarmEntry is less than, equal to, or greater than the given
625      * AlarmEntry.
626      * @exception ClassCastException if the specified Object's type
627      * prevents it from being compared to this AlarmEntry.
628      */

629     public int compareTo(Object JavaDoc obj) {
630         AlarmEntry other = (AlarmEntry)obj;
631         if (alarmTime < other.alarmTime)
632             return -1;
633         else if (alarmTime > other.alarmTime)
634             return 1;
635         else // alarmTime == other.alarmTime
636
{
637             if( lastUpdateTime < other.lastUpdateTime )
638                 return -1;
639             else if( lastUpdateTime > other.lastUpdateTime)
640                 return 1;
641             else
642                 return 0;
643         }
644     }
645     
646     
647     /**
648      * Indicates whether some other AlarmEntry is "equal to" this one.
649      * This is where the name is important, since two alarms can have the
650      * exact same schedule.
651      *
652      * @param obj the AlarmEntry with which to compare.
653      * @return <code>true if this AlarmEntry has the same name,
654      * <code>alarmTime</code> AND the same schedule as the
655      * obj argument;
656      * <code>false</code> otherwise.
657      */

658     public boolean equals(Object JavaDoc obj) {
659         AlarmEntry entry = null;
660         
661         if( obj == null || !(obj instanceof AlarmEntry) )
662             return false;
663         
664         entry = (AlarmEntry)obj;
665         return ( name.equals(entry.name)
666                 && alarmTime == entry.alarmTime
667                 && isRelative == entry.isRelative
668                 && isRepeating == entry.isRepeating
669                 && Arrays.equals(minutes, entry.minutes)
670                 && Arrays.equals(hours, entry.hours)
671                 && Arrays.equals(daysOfMonth, entry.daysOfMonth)
672                 && Arrays.equals(months, entry.months)
673                 && Arrays.equals(daysOfWeek, entry.daysOfWeek) );
674     }
675     
676     
677     
678     /**
679      * @return a string representation of this alarm.
680      */

681     public String JavaDoc toString() {
682         if (year != -1) {
683             return "Alarm ("+name+") at " + new Date JavaDoc(alarmTime);
684         }
685         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Alarm ("+name+") params");
686         sb.append(" minute="); sb.append( arrToString(minutes) );
687         sb.append(" hour="); sb.append( arrToString(hours) );
688         sb.append(" dayOfMonth="); sb.append( arrToString(daysOfMonth) );
689         sb.append(" month="); sb.append( arrToString(months) );
690         sb.append(" dayOfWeek="); sb.append( arrToString(daysOfWeek) );
691         sb.append(" (next alarm date=" + new Date JavaDoc(alarmTime) + ")");
692         return sb.toString();
693     }
694     
695     
696     /**
697      * some unit testing...
698      */

699     public static void main( String JavaDoc[] args ) {
700         
701         System.out.println( "GETTING OFFSETS" );
702         
703         System.out.println( "getOffsetToNext(3, 0, 11, new int[]{3,5,7,9}) = " +
704                 getOffsetToNext(3, 0, 11, new int[]{3,5,7,9}) );
705         System.out.println( "getOffsetToNextOrEqual(3, 0, 11, new int[]{3,5,7,9}) = " +
706                 getOffsetToNextOrEqual(3, 0, 11, new int[]{3,5,7,9}) );
707         
708         System.out.println();
709         System.out.println( "getOffsetToNext(9, 0, 11, new int[]{3,5,7,9}) = " +
710                 getOffsetToNext(9, 0, 11, new int[]{3,5,7,9}) );
711         System.out.println( "getOffsetToNextOrEqual(9, 0, 11, new int[]{3,5,7,9}) = " +
712                 getOffsetToNextOrEqual(9, 0, 11, new int[]{3,5,7,9}) );
713         
714         System.out.println();
715         System.out.println( "getOffsetToNext(0, 0, 11, new int[]{0}) = " +
716                 getOffsetToNext(0, 0, 11, new int[]{0}) );
717         System.out.println( "getOffsetToNextOrEqual(0, 0, 11, new int[]{0}) = " +
718                 getOffsetToNextOrEqual(0, 0, 11, new int[]{0}) );
719         
720         System.out.println();
721         System.out.println( "getOffsetToNext(5, 0, 11, new int[]{5}) = " +
722                 getOffsetToNext(5, 0, 11, new int[]{5}) );
723         System.out.println( "getOffsetToNextOrEqual(5, 0, 11, new int[]{5}) = " +
724                 getOffsetToNextOrEqual(5, 0, 11, new int[]{5}) );
725         
726         System.out.println();
727         System.out.println( "getOffsetToNext(0, 0, 11, new int[]{-1}) = " +
728                 getOffsetToNext(0, 0, 11, new int[]{-1}) );
729         System.out.println( "getOffsetToNextOrEqual(0, 0, 11, new int[]{-1}) = " +
730                 getOffsetToNextOrEqual(0, 0, 11, new int[]{-1}) );
731         
732         System.out.println();
733         
734         System.out.println();
735         System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 4)) = " +
736                 arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 4)) );
737         System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 6)) = " +
738                 arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 6)) );
739         System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 0)) = " +
740                 arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 0)) );
741         System.out.println( "discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 7)) = " +
742                 arrToString(discardValuesOverMax(new int[]{0,1,2,3,4,5,6}, 7)) );
743     }
744 }
745
746
747
748
749
750
751
752
753
754
Popular Tags