1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.exchange.ews;
21
22 import davmail.exchange.ExchangeSession;
23 import org.apache.log4j.Logger;
24
25 import java.io.IOException;
26 import java.io.Writer;
27 import java.text.SimpleDateFormat;
28 import java.util.Date;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.Locale;
32
33
34
35
36
37 public class RecurrenceFieldUpdate extends FieldUpdate {
38 public static final Logger LOGGER = Logger.getLogger(RecurrenceFieldUpdate.class);
39 static final HashMap<String, String> calDayToDayOfWeek = new HashMap<>();
40 static {
41 calDayToDayOfWeek.put("SU", "Sunday");
42 calDayToDayOfWeek.put("MO", "Monday");
43 calDayToDayOfWeek.put("TU", "Tuesday");
44 calDayToDayOfWeek.put("WE", "Wednesday");
45 calDayToDayOfWeek.put("TH", "Thursday");
46 calDayToDayOfWeek.put("FR", "Friday");
47 calDayToDayOfWeek.put("SA", "Saturday");
48 }
49 protected Date startDate;
50 protected Date endDate;
51 protected String count;
52 protected HashSet<String> byDays = null;
53 protected String dayOfMonth;
54 protected String month;
55 protected String dayOfWeekIndex;
56 protected String firstDayOfWeek;
57
58 public void setStartDate(Date startDate) {
59 this.startDate = startDate;
60 }
61
62 public void setEndDate(Date endDate) {
63 this.endDate = endDate;
64 }
65
66 public void setByDay(String[] days) {
67 byDays = new HashSet<>();
68 for (String day: days) {
69
70 String dayCode = day.replaceAll("^-?\\d+", "");
71 String value = calDayToDayOfWeek.get(dayCode);
72 if (value == null) {
73 LOGGER.warn("Invalid day value: "+day);
74 } else {
75 byDays.add(value);
76 }
77 }
78
79 if (recurrencePattern == RecurrencePattern.DailyRecurrence) {
80 recurrencePattern = RecurrencePattern.WeeklyRecurrence;
81 }
82 }
83
84 public void setDayOfMonth(String dayOfMonth) {
85 this.dayOfMonth = dayOfMonth;
86 }
87
88 public void setMonthFromByMonth(String byMonth) {
89 this.month = convertByMonthToName(byMonth);
90 }
91
92 public void setDayOfWeekIndexFromByDay(String byDay) {
93 this.dayOfWeekIndex = extractDayOfWeekIndex(byDay);
94 }
95
96 public void setFirstDayOfWeek(String firstDayOfWeek) {
97 this.firstDayOfWeek = firstDayOfWeek;
98 }
99
100 public void setCount(String count) {
101 this.count = count;
102 }
103
104 public enum RecurrencePattern {DailyRecurrence, WeeklyRecurrence, AbsoluteMonthlyRecurrence, AbsoluteYearlyRecurrence, RelativeMonthlyRecurrence, RelativeYearlyRecurrence}
105
106 RecurrencePattern recurrencePattern;
107 int recurrenceInterval = 1;
108
109
110
111
112 public RecurrenceFieldUpdate() {
113 }
114
115 public void setRecurrencePattern(RecurrencePattern recurrencePattern) {
116 this.recurrencePattern = recurrencePattern;
117 }
118
119 public void setRecurrencePattern(String value) {
120 if ("DAILY".equals(value)) {
121 setRecurrencePattern(RecurrenceFieldUpdate.RecurrencePattern.DailyRecurrence);
122 } else if ("WEEKLY".equals(value)) {
123 setRecurrencePattern(RecurrencePattern.WeeklyRecurrence);
124 } else if ("MONTHLY".equals(value)) {
125 setRecurrencePattern(RecurrencePattern.AbsoluteMonthlyRecurrence);
126 } else if ("YEARLY".equals(value)) {
127 setRecurrencePattern(RecurrencePattern.AbsoluteYearlyRecurrence);
128 } else if ("RELATIVEMONTHLY".equals(value)) {
129 setRecurrencePattern(RecurrencePattern.RelativeMonthlyRecurrence);
130 } else if ("RELATIVEYEARLY".equals(value)) {
131 setRecurrencePattern(RecurrencePattern.RelativeYearlyRecurrence);
132 }
133 }
134
135 public void setRecurrenceInterval(String interval) {
136 this.recurrenceInterval = Integer.parseInt(interval);
137 }
138
139
140
141
142
143
144
145
146 public void write(String itemType, Writer writer) throws IOException {
147 if (itemType != null) {
148 writer.write("<t:Set");
149 writer.write(itemType);
150 writer.write("Field>");
151 }
152
153
154 if (itemType != null) {
155 writer.write("<t:FieldURI FieldURI=\"calendar:Recurrence\"/>");
156 writer.write("<t:CalendarItem>");
157
158 writer.write("<t:Recurrence>");
159 writer.write("<t:");
160 writer.write(recurrencePattern.toString());
161 writer.write(">");
162 if (recurrencePattern == RecurrencePattern.AbsoluteYearlyRecurrence) {
163 writeDayOfMonth(writer);
164 writeMonth(writer);
165 } else if (recurrencePattern == RecurrencePattern.AbsoluteMonthlyRecurrence) {
166 writeInterval(writer);
167 writeDayOfMonth(writer);
168 } else if (recurrencePattern == RecurrencePattern.RelativeYearlyRecurrence) {
169 writeDaysOfWeek(writer);
170 writeDayOfWeekIndex(writer);
171 writeMonth(writer);
172 } else if (recurrencePattern == RecurrencePattern.RelativeMonthlyRecurrence) {
173 writeInterval(writer);
174 writeDaysOfWeek(writer);
175 writeDayOfWeekIndex(writer);
176 } else if (recurrencePattern == RecurrencePattern.WeeklyRecurrence) {
177 writeInterval(writer);
178 writeDaysOfWeek(writer);
179 if (firstDayOfWeek != null) {
180 writeFirstDayOfWeek(writer);
181 }
182 } else if (recurrencePattern == RecurrencePattern.DailyRecurrence) {
183 writeInterval(writer);
184 }
185 writer.write("</t:");
186 writer.write(recurrencePattern.toString());
187 writer.write(">");
188 writeStartEnd(writer);
189 writer.write("</t:Recurrence>");
190
191 writer.write("</t:CalendarItem>");
192 }
193
194 if (itemType != null) {
195 writer.write("</t:Set");
196 writer.write(itemType);
197 writer.write("Field>");
198 }
199 }
200
201 private void writeInterval(Writer writer) throws IOException {
202 writer.write("<t:Interval>");
203 writer.write(String.valueOf(recurrenceInterval));
204 writer.write("</t:Interval>");
205 }
206
207 private void writeStartEnd(Writer writer) throws IOException {
208 if (count != null) {
209 writer.write("<t:NumberedRecurrence>");
210 writer.write("<t:StartDate>");
211 writer.write(getFormattedDate(startDate));
212 writer.write("</t:StartDate>");
213 writer.write("<t:NumberOfOccurrences>");
214 writer.write(count);
215 writer.write("</t:NumberOfOccurrences>");
216 writer.write("</t:NumberedRecurrence>");
217 } else if (endDate == null) {
218 writer.write("<t:NoEndRecurrence><t:StartDate>");
219 writer.write(getFormattedDate(startDate));
220 writer.write("</t:StartDate></t:NoEndRecurrence>");
221 } else {
222 writer.write("<t:EndDateRecurrence>");
223 writer.write("<t:StartDate>");
224 writer.write(getFormattedDate(startDate));
225 writer.write("</t:StartDate>");
226 writer.write("<t:EndDate>");
227 writer.write(getFormattedDate(endDate));
228 writer.write("</t:EndDate>");
229 writer.write("</t:EndDateRecurrence>");
230
231 }
232 }
233
234 private void writeDaysOfWeek(Writer writer) throws IOException {
235 writer.write("<t:DaysOfWeek>");
236 if (byDays != null) {
237 boolean first = true;
238 for (String dayOfeek:byDays) {
239 if (first) {
240 first = false;
241 } else {
242 writer.write(' ');
243 }
244 writer.write(dayOfeek);
245 }
246 } else {
247 writer.write(getDayOfWeek());
248 }
249 writer.write("</t:DaysOfWeek>");
250 }
251
252 private void writeDayOfMonth(Writer writer) throws IOException {
253 writer.write("<t:DayOfMonth>");
254 writer.write(dayOfMonth != null ? dayOfMonth : getDayOfMonth());
255 writer.write("</t:DayOfMonth>");
256 }
257
258 private void writeMonth(Writer writer) throws IOException {
259 writer.write("<t:Month>");
260 writer.write(month != null ? month : getMonth());
261 writer.write("</t:Month>");
262 }
263
264 private void writeDayOfWeekIndex(Writer writer) throws IOException {
265 writer.write("<t:DayOfWeekIndex>");
266 writer.write(dayOfWeekIndex != null ? dayOfWeekIndex : "First");
267 writer.write("</t:DayOfWeekIndex>");
268 }
269
270 private void writeFirstDayOfWeek(Writer writer) throws IOException {
271 writer.write("<t:FirstDayOfWeek>");
272 writer.write(firstDayOfWeek);
273 writer.write("</t:FirstDayOfWeek>");
274 }
275
276 private String getDayOfWeek() {
277 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE", Locale.ENGLISH);
278 simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
279 return simpleDateFormat.format(startDate);
280 }
281
282 private String getMonth() {
283 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMMM", Locale.ENGLISH);
284 simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
285 return simpleDateFormat.format(startDate);
286 }
287
288 private String getDayOfMonth() {
289 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("d", Locale.ENGLISH);
290 simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
291 return simpleDateFormat.format(startDate);
292 }
293
294 private String getFormattedDate(Date date) {
295 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
296 simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
297 return simpleDateFormat.format(date);
298 }
299
300 private String extractDayOfWeekIndex(String byDay) {
301
302 java.util.regex.Matcher m = java.util.regex.Pattern.compile("^(-?\\d+)").matcher(byDay);
303 if (m.find()) {
304 switch (m.group(1)) {
305 case "2": return "Second";
306 case "3": return "Third";
307 case "4": return "Fourth";
308 case "-1": return "Last";
309 default: return "First";
310 }
311 }
312 return "First";
313 }
314
315 private static final String[] MONTH_NAMES = {
316 "January","February","March","April","May","June",
317 "July","August","September","October","November","December"
318 };
319
320 private String convertByMonthToName(String byMonth) {
321 try {
322 int m = Integer.parseInt(byMonth);
323 if (m >= 1 && m <= 12) return MONTH_NAMES[m - 1];
324 } catch (NumberFormatException e) {
325
326 }
327 return byMonth;
328 }
329
330
331 }