KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > quartz > Trigger


1
2 /*
3  * Copyright 2004-2005 OpenSymphony
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6  * use this file except in compliance with the License. You may obtain a copy
7  * of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations
15  * under the License.
16  *
17  */

18
19 /*
20  * Previously Copyright (c) 2001-2004 James House
21  */

22 package org.quartz;
23
24 import java.util.Date JavaDoc;
25 import java.util.LinkedList JavaDoc;
26
27 import org.quartz.utils.Key;
28
29
30 /**
31  * <p>
32  * The base abstract class to be extended by all <code>Trigger</code>s.
33  * </p>
34  *
35  * <p>
36  * <code>Triggers</code> s have a name and group associated with them, which
37  * should uniquely identify them within a single <code>{@link Scheduler}</code>.
38  * </p>
39  *
40  * <p>
41  * <code>Trigger</code>s are the 'mechanism' by which <code>Job</code> s
42  * are scheduled. Many <code>Trigger</code> s can point to the same <code>Job</code>,
43  * but a single <code>Trigger</code> can only point to one <code>Job</code>.
44  * </p>
45  *
46  * <p>
47  * Triggers can 'send' parameters/data to <code>Job</code>s by placing contents
48  * into the <code>JobDataMap</code> on the <code>Trigger</code>.
49  * </p>
50  *
51  * @see SimpleTrigger
52  * @see CronTrigger
53  * @see NthIncludedDayTrigger
54  * @see TriggerUtils
55  * @see JobDataMap
56  * @see JobExecutionContext
57  *
58  * @author James House
59  * @author Sharada Jambula
60  */

