View Javadoc
1   /*
2    * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
3    * Copyright (C) 2010  Mickael Guessant
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (at your option) any later version.
9    *
10   * This program 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 General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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   * Handle calendar item recurrence update
35   */
36  public class RecurrenceFieldUpdate extends FieldUpdate {
37      public static final Logger LOGGER = Logger.getLogger(RecurrenceFieldUpdate.class);
38      static final HashMap<String, String> calDayToDayOfWeek = new HashMap<>();
39      static {
40          calDayToDayOfWeek.put("SU", "Sunday");
41          calDayToDayOfWeek.put("MO", "Monday");
42          calDayToDayOfWeek.put("TU", "Tuesday");
43          calDayToDayOfWeek.put("WE", "Wednesday");
44          calDayToDayOfWeek.put("TH", "Thursday");
45          calDayToDayOfWeek.put("FR", "Friday");
46          calDayToDayOfWeek.put("SA", "Saturday");
47      }
48      protected Date startDate;
49      protected Date endDate;
50      protected String count;
51      protected HashSet<String> byDays = null;
52  
53      public void setStartDate(Date startDate) {
54          this.startDate = startDate;
55      }
56  
57      public void setEndDate(Date endDate) {
58          this.endDate = endDate;
59      }
60  
61      public void setByDay(String[] days) {
62          byDays = new HashSet<>();
63          for (String day: days) {
64              String value = calDayToDayOfWeek.get(day);
65              if (value == null) {
66                  LOGGER.warn("Invalid day value: "+day);
67              } else {
68                  byDays.add(value);
69              }
70          }
71          // fix recurrence for Thunderbird weekday pattern
72          if (recurrencePattern == RecurrencePattern.DailyRecurrence) {
73              recurrencePattern = RecurrencePattern.WeeklyRecurrence;
74          }
75      }
76  
77      public void setCount(String count) {
78          this.count = count;
79      }
80  
81      public enum RecurrencePattern {DailyRecurrence, WeeklyRecurrence,  AbsoluteMonthlyRecurrence, AbsoluteYearlyRecurrence}
82  
83      RecurrencePattern recurrencePattern;
84      int recurrenceInterval = 1;
85  
86      /**
87       * Create recurrence field update.
88       */
89      public RecurrenceFieldUpdate() {
90      }
91  
92      public void setRecurrencePattern(RecurrencePattern recurrencePattern) {
93          this.recurrencePattern = recurrencePattern;
94      }
95  
96      public void setRecurrencePattern(String value) {
97          if ("DAILY".equals(value)) {
98              setRecurrencePattern(RecurrenceFieldUpdate.RecurrencePattern.DailyRecurrence);
99          } else if ("WEEKLY".equals(value)) {
100             setRecurrencePattern(RecurrencePattern.WeeklyRecurrence);
101         } else if ("MONTHLY".equals(value)) {
102             setRecurrencePattern(RecurrencePattern.AbsoluteMonthlyRecurrence);
103         } else if ("YEARLY".equals(value)) {
104             setRecurrencePattern(RecurrencePattern.AbsoluteYearlyRecurrence);
105         }
106     }
107 
108     public void setRecurrenceInterval(String interval) {
109         this.recurrenceInterval = Integer.parseInt(interval);
110     }
111 
112     /**
113      * Write field to request writer.
114      *
115      * @param itemType item type
116      * @param writer   request writer
117      * @throws IOException on error
118      */
119     public void write(String itemType, Writer writer) throws IOException {
120         if (itemType != null) {
121             writer.write("<t:Set");
122             writer.write(itemType);
123             writer.write("Field>");
124         }
125 
126         // do not try to set empty value on create
127         if (itemType != null) {
128             writer.write("<t:FieldURI FieldURI=\"calendar:Recurrence\"/>");
129             writer.write("<t:CalendarItem>");
130 
131             writer.write("<t:Recurrence>");
132             writer.write("<t:");
133             writer.write(recurrencePattern.toString());
134             writer.write(">");
135             if (recurrencePattern == RecurrencePattern.AbsoluteYearlyRecurrence) {
136                 writeDayOfMonth(writer);
137                 writeMonth(writer);
138             } else if (recurrencePattern == RecurrencePattern.AbsoluteMonthlyRecurrence) {
139                 writeInterval(writer);
140                 writeDayOfMonth(writer);
141             } else if (recurrencePattern == RecurrencePattern.WeeklyRecurrence) {
142                 writeInterval(writer);
143                 writeDaysOfWeek(writer);
144             } else if (recurrencePattern == RecurrencePattern.DailyRecurrence) {
145                 writeInterval(writer);
146             }
147             writer.write("</t:");
148             writer.write(recurrencePattern.toString());
149             writer.write(">");
150             writeStartEnd(writer);
151             writer.write("</t:Recurrence>");
152 
153             writer.write("</t:CalendarItem>");
154         }
155 
156         if (itemType != null) {
157             writer.write("</t:Set");
158             writer.write(itemType);
159             writer.write("Field>");
160         }
161     }
162 
163     private void writeInterval(Writer writer) throws IOException {
164         writer.write("<t:Interval>");
165         writer.write(String.valueOf(recurrenceInterval));
166         writer.write("</t:Interval>");
167     }
168 
169     private void writeStartEnd(Writer writer) throws IOException {
170         if (count != null) {
171             writer.write("<t:NumberedRecurrence>");
172             writer.write("<t:StartDate>");
173             writer.write(getFormattedDate(startDate));
174             writer.write("</t:StartDate>");
175             writer.write("<t:NumberOfOccurrences>");
176             writer.write(count);
177             writer.write("</t:NumberOfOccurrences>");
178             writer.write("</t:NumberedRecurrence>");
179         } else if (endDate == null) {
180             writer.write("<t:NoEndRecurrence><t:StartDate>");
181             writer.write(getFormattedDate(startDate));
182             writer.write("</t:StartDate></t:NoEndRecurrence>");
183         } else {
184             writer.write("<t:EndDateRecurrence>");
185             writer.write("<t:StartDate>");
186             writer.write(getFormattedDate(startDate));
187             writer.write("</t:StartDate>");
188             writer.write("<t:EndDate>");
189             writer.write(getFormattedDate(endDate));
190             writer.write("</t:EndDate>");
191             writer.write("</t:EndDateRecurrence>");
192 
193         }
194     }
195 
196     private void writeDaysOfWeek(Writer writer) throws IOException {
197         writer.write("<t:DaysOfWeek>");
198         if (byDays != null) {
199             boolean first = true;
200             for (String dayOfeek:byDays) {
201                 if (first) {
202                     first = false;
203                 } else {
204                     writer.write(' ');
205                 }
206                 writer.write(dayOfeek);
207             }
208         } else {
209             writer.write(getDayOfWeek());
210         }
211         writer.write("</t:DaysOfWeek>");
212     }
213 
214     private void writeDayOfMonth(Writer writer) throws IOException {
215         writer.write("<t:DayOfMonth>");
216         writer.write(getDayOfMonth());
217         writer.write("</t:DayOfMonth>");
218     }
219 
220     private void writeMonth(Writer writer) throws IOException {
221         writer.write("<t:Month>");
222         writer.write(getMonth());
223         writer.write("</t:Month>");
224     }
225 
226     private String getDayOfWeek() {
227         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE", Locale.ENGLISH);
228         simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
229         return simpleDateFormat.format(startDate);
230     }
231 
232     private String getMonth() {
233         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMMMM", Locale.ENGLISH);
234         simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
235         return simpleDateFormat.format(startDate);
236     }
237 
238     private String getDayOfMonth() {
239         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("d", Locale.ENGLISH);
240         simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
241         return simpleDateFormat.format(startDate);
242     }
243 
244     private String getFormattedDate(Date date) {
245         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
246         simpleDateFormat.setTimeZone(ExchangeSession.GMT_TIMEZONE);
247         return simpleDateFormat.format(date);
248     }
249 
250 }