1 package com.atlassian.core.cron.generator;
2
3 import com.atlassian.core.cron.CronEditorBean;
4 import com.atlassian.core.i18n.I18nTextProvider;
5 import com.atlassian.core.util.map.EasyMap;
6 import org.apache.commons.lang.StringUtils;
7 import org.apache.commons.lang.Validate;
8
9 import java.text.NumberFormat;
10 import java.util.Arrays;
11 import java.util.Map;
12
13
14
15
16 public class CronExpressionDescriptor
17 {
18 private static final Map<String, String> MINUTE_INCREMENT_TO_MESG_KEY = EasyMap.build(
19 "15", "cron.editor.every.15.minutes",
20 "30", "cron.editor.every.30.minutes",
21 "60", "cron.editor.every.hour",
22 "120", "cron.editor.every.2.hours",
23 "180", "cron.editor.every.3.hours"
24 );
25
26 private static final Map<String, String> DAY_NUMBERS = EasyMap.build(
27 "1", "sunday",
28 "2", "monday",
29 "3", "tuesday",
30 "4", "wednesday",
31 "5", "thursday",
32 "6", "friday",
33 "7", "saturday"
34 );
35
36 private static final String CRON_EDITOR_KEY_PREFIX = "cron.editor.";
37 private static final int MINUTES_DIGITS = 2;
38 private static final int DAYS_IN_WEEK = 7;
39 private static final String LAST_COMMA_REGEX = ",([^,]*)$";
40
41 private final I18nTextProvider i18n;
42
43
44
45
46
47
48 public CronExpressionDescriptor(I18nTextProvider i18n)
49 {
50 Validate.notNull(i18n, "I18nTextProvider must nnot be null");
51 this.i18n = i18n;
52 }
53
54
55
56
57
58
59
60 private String getDay(String number)
61 {
62 String keypart = DAY_NUMBERS.get(number);
63 Validate.notNull(keypart, "Unable to get day for number '" + number + "'. CronEditorBean likely to be inconsistent");
64 return i18n.getText(CRON_EDITOR_KEY_PREFIX + keypart);
65 }
66
67
68
69
70
71
72
73
74
75 public String getPrettySchedule(CronEditorBean bean)
76 {
77 if (bean.isAdvancedMode()) {
78 return bean.getCronString();
79 }
80 StringBuilder desc = new StringBuilder();
81 if (bean.isDailyMode())
82 {
83 desc.append(i18n.getText("cron.editor.daily")).append(" ");
84 desc.append(getTimePart(bean));
85 }
86 else if (bean.isDayPerWeekMode())
87 {
88 desc.append(getDayPerWeekDescriptor(bean));
89 }
90 else if (bean.isDaysPerMonthMode())
91 {
92 desc.append(getDayPerMonthDescriptor(bean));
93 }
94
95 return desc.toString();
96 }
97
98 private String getDayPerWeekDescriptor(CronEditorBean bean)
99 {
100 StringBuilder desc = new StringBuilder();
101 desc.append(i18n.getText("cron.editor.each"));
102 desc.append(" ");
103
104 String[] daysArray = bean.getSpecifiedDaysPerWeek().split(",");
105 Arrays.sort(daysArray);
106 String daysString = StringUtils.join(daysArray, ",");
107 daysString = daysString.replaceAll(LAST_COMMA_REGEX, " and $1");
108 for (int i = 1; i <= DAYS_IN_WEEK; i++)
109 {
110 String dayNum = Integer.toString(i);
111 daysString = daysString.replaceAll(dayNum, getDay(dayNum));
112 }
113 daysString = daysString.replaceAll(",", ", ");
114 desc.append(daysString).append(" ");
115
116 desc.append(getTimePart(bean));
117 return desc.toString();
118 }
119
120
121
122
123
124
125
126 private String getDayPerMonthDescriptor(CronEditorBean bean)
127 {
128 StringBuilder desc = new StringBuilder();
129 if (bean.isDayOfWeekOfMonth())
130 {
131 String ordinal = i18n.getText("cron.editor.ordinal." + bean.getDayInMonthOrdinal());
132 String ordinalWeekday = ordinal + " " + getDay(bean.getSpecifiedDaysPerWeek());
133 desc.append(i18n.getText("cron.editor.the.of.every.month", new String[]{ordinalWeekday}));
134 desc.append(" ");
135 desc.append(getTimePart(bean));
136 }
137 else
138 {
139
140 desc.append(i18n.getText("cron.editor.the.day.of.every.month", new String[]{i18n.getText("cron.editor.nth." + bean.getDayOfMonth())}));
141 desc.append(" ");
142 desc.append(getTimePart(bean));
143 }
144 return desc.toString();
145 }
146
147
148
149
150
151
152
153
154 private String getTimePart(CronEditorBean bean)
155 {
156 StringBuilder desc = new StringBuilder();
157 if (!bean.isRange())
158 {
159 desc.append(getRunOnce(bean));
160 }
161 else
162 {
163 desc.append(getRepeatInRange(bean));
164 }
165 return desc.toString();
166 }
167
168
169
170
171
172
173
174 private String getRunOnce(CronEditorBean bean)
175 {
176 StringBuilder desc = new StringBuilder();
177 desc.append(i18n.getText("cron.editor.at"));
178 desc.append(" ");
179 desc.append(bean.getHoursRunOnce()).append(":").append(getPaddedMinutes(bean.getMinutes())).append(" ").append(bean.getHoursRunOnceMeridian());
180 return desc.toString();
181 }
182
183
184
185
186
187
188
189 private String getRepeatInRange(CronEditorBean bean)
190 {
191 StringBuilder desc = new StringBuilder();
192 String increment = bean.getIncrementInMinutes();
193 if (increment.equals("0"))
194 {
195
196 }
197 else
198 {
199 String key = MINUTE_INCREMENT_TO_MESG_KEY.get(increment);
200 desc.append(i18n.getText(key));
201 }
202
203 if (!bean.is24HourRange())
204 {
205 desc.append(" ");
206 desc.append(i18n.getText("cron.editor.from"));
207 desc.append(" ");
208 desc.append(bean.getHoursFrom()).append(":00 ").append(bean.getHoursFromMeridian());
209 desc.append(" ");
210 desc.append(i18n.getText("cron.editor.to"));
211 desc.append(" ");
212 desc.append(bean.getHoursTo()).append(":00 ").append(bean.getHoursToMeridian());
213 }
214 return desc.toString();
215 }
216
217 private String getPaddedMinutes(String minutes)
218 {
219 NumberFormat format = NumberFormat.getInstance();
220 format.setMinimumIntegerDigits(MINUTES_DIGITS);
221 return format.format(Integer.parseInt(minutes));
222 }
223 }