61 public abstract class Trigger implements java.io.Serializable JavaDoc, Cloneable JavaDoc,
62         Comparable JavaDoc {
63
64     private static final long serialVersionUID = -3904243490805975570L;
65
66     /*
67     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68     *
69     * Constants.
70     *
71     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72     */

73
74     /**
75      * <p>
76      * Instructs the <code>{@link Scheduler}</code> that the <code>{@link Trigger}</code>
77      * has no further instructions.
78      * </p>
79      */

80     public static final int INSTRUCTION_NOOP = 0;
81
82     /**
83      * <p>
84      * Instructs the <code>{@link Scheduler}</code> that the <code>{@link Trigger}</code>
85      * wants the <code>{@link org.quartz.JobDetail}</code> to re-execute
86      * immediately. If not in a 'RECOVERING' or 'FAILED_OVER' situation, the
87      * execution context will be re-used (giving the <code>Job</code> the
88      * abilitiy to 'see' anything placed in the context by its last execution).
89      * </p>
90      */

91     public static final int INSTRUCTION_RE_EXECUTE_JOB = 1;
92
93     /**
94      * <p>
95      * Instructs the <code>{@link Scheduler}</code> that the <code>{@link Trigger}</code>
96      * should be put in the <code>COMPLETE</code> state.
97      * </p>
98      */

99     public static final int INSTRUCTION_SET_TRIGGER_COMPLETE = 2;
100
101     /**
102      * <p>
103      * Instructs the <code>{@link Scheduler}</code> that the <code>{@link Trigger}</code>
104      * wants itself deleted.
105      * </p>
106      */

107     public static final int INSTRUCTION_DELETE_TRIGGER = 3;
108
109     /**
110      * <p>
111      * Instructs the <code>{@link Scheduler}</code> that all <code>Trigger</code>
112      * s referencing the same <code>{@link org.quartz.JobDetail}</code> as
113      * this one should be put in the <code>COMPLETE</code> state.
114      * </p>
115      */

116     public static final int INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE = 4;
117
118     /**
119      * <p>
120      * Instructs the <code>{@link Scheduler}</code> that all <code>Trigger</code>
121      * s referencing the same <code>{@link org.quartz.JobDetail}</code> as
122      * this one should be put in the <code>ERROR</code> state.
123      * </p>
124      */

125     public static final int INSTRUCTION_SET_TRIGGER_ERROR = 5;
126
127     /**
128      * <p>
129      * Instructs the <code>{@link Scheduler}</code> that the <code>Trigger</code>
130      * should be put in the <code>ERROR</code> state.
131      * </p>
132      */

133     public static final int INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR = 6;
134
135     /**
136      * <p>
137      * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire
138      * situation, the <code>updateAfterMisfire()</code> method will be called
139      * on the <code>Trigger</code> to determine the mis-fire instruction.
140      * </p>
141      *
142      * <p>
143      * In order to see if this instruction fits your needs, you should look at
144      * the documentation for the <code>getSmartMisfirePolicy()</code> method
145      * on the particular <code>Trigger</code> implementation you are using.
146      * </p>
147      */

148     public static final int MISFIRE_INSTRUCTION_SMART_POLICY = 0;
149
150     /**
151      * <p>
152      * Indicates that the <code>Trigger</code> is in the "normal" state.
153      * </p>
154      */

155     public static final int STATE_NORMAL = 0;
156
157     /**
158      * <p>
159      * Indicates that the <code>Trigger</code> is in the "paused" state.
160      * </p>
161      */

162     public static final int STATE_PAUSED = 1;
163
164     /**
165      * <p>
166      * Indicates that the <code>Trigger</code> is in the "complete" state.
167      * </p>
168      *
169      * <p>
170      * "Complete" indicates that the trigger has not remaining fire-times in
171      * its schedule.
172      * </p>
173      */

174     public static final int STATE_COMPLETE = 2;
175
176     /**
177      * <p>
178      * Indicates that the <code>Trigger</code> is in the "error" state.
179      * </p>
180      *
181      * <p>
182      * A <code>Trigger</code> arrives at the error state when the scheduler
183      * attempts to fire it, but cannot due to an error creating and executing
184      * its related job. Often this is due to the <code>Job</code>'s
185      * class not existing in the classpath.
186      * </p>
187      *
188      * <p>
189      * When the trigger is in the error state, the scheduler will make no
190      * attempts to fire it.
191      * </p>
192      */

193     public static final int STATE_ERROR = 3;
194
195
196     /**
197      * <p>
198      * Indicates that the <code>Trigger</code> is in the "blocked" state.
199      * </p>
200      *
201      * <p>
202      * A <code>Trigger</code> arrives at the blocked state when the job that
203      * it is associated with is a <code>StatefulJob</code> and it is
204      * currently executing.
205      * </p>
206      *
207      * @see StatefulJob
208      */

209     public static final int STATE_BLOCKED = 4;
210
211     /**
212      * <p>
213      * Indicates that the <code>Trigger</code> does not exist.
214      * </p>
215      */

216     public static final int STATE_NONE = -1;
217
218     /**
219      * The default value for priority.
220      */

221     public static final int DEFAULT_PRIORITY = 5;
222
223     /*
224     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
225     *
226     * Data members.
227     *
228     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229     */

230
231     private String JavaDoc name;
232
233     private String JavaDoc group = Scheduler.DEFAULT_GROUP;
234
235     private String JavaDoc jobName;
236
237     private String JavaDoc jobGroup = Scheduler.DEFAULT_GROUP;
238
239     private String JavaDoc description;
240
241     private JobDataMap jobDataMap;
242
243     private boolean volatility = false;
244
245     private String JavaDoc calendarName = null;
246
247     private String JavaDoc fireInstanceId = null;
248
249     private int misfireInstruction = MISFIRE_INSTRUCTION_SMART_POLICY;
250
251     private LinkedList JavaDoc triggerListeners = new LinkedList JavaDoc();
252
253     private int priority = DEFAULT_PRIORITY;
254
255     private transient Key key = null;
256
257     /*
258     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259     *
260     * Constructors.
261     *
262     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
263     */

264
265
266
267     /**
268      * <p>
269      * Create a <code>Trigger</code> with no specified name, group, or <code>{@link org.quartz.JobDetail}</code>.
270      * </p>
271      *
272      * <p>
273      * Note that the {@link #setName(String)},{@link #setGroup(String)}and
274      * the {@link #setJobName(String)}and {@link #setJobGroup(String)}methods
275      * must be called before the <code>Trigger</code> can be placed into a
276      * {@link Scheduler}.
277      * </p>
278      */

279     public Trigger() {
280         // do nothing...
281
}
282
283     /**
284      * <p>
285      * Create a <code>Trigger</code> with the given name, and group.
286      * </p>
287      *
288      * <p>
289      * Note that the {@link #setJobName(String)}and
290      * {@link #setJobGroup(String)}methods must be called before the <code>Trigger</code>
291      * can be placed into a {@link Scheduler}.
292      * </p>
293      *
294      * @param group if <code>null</code>, Scheduler.DEFAULT_GROUP will be used.
295      *
296      * @exception IllegalArgumentException
297      * if name is null or empty, or the group is an empty string.
298      */

299     public Trigger(String JavaDoc name, String JavaDoc group) {
300         setName(name);
301         setGroup(group);
302     }
303
304     /**
305      * <p>
306      * Create a <code>Trigger</code> with the given name, and group.
307      * </p>
308      *
309      * @param group if <code>null</code>, Scheduler.DEFAULT_GROUP will be used.
310      *
311      * @exception IllegalArgumentException
312      * if name is null or empty, or the group is an empty string.
313      */

314     public Trigger(String JavaDoc name, String JavaDoc group, String JavaDoc jobName, String JavaDoc jobGroup) {
315         setName(name);
316         setGroup(group);
317         setJobName(jobName);
318         setJobGroup(jobGroup);
319     }
320
321     /*
322      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
323      *
324      * Interface.
325      *
326      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
327      */

328
329     /**
330      * <p>
331      * Get the name of this <code>Trigger</code>.
332      * </p>
333      */

334     public String JavaDoc getName() {
335         return name;
336     }
337
338     /**
339      * <p>
340      * Set the name of this <code>Trigger</code>.
341      * </p>
342      *
343      * @exception IllegalArgumentException
344      * if name is null or empty.
345      */

346     public void setName(String JavaDoc name) {
347         if (name == null || name.trim().length() == 0) {
348             throw new IllegalArgumentException JavaDoc(
349                     "Trigger name cannot be null or empty.");
350         }
351
352         this.name = name;
353     }
354
355     /**
356      * <p>
357      * Get the group of this <code>Trigger</code>.
358      * </p>
359      */

360     public String JavaDoc getGroup() {
361         return group;
362     }
363
364     /**
365      * <p>
366      * Set the name of this <code>Trigger</code>.
367      * </p>
368      *
369      * @param group if <code>null</code>, Scheduler.DEFAULT_GROUP will be used.
370      *
371      * @exception IllegalArgumentException
372      * if group is an empty string.
373      */

374     public void setGroup(String JavaDoc group) {
375         if (group != null && group.trim().length() == 0) {
376             throw new IllegalArgumentException JavaDoc(
377                     "Group name cannot be an empty string.");
378         }
379
380         if(group == null) {
381             group = Scheduler.DEFAULT_GROUP;
382         }
383
384         this.group = group;
385     }
386
387     /**
388      * <p>
389      * Get the name of the associated <code>{@link org.quartz.JobDetail}</code>.
390      * </p>
391      */

392     public String JavaDoc getJobName() {
393         return jobName;
394     }
395
396     /**
397      * <p>
398      * Set the name of the associated <code>{@link org.quartz.JobDetail}</code>.
399      * </p>
400      *
401      * @exception IllegalArgumentException
402      * if jobName is null or empty.
403      */

404     public void setJobName(String JavaDoc jobName) {
405         if (jobName == null || jobName.trim().length() == 0) {
406             throw new IllegalArgumentException JavaDoc(
407                     "Job name cannot be null or empty.");
408         }
409
410         this.jobName = jobName;
411     }
412
413     /**
414      * <p>
415      * Get the name of the associated <code>{@link org.quartz.JobDetail}</code>'s
416      * group.
417      * </p>
418      */

419     public String JavaDoc getJobGroup() {
420         return jobGroup;
421     }
422
423     /**
424      * <p>
425      * Set the name of the associated <code>{@link org.quartz.JobDetail}</code>'s
426      * group.
427      * </p>
428      *
429      * @param jobGroup if <code>null</code>, Scheduler.DEFAULT_GROUP will be used.
430      *
431      * @exception IllegalArgumentException
432      * if group is an empty string.
433      */

434     public void setJobGroup(String JavaDoc jobGroup) {
435         if (jobGroup != null && jobGroup.trim().length() == 0) {
436             throw new IllegalArgumentException JavaDoc(
437                     "Group name cannot be null or empty.");
438         }
439
440         if(jobGroup == null) {
441             jobGroup = Scheduler.DEFAULT_GROUP;
442         }
443
444         this.jobGroup = jobGroup;
445     }
446
447     /**
448      * <p>
449      * Returns the 'full name' of the <code>Trigger</code> in the format
450      * "group.name".
451      * </p>
452      */

453     public String JavaDoc getFullName() {
454         return group + "." + name;
455     }
456
457     public Key getKey() {
458         if(key == null) {
459             key = new Key(getName(), getGroup());
460         }
461
462         return key;
463     }
464
465     /**
466      * <p>
467      * Returns the 'full name' of the <code>Job</code> that the <code>Trigger</code>
468      * points to, in the format "group.name".
469      * </p>
470      */

471     public String JavaDoc getFullJobName() {
472         return jobGroup + "." + jobName;
473     }
474
475     /**
476      * <p>
477      * Return the description given to the <code>Trigger</code> instance by
478      * its creator (if any).
479      * </p>
480      *
481      * @return null if no description was set.
482      */

483     public String JavaDoc getDescription() {
484         return description;
485     }
486
487     /**
488      * <p>
489      * Set a description for the <code>Trigger</code> instance - may be
490      * useful for remembering/displaying the purpose of the trigger, though the
491      * description has no meaning to Quartz.
492      * </p>
493      */

494     public void setDescription(String JavaDoc description) {
495         this.description = description;
496     }
497
498     /**
499      * <p>
500      * Set whether or not the <code>Trigger</code> should be persisted in the
501      * <code>{@link org.quartz.spi.JobStore}</code> for re-use after program
502      * restarts.
503      * </p>
504      */

505     public void setVolatility(boolean volatility) {
506         this.volatility = volatility;
507     }
508
509     /**
510      * <p>
511      * Associate the <code>{@link Calendar}</code> with the given name with
512      * this Trigger.
513      * </p>
514      *
515      * @param calendarName
516      * use <code>null</code> to dis-associate a Calendar.
517      */

518     public void setCalendarName(String JavaDoc calendarName) {
519         this.calendarName = calendarName;
520     }
521
522     /**
523      * <p>
524      * Get the name of the <code>{@link Calendar}</code> associated with this
525      * Trigger.
526      * </p>
527      *
528      * @return <code>null</code> if there is no associated Calendar.
529      */

530     public String JavaDoc getCalendarName() {
531         return calendarName;
532     }
533
534     /**
535      * <p>
536      * Get the <code>JobDataMap</code> that is associated with the
537      * <code>Trigger</code>.
538      * </p>
539      *
540      * <p>
541      * Changes made to this map during job execution are not re-persisted, and
542      * in fact typically result in an <code>IllegalStateException</code>.
543      * </p>
544      */

545     public JobDataMap getJobDataMap() {
546         if (jobDataMap == null) {
547             jobDataMap = new JobDataMap();
548         }
549         return jobDataMap;
550     }
551
552
553     /**
554      * <p>
555      * Set the <code>JobDataMap</code> to be associated with the
556      * <code>Trigger</code>.
557      * </p>
558      */

559     public void setJobDataMap(JobDataMap jobDataMap) {
560         this.jobDataMap = jobDataMap;
561     }
562
563     /**
564      * <p>
565      * Whether or not the <code>Trigger</code> should be persisted in the
566      * <code>{@link org.quartz.spi.JobStore}</code> for re-use after program
567      * restarts.
568      * </p>
569      *
570      * <p>
571      * If not explicitly set, the default value is <code>false</code>.
572      * </p>
573      *
574      * @return <code>true</code> if the <code>Trigger</code> should be
575      * garbage collected along with the <code>{@link Scheduler}</code>.
576      */

577     public boolean isVolatile() {
578         return volatility;
579     }
580
581     /**
582      * The priority of a <code>Trigger</code> acts as a tiebreaker such that if
583      * two <code>Trigger</code>s have the same scheduled fire time, then the
584      * one with the higher priority will get first access to a worker
585      * thread.
586      *
587      * <p>
588      * If not explicitly set, the default value is <code>5</code>.
589      * </p>
590      *
591      * @see #DEFAULT_PRIORITY
592      */

593     public int getPriority() {
594         return priority;
595     }
596
597
598     /**
599      * The priority of a <code>Trigger</code> acts as a tiebreaker such that if
600      * two <code>Trigger</code>s have the same scheduled fire time, then the
601      * one with the higher priority will get first access to a worker
602      * thread.
603      *
604      * <p>
605      * If not explicitly set, the default value is <code>5</code>.
606      * </p>
607      *
608      * @see #DEFAULT_PRIORITY
609      */

610     public void setPriority(int priority) {
611         this.priority = priority;
612     }
613
614     /**
615      * <p>
616      * Add the specified name of a <code>{@link TriggerListener}</code> to
617      * the end of the <code>Trigger</code>'s list of listeners.
618      * </p>
619      */

620     public void addTriggerListener(String JavaDoc name) {
621         if (triggerListeners.contains(name)) {
622             throw new IllegalArgumentException JavaDoc(
623                 "Trigger listener '" + name + "' is already registered for trigger: " + getFullName());
624         }
625
626         triggerListeners.add(name);
627     }
628
629     /**
630      * <p>
631      * Remove the specified name of a <code>{@link TriggerListener}</code>
632      * from the <code>Trigger</code>'s list of listeners.
633      * </p>
634      *
635      * @return true if the given name was found in the list, and removed
636      */

637     public boolean removeTriggerListener(String JavaDoc name) {
638         return triggerListeners.remove(name);
639     }
640
641     /**
642      * <p>
643      * Returns an array of <code>String</code> containing the names of all
644      * <code>{@link TriggerListener}</code>s assigned to the <code>Trigger</code>,
645      * in the order in which they should be notified.
646      * </p>
647      */

648     public String JavaDoc[] getTriggerListenerNames() {
649         return (String JavaDoc[])triggerListeners.toArray(new String JavaDoc[triggerListeners.size()]);
650     }
651
652     /**
653      * Remove all <code>{@link TriggerListener}</code>s from the <code>Trigger</code>.
654      */

655     public void clearAllTriggerListeners() {
656         triggerListeners.clear();
657     }
658
659     /**
660      * <p>
661      * This method should not be used by the Quartz client.
662      * </p>
663      *
664      * <p>
665      * Called when the <code>{@link Scheduler}</code> has decided to 'fire'
666      * the trigger (execute the associated <code>Job</code>), in order to
667      * give the <code>Trigger</code> a chance to update itself for its next
668      * triggering (if any).
669      * </p>
670      *
671      * @see #executionComplete(JobExecutionContext, JobExecutionException)
672      */

673     public abstract void triggered(Calendar calendar);
674
675     /**
676      * <p>
677      * This method should not be used by the Quartz client.
678      * </p>
679      *
680      * <p>
681      * Called by the scheduler at the time a <code>Trigger</code> is first
682      * added to the scheduler, in order to have the <code>Trigger</code>
683      * compute its first fire time, based on any associated calendar.
684      * </p>
685      *
686      * <p>
687      * After this method has been called, <code>getNextFireTime()</code>
688      * should return a valid answer.
689      * </p>
690      *
691      * @return the first time at which the <code>Trigger</code> will be fired
692      * by the scheduler, which is also the same value <code>getNextFireTime()</code>
693      * will return (until after the first firing of the <code>Trigger</code>).
694      * </p>
695      */

696     public abstract Date JavaDoc computeFirstFireTime(Calendar calendar);
697
698     /**
699      * <p>
700      * This method should not be used by the Quartz client.
701      * </p>
702      *
703      * <p>
704      * Called after the <code>{@link Scheduler}</code> has executed the
705      * <code>{@link org.quartz.JobDetail}</code> associated with the <code>Trigger</code>
706      * in order to get the final instruction code from the trigger.
707      * </p>
708      *
709      * @param context
710      * is the <code>JobExecutionContext</code> that was used by the
711      * <code>Job</code>'s<code>execute(xx)</code> method.
712      * @param result
713      * is the <code>JobExecutionException</code> thrown by the
714      * <code>Job</code>, if any (may be null).
715      * @return one of the Trigger.INSTRUCTION_XXX constants.
716      *
717      * @see #INSTRUCTION_NOOP
718      * @see #INSTRUCTION_RE_EXECUTE_JOB
719      * @see #INSTRUCTION_DELETE_TRIGGER
720      * @see #INSTRUCTION_SET_TRIGGER_COMPLETE
721      * @see #triggered(Calendar)
722      */

723     public abstract int executionComplete(JobExecutionContext context,
724                                           JobExecutionException result);
725
726     /**
727      * <p>
728      * Used by the <code>{@link Scheduler}</code> to determine whether or not
729      * it is possible for this <code>Trigger</code> to fire again.
730      * </p>
731      *
732      * <p>
733      * If the returned value is <code>false</code> then the <code>Scheduler</code>
734      * may remove the <code>Trigger</code> from the <code>{@link org.quartz.spi.JobStore}</code>.
735      * </p>
736      */

737     public abstract boolean mayFireAgain();
738
739     /**
740      * <p>
741      * Get the time at which the <code>Trigger</code> should occur.
742      * </p>
743      */

744     public abstract Date JavaDoc getStartTime();
745
746     public abstract void setStartTime(Date JavaDoc startTime);
747
748     public abstract void setEndTime(Date JavaDoc endTime);
749
750     /**
751      * <p>
752      * Get the time at which the <code>Trigger</code> should quit repeating -
753      * even if an assigned 'repeatCount' isn't yet satisfied.
754      * </p>
755      *
756      * @see #getFinalFireTime()
757      */

758     public abstract Date JavaDoc getEndTime();
759
760     /**
761      * <p>
762      * Returns the next time at which the <code>Trigger</code> will fire. If
763      * the trigger will not fire again, <code>null</code> will be returned.
764      * The value returned is not guaranteed to be valid until after the <code>Trigger</code>
765      * has been added to the scheduler.
766      * </p>
767      */

768     public abstract Date JavaDoc getNextFireTime();
769
770     /**
771      * <p>
772      * Returns the previous time at which the <code>Trigger</code> will fire.
773      * If the trigger has not yet fired, <code>null</code> will be returned.
774      */

775     public abstract Date JavaDoc getPreviousFireTime();
776
777     /**
778      * <p>
779      * Returns the next time at which the <code>Trigger</code> will fire,
780      * after the given time. If the trigger will not fire after the given time,
781      * <code>null</code> will be returned.
782      * </p>
783      */

784     public abstract Date JavaDoc getFireTimeAfter(Date JavaDoc afterTime);
785
786     /**
787      * <p>
788      * Returns the last time at which the <code>Trigger</code> will fire, if
789      * the Trigger will repeat indefinitely, null will be returned.
790      * </p>
791      *
792      * <p>
793      * Note that the return time *may* be in the past.
794      * </p>
795      */

796     public abstract Date JavaDoc getFinalFireTime();
797
798     /**
799      * <p>
800      * Set the instruction the <code>Scheduler</code> should be given for
801      * handling misfire situations for this <code>Trigger</code>- the
802      * concrete <code>Trigger</code> type that you are using will have
803      * defined a set of additional <code>MISFIRE_INSTRUCTION_XXX</code>
804      * constants that may be passed to this method.
805      * </p>
806      *
807      * <p>
808      * If not explicitly set, the default value is <code>MISFIRE_INSTRUCTION_SMART_POLICY</code>.
809      * </p>
810      *
811      * @see #MISFIRE_INSTRUCTION_SMART_POLICY
812      * @see #updateAfterMisfire(Calendar)
813      * @see SimpleTrigger
814      * @see CronTrigger
815      */

816     public void setMisfireInstruction(int misfireInstruction) {
817         if (!validateMisfireInstruction(misfireInstruction)) {
818             throw new IllegalArgumentException JavaDoc(
819                         "The misfire instruction code is invalid for this type of trigger.");
820         }
821         this.misfireInstruction = misfireInstruction;
822     }
823
824     protected abstract boolean validateMisfireInstruction(int misfireInstruction);
825
826     /**
827      * <p>
828      * Get the instruction the <code>Scheduler</code> should be given for
829      * handling misfire situations for this <code>Trigger</code>- the
830      * concrete <code>Trigger</code> type that you are using will have
831      * defined a set of additional <code>MISFIRE_INSTRUCTION_XXX</code>
832      * constants that may be passed to this method.
833      * </p>
834      *
835      * <p>
836      * If not explicitly set, the default value is <code>MISFIRE_INSTRUCTION_SMART_POLICY</code>.
837      * </p>
838      *
839      * @see #MISFIRE_INSTRUCTION_SMART_POLICY
840      * @see #updateAfterMisfire(Calendar)
841      * @see SimpleTrigger
842      * @see CronTrigger
843      */

844     public int getMisfireInstruction() {
845         return misfireInstruction;
846     }
847
848     /**
849      * <p>
850      * This method should not be used by the Quartz client.
851      * </p>
852      *
853      * <p>
854      * To be implemented by the concrete classes that extend this class.
855      * </p>
856      *
857      * <p>
858      * The implementation should update the <code>Trigger</code>'s state
859      * based on the MISFIRE_INSTRUCTION_XXX that was selected when the <code>Trigger</code>
860      * was created.
861      * </p>
862      */

863     public abstract void updateAfterMisfire(Calendar cal);
864
865     /**
866      * <p>
867      * This method should not be used by the Quartz client.
868      * </p>
869      *
870      * <p>
871      * To be implemented by the concrete class.
872      * </p>
873      *
874      * <p>
875      * The implementation should update the <code>Trigger</code>'s state
876      * based on the given new version of the associated <code>Calendar</code>
877      * (the state should be updated so that it's next fire time is appropriate
878      * given the Calendar's new settings).
879      * </p>
880      *
881      * @param cal
882      */

883     public abstract void updateWithNewCalendar(Calendar cal, long misfireThreshold);
884
885     /**
886      * <p>
887      * Validates whether the properties of the <code>JobDetail</code> are
888      * valid for submission into a <code>Scheduler</code>.
889      *
890      * @throws IllegalStateException
891      * if a required property (such as Name, Group, Class) is not
892      * set.
893      */

894     public void validate() throws SchedulerException {
895         if (name == null) {
896             throw new SchedulerException("Trigger's name cannot be null",
897                         SchedulerException.ERR_CLIENT_ERROR);
898         }
899
900         if (group == null) {
901             throw new SchedulerException("Trigger's group cannot be null",
902                         SchedulerException.ERR_CLIENT_ERROR);
903         }
904
905         if (jobName == null) {
906             throw new SchedulerException(
907                         "Trigger's related Job's name cannot be null",
908                         SchedulerException.ERR_CLIENT_ERROR);
909         }
910
911         if (jobGroup == null) {
912             throw new SchedulerException(
913                         "Trigger's related Job's group cannot be null",
914                         SchedulerException.ERR_CLIENT_ERROR);
915         }
916     }
917
918     /**
919      * <p>
920      * This method should not be used by the Quartz client.
921      * </p>
922      *
923      * <p>
924      * Usable by <code>{@link org.quartz.spi.JobStore}</code>
925      * implementations, in order to facilitate 'recognizing' instances of fired
926      * <code>Trigger</code> s as their jobs complete execution.
927      * </p>
928      *
929      *
930      */

931     public void setFireInstanceId(String JavaDoc id) {
932         this.fireInstanceId = id;
933     }
934
935     /**
936      * <p>
937      * This method should not be used by the Quartz client.
938      * </p>
939      */

940     public String JavaDoc getFireInstanceId() {
941         return fireInstanceId;
942     }
943
944     /**
945      * <p>
946      * Return a simple string representation of this object.
947      * </p>
948      */

949     public String JavaDoc toString() {
950         return "Trigger '" + getFullName() + "': triggerClass: '"
951                 + getClass().getName() + " isVolatile: " + isVolatile()
952                 + " calendar: '" + getCalendarName() + "' misfireInstruction: "
953                 + getMisfireInstruction() + " nextFireTime: " + getNextFireTime();
954     }
955
956     /**
957      * <p>
958      * Compare the next fire time of this <code>Trigger</code> to that of
959      * another.
960      * </p>
961      */

962     public int compareTo(Object JavaDoc obj) {
963         Trigger other = (Trigger) obj;
964
965         Date JavaDoc myTime = getNextFireTime();
966         Date JavaDoc otherTime = other.getNextFireTime();
967
968         if (myTime == null && otherTime == null) {
969             return 0;
970         }
971
972         if (myTime == null) {
973             return 1;
974         }
975
976         if (otherTime == null) {
977             return -1;
978         }
979
980         if(myTime.before(otherTime)) {
981             return -1;
982         }
983
984         if(myTime.after(otherTime)) {
985             return 1;
986         }
987
988         return 0;
989     }
990
991     public boolean equals(Object JavaDoc obj) {
992         if (!(obj instanceof Trigger)) {
993             return false;
994         }
995
996         Trigger other = (Trigger) obj;
997
998         if (!other.getName().equals(getName())) {
999             return false;
1000        }
1001        if (!other.getGroup().equals(getGroup())) {
1002            return false;
1003        }
1004
1005        return true;
1006    }
1007
1008
1009    public int hashCode() {
1010        return getFullName().hashCode();
1011    }
1012
1013    public Object JavaDoc clone() {
1014        Trigger copy;
1015        try {
1016            copy = (Trigger) super.clone();
1017
1018            copy.triggerListeners = (LinkedList JavaDoc)triggerListeners.clone();
1019
1020            // Shallow copy the jobDataMap. Note that this means that if a user
1021
// modifies a value object in this map from the cloned Trigger
1022
// they will also be modifying this Trigger.
1023
if (jobDataMap != null) {
1024                copy.jobDataMap = (JobDataMap)jobDataMap.clone();
1025            }
1026
1027        } catch (CloneNotSupportedException JavaDoc ex) {
1028            throw new IncompatibleClassChangeError JavaDoc("Not Cloneable.");
1029        }
1030        return copy;
1031    }
1032}
1033
Popular Tags