View Javadoc

1   package com.atlassian.scheduler.cron;
2   
3   import javax.annotation.Nonnull;
4   import javax.annotation.Nullable;
5   
6   /**
7    * Clarifies the reason for failure when a cron expression cannot be parsed.
8    *
9    * @since v1.4
10   */
11  public enum ErrorCode {
12      /**
13       * The cron expression used multiple expressions for the day-of-month, at least one of which used the {@code L}
14       * flag.
15       * This is not supported; the {@code L} flag can only be used when a single expression is given.
16       */
17      COMMA_WITH_LAST_DOM("You cannot use 'L' or 'W' with multiple day-of-month values."),
18  
19      /**
20       * The cron expression used multiple expressions for the day-of-week, at least one of which used the {@code L}
21       * flag.
22       * This is not supported; the {@code L} flag can only be used when a single expression is given.
23       */
24      COMMA_WITH_LAST_DOW("You cannot use 'L' with multiple day-of-week values."),
25  
26      /**
27       * The cron expression used multiple expressions for the day-of-week, at least one of which used the {@code #}
28       * flag.
29       * This is not supported; the {@code #} flag can only be used when a single expression is given.
30       */
31      COMMA_WITH_NTH_DOW("You cannot use '#' with multiple day-of-week values."),
32  
33      /**
34       * The cron expression used multiple expressions for the day-of-month, at least one of which used the {@code W}
35       * flag.
36       * This is not supported; the {@code W} flag can only be used when a single expression is given.
37       */
38      COMMA_WITH_WEEKDAY_DOM("You cannot use 'W' with multiple day-of-month values."),
39  
40      /**
41       * The reason of the failure could not be determined.
42       * This indicates that the underlying cause is an unexpected runtime exception and indicates a programming
43       * error in the cron expression parsing.
44       * The {@code value} should be the message from {@code cause}.
45       */
46      INTERNAL_PARSER_FAILURE("Internal parser failure: ", ""),
47  
48      /**
49       * The cron expression contained a character that is not legal in the cron expression syntax.
50       * The {@code value} should be the illegal character that was encountered.
51       */
52      ILLEGAL_CHARACTER("Unexpected character: '", "'"),
53  
54      /**
55       * The cron expression contained a question-mark (<code>?</code>) followed by another non-whitespace character.
56       * This special value can only be used by itself in the day-of-month or day-of-week field; it cannot be combined
57       * with any other value.
58       * The {@code value} should be the illegal character that was encountered.
59       */
60      ILLEGAL_CHARACTER_AFTER_QM("Illegal character after '?': '", "'"),
61  
62      /**
63       * The cron expression contained a hash (<code>#</code>) in the day-of-week column that was not followed by an
64       * integer value from {@code 1} to {@code 5}.
65       */
66      ILLEGAL_CHARACTER_AFTER_HASH("A numeric value between 1 and 5 must follow the '#' option."),
67  
68      /**
69       * The cron expression contained a step interval (a value after {@code /}) that was followed by additional
70       * characters in the same field expression.
71       * The step interval must be the last part of a value.  The slash (<code>/</code>) must be followed by an
72       * integer.  After that, the only legal characters are whitespace or a comma (<code>,</code>) to separate
73       * it from the next value for that field.
74       */
75      ILLEGAL_CHARACTER_AFTER_INTERVAL("Illegal character after '/': '", "'"),
76  
77      /**
78       * The cron expression contained a slash (<code>/</code>) that was not followed by an integer value.
79       * A step interval value must be specified, such as {@code /5} in the minutes column to indicate that
80       * the accept values are spaces five minutes apart.
81       */
82      INVALID_STEP("The step interval character '/' must be followed by a positive integer."),
83  
84      /**
85       * The cron expression contained an interval step for the day-of-month that was greater than or equal to {@code 31}.
86       * Since this value is large enough to make it impossible to result in a second value with any starting
87       * value in any month, it is not permitted.
88       */
89      INVALID_STEP_DAY_OF_MONTH("The step interval for day-of-month must be less than 31: ", ""),
90  
91      /**
92       * The cron expression contained an interval step for the day-of-week that was greater than or equal to {@code 7}.
93       * Since this value is large enough to make it impossible to result in a second value, it is not permitted.
94       */
95      INVALID_STEP_DAY_OF_WEEK("The step interval for day-of-week must be less than 7: ", ""),
96  
97      /**
98       * The cron expression contained an interval step for the hour that was greater than or equal to {@code 24}.
99       * Since this value is large enough to make it impossible to result in a second value, it is not permitted.
100      */
101     INVALID_STEP_HOUR("The step interval for hour must be less than 24: ", ""),
102 
103     /**
104      * The cron expression contained an interval step for the month that was greater than or equal to {@code 12}.
105      * Since this value is large enough to make it impossible to result in a second value, it is not permitted.
106      */
107     INVALID_STEP_MONTH("The step interval for month must be less than 12: ", ""),
108 
109     /**
110      * The cron expression contained an interval step for the second or minute that was greater than or equal to
111      * {@code 60}.
112      * Since this value is large enough to make it impossible to result in a second value, it is not permitted.
113      */
114     INVALID_STEP_SECOND_OR_MINUTE("The step interval for second or minute must be less than 60: ", ""),
115 
116     /**
117      * The cron expression contained a sequence of letters that appears to be meant as the name of a month or
118      * day-of-week, but it was malformed.
119      * For example, {@code MO} would be invalid because it is too short.
120      */
121     INVALID_NAME("Invalid name: '", "'"),
122 
123     /**
124      * The cron expression contained a sequence of letters that appears to be meant as the name of a month or
125      * day-of-week, but it was specified in one of the other fields.
126      */
127     INVALID_NAME_FIELD("This field does not support names: '", "'"),
128 
129     /**
130      * The cron expression contained a sequence that appears to be meant as a name-based range of a month or
131      * day-of-week values, but the end value of the sequence was malformed.
132      * Examples include {@code 3-FRI} or {@code MON-4} or {@code FEB-L}.
133      */
134     INVALID_NAME_RANGE("Cannot specify a range using month or day-of-week names unless a valid name is used"
135             + " for both bounds."),
136 
137     /**
138      * The cron expression contained a sequence of letters that appears to be meant as the name of a month,
139      * but the name was not recognized.
140      * Only the three-letter English abbreviations for month names are supported, such as {@code FEB} for
141      * February or {@code SEP} for September.
142      */
143     INVALID_NAME_MONTH("Invalid month name: '", "'"),
144 
145     /**
146      * The cron expression contained a sequence of letters that appears to be meant as the name of a day-of-week,
147      * but the name was not recognized.
148      * Only the three-letter English abbreviations for day-of-week names are supported, such as {@code MON} for
149      * Monday or {@code THU} for Thursday.  Note that {@code THR} is not accepted.
150      */
151     INVALID_NAME_DAY_OF_WEEK("Invalid day-of-week name: '", "'"),
152 
153     /**
154      * The cron expression contained a number in the minute or second field that was outside the supported range
155      * of {@code [0, 59]}.
156      */
157     INVALID_NUMBER_SEC_OR_MIN("The values for seconds and minutes must be from 0 to 59."),
158 
159     /**
160      * The cron expression contained a number in the hour field that was outside the supported range
161      * of {@code [0, 23]}.
162      */
163     INVALID_NUMBER_HOUR("The values for hours must be from 0 to 23."),
164 
165     /**
166      * The cron expression contained a number in the day-of-month field that was outside the supported range
167      * of {@code [0, 31]}.
168      */
169     INVALID_NUMBER_DAY_OF_MONTH("The values for day-of-month must be from 1 to 31."),
170 
171     /**
172      * The cron expression contained an {@code L-x} or {@code L-xW} expression where the value of {@code x}
173      * was more than {@code 30}.
174      * Since {@code 31} or more days before the last day of the month is always in a different month, such
175      * an expression could not possibly ever match.
176      */
177     INVALID_NUMBER_DAY_OF_MONTH_OFFSET("The offset from the last day day of the month must be no more than 30."),
178 
179     /**
180      * The cron expression contained a number in the month field that was outside the supported range
181      * of {@code [1, 12]}.
182      */
183     INVALID_NUMBER_MONTH("The values for month must be from 1 to 12."),
184 
185     /**
186      * The cron expression contained a number in the day-of-week field that was outside the supported range
187      * of {@code [1, 7]}.
188      */
189     INVALID_NUMBER_DAY_OF_WEEK("The values for day-of-week must be from 1 to 7."),
190 
191     /**
192      * The cron expression contained a number in the year field that was outside the supported range
193      * of {@code [1970, 2299]}.
194      */
195     // Note: Currently unused because Quartz does not consider this a problem until it tries to find
196     // the next matching date and gives up because it is more than 100 years in the future.  It is
197     // not caught by the parser.
198     INVALID_NUMBER_YEAR("The values for year must be from 1970 to 2299."),
199 
200     /**
201      * The cron expression contains a range in the year field that gave the years in reverse order,
202      * such as {@code 2036-2016}.
203      * Reversed ranges are permitted for the other fields and "wrap around" such that {@code NOV-FEB}
204      * means November, December, January, or February.  There is no really meaningful way to do that
205      * for the year ranges, so that is not allowed for this field.
206      */
207     INVALID_NUMBER_YEAR_RANGE("Year ranges must specify the earlier year first."),
208 
209     /**
210      * The cron expression contained a question-mark (<code>?</code>) in some field other than the day-of-month
211      * or day-of-week.
212      * This special value cannot be used in any other field.
213      */
214     QM_CANNOT_USE_HERE("You can only use '?' for the day-of-month or the day-of-week."),
215 
216     /**
217      * The cron expression contained a question-mark (<code>?</code>) for both the day-of-month and the
218      * day-of-week.
219      * One of these fields must be specified, and it is likely that changing either one to {@code *} will
220      * give the intended result.
221      */
222     QM_CANNOT_USE_FOR_BOTH_DAYS("You cannot specify '?' for both the day-of-month and the day-of-week."),
223 
224     /**
225      * The cron expression specified values other than {@code ?} for both the day-of-month and the
226      * day-of-week.
227      * Exactly one of these fields must be specified; the other must be disabled by giving {@code ?} as its value.
228      */
229     QM_MUST_USE_FOR_ONE_OF_DAYS("You must use '?' for either the day-of-month or day-of-week."),
230 
231     /**
232      * The cron expression contained what looks like an {@code L} flag, but it is in a column that does not
233      * support it or is not in a place that makes sense.  For example, you cannot specify {@code L}
234      * for the hour field, and while you could say {@code L-3} as the day-of-month to indicate the third-to-last
235      * day of the month, {@code 3-L} does not make sense.
236      */
237     UNEXPECTED_TOKEN_FLAG_L("The 'L' option was used incorrectly."),
238 
239     /**
240      * The cron expression contained what looks like a {@code W} flag, but it is in a column that does not
241      * support it or is not in a place that makes sense.  For example, you cannot specify {@code W}
242      * for the hour field, and while you could say {@code 3W} as the day-of-month to indicate the weekday
243      * closest to the third day of the month, {@code 3-W} does not make sense.
244      */
245     UNEXPECTED_TOKEN_FLAG_W("The 'W' option was used incorrectly."),
246 
247     /**
248      * The cron expression contained what looks like a {@code #} flag, but it is in a column that does not
249      * support it or is not in a place that makes sense.  For example, you cannot specify {@code #}
250      * in the hour field, and while you could say {@code MON#3} as the day-of-week to indicate the third
251      * Monday of the month, {@code #3} by itself does not make sense.
252      */
253     UNEXPECTED_TOKEN_HASH("The '#' option was used incorrectly."),
254 
255     /**
256      * The cron expression contained an invalid hyphen (<code>-</code>).
257      * This can only be used for ranges that provide both a starting and ending value, such as {@code 5-8}
258      * or {@code MAY-AUG}, or in the special syntax {@code L-3} that is available for the day-of-month field.
259      */
260     UNEXPECTED_TOKEN_HYPHEN("Ranges specified with '-' must have both a starting and ending value."),
261 
262     /**
263      * The cron expression ended without specifying all of the required fields or ended in a way that would
264      * require more characters.
265      * Only the year field is optional; all other fields must be included in the cron expression.
266      * This error code can also be used if the cron expression ended in a way that would have required
267      * more characters to follow, such as a comma (<code>,</code>) or hyphen (<code>-</code>).
268      */
269     UNEXPECTED_END_OF_EXPRESSION("Unexpected end of expression");
270 
271     private final String message;
272     private final String suffix;
273 
274     private ErrorCode(final String message) {
275         this(message, null);
276     }
277 
278     private ErrorCode(final String message, @Nullable final String suffix) {
279         this.message = message;
280         this.suffix = suffix;
281     }
282 
283     /**
284      * Renders the standard message for this error code and offending value.
285      */
286     @Nonnull
287     public String toMessage(@Nullable String value) {
288         if (suffix != null) {
289             return message + value + suffix;
290         }
291         return message;
292     }
293 }