1 /* CalendarManager.java
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 package de.dhbwloe.campusapp.vorlesungen;
17 import android.util.Log;
19 import net.fortuna.ical4j.model.Calendar;
20 import net.fortuna.ical4j.model.Component;
21 import net.fortuna.ical4j.model.Property;
23 import java.text.DateFormat;
24 import java.text.ParseException;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Date;
28 import java.util.ListIterator;
29 import java.util.Locale;
31 import de.dhbwloe.campusapp.CampusAppContext;
32 import de.dhbwloe.campusapp.network.IscRequestHelper;
33 import de.dhbwloe.campusapp.search.SearchIndices;
36 * Created by pk910 on 19.01.2016.
38 public class CalendarManager extends IscRequestHelper {
39 private static final String[][] PLAN_SOURCES = {
40 {"STUV", "https://www.google.com/calendar/ical/asta.dhbw.de_c0g35t6hrh16kr4ankrqg2rdm4%40group.calendar.google.com/public/basic.ics"},
43 private CampusAppContext AppContext;
44 private boolean bRequestRunning = false;
45 private boolean bFastSynchronisation = false;
46 private String sCourseName;
47 private String source[];
48 private ArrayList<CalendarManagerInterface> aCallbackInterfaces = new ArrayList<CalendarManagerInterface>();
50 public CalendarManager(CampusAppContext context, String courseName) {
52 sCourseName = courseName;
54 for(String src[] : PLAN_SOURCES) {
55 if(src[0].equalsIgnoreCase(courseName)) {
62 public void performFastSynchronisation(CalendarManagerInterface callback) {
63 performSynchronisation(callback, false);
66 public void performFullSynchronisation(CalendarManagerInterface callback) {
67 performSynchronisation(callback, true);
70 private void performSynchronisation(CalendarManagerInterface callback, boolean fullsync) {
71 if(sCourseName.length() == 0) {
72 callback.onCalendarUpdateFail("no course name");
76 aCallbackInterfaces.add(callback);
80 bFastSynchronisation = !fullsync;
81 bRequestRunning = true;
82 String courseCalendarUrl;
84 courseCalendarUrl = "https://webmail.dhbw-loerrach.de/owa/calendar/kal-" + sCourseName + "@dhbw-loerrach.de/Kalender/calendar.ics";
86 courseCalendarUrl = source[1];
88 requestCalenderFromWeb(courseCalendarUrl);
92 protected void onCalendarReceived(Calendar calendar) {
93 long timeFrom, timeTo;
94 long now = (new Date()).getTime() / 1000;
95 if(bFastSynchronisation) {
96 timeFrom = now - (86400 * 5);
97 timeTo = now + (86400 * 7 * 4);
99 timeFrom = now - (86400 * 365 * 4);
100 timeTo = now + (86400 * 365 * 4);
102 CourseEvent[] events = AppContext.getDatabaseManager().getCourseCalendarEvents(sCourseName, timeFrom, timeTo);
103 Log.i("CMSync", "Event count: " + events.length);
104 ArrayList<CourseEvent> newEvents = new ArrayList<CourseEvent>();
105 ArrayList<SearchIndices> newIndices = new ArrayList<SearchIndices>();
106 int lastEventIndex = 0;
107 ListIterator cIterator = calendar.getComponents().listIterator();
109 while (cIterator.hasNext()) {
110 Component event = (Component)cIterator.next();
114 prop = event.getProperty("UID");
117 uid = prop.getValue();
121 prop = event.getProperty("SEQUENCE");
124 sequence = Integer.parseInt(prop.getValue());
128 long startTime = 0, endTime = 0;
129 prop = event.getProperty("DTSTART");
131 startTime = getTimeFromTimestamp(prop.getValue());
133 Log.i("CMSync", "Parse Event: DTSTART not found!");
135 prop = event.getProperty("DTEND");
137 endTime = getTimeFromTimestamp(prop.getValue());
139 Log.i("CMSync", "Parse Event: DTEND not found!");
141 if(!(endTime > timeFrom && startTime < timeTo)) {
142 Log.i("CMSync", "Skip Entry: ("+timeFrom+" - "+timeTo+") Filter: "+startTime+" - "+endTime);
147 for(int i = lastEventIndex; i < events.length; i++) {
148 if(events[i].getUniqueId().equalsIgnoreCase(uid)) {
153 if(dbEvent == null && lastEventIndex > 0) {
154 for(int i = 0; i < lastEventIndex; i++) {
155 if(events[i].getUniqueId().equalsIgnoreCase(uid)) {
161 if(dbEvent == null) {
162 for(CourseEvent cevent : newEvents) {
163 if(cevent.getUniqueId().equalsIgnoreCase(uid)) {
170 if(dbEvent == null) {
172 Log.i("CMSync", "New Event "+uid);
173 dbEvent = new CourseEvent(sCourseName, uid, sequence, true);
174 newEvents.add(dbEvent);
176 Log.i("CMSync", "Existing Event "+uid+" ("+dbEvent.getSequenceId()+" >= "+sequence+")");
177 if(dbEvent.getSequenceId() >= sequence) {
178 continue; // skip event
180 dbEvent.setSequenceId(sequence);
183 prop = event.getProperty("SUMMARY");
185 dbEvent.setEventTitle(prop.getValue());
187 Log.i("CMSync", "Parse Event: SUMMARY not found!");
189 dbEvent.setEventFrom(startTime);
190 dbEvent.setEventTo(endTime);
192 prop = event.getProperty("LOCATION");
194 dbEvent.setEventLocation(prop.getValue());
196 Log.i("CMSync", "Parse Event: LOCATION not found!");
198 prop = event.getProperty("STATUS");
200 dbEvent.setEventStatus(prop.getValue());
202 Log.i("CMSync", "Parse Event: STATUS not found!");
204 prop = event.getProperty("RRULE");
206 dbEvent.setRecurRule(prop.getValue());
208 dbEvent.setRecurRule("");
210 prop = event.getProperty("EXDATE");
212 dbEvent.setExcludeDates(prop.getValue());
214 dbEvent.setExcludeDates("");
216 CourseGroup group = CourseGroup.GetCourseGroupByName(AppContext.getDatabaseManager(), sCourseName, dbEvent.getGroupTitle().trim());
218 dbEvent.setCourseGroup(group);
220 if(group.isNewGroup(true)) {
221 for(CalendarManagerInterface callback : aCallbackInterfaces) {
222 SearchIndices indices = callback.onGenerateCalendarSearchIndices(dbEvent);
223 if(indices != null) {
224 newIndices.add(indices);
229 dbEvent.update(AppContext.getDatabaseManager(), event);
230 Log.i("CMSync", "Update Event: "+dbEvent.getUniqueId());
233 SearchIndices[] newIndicesArr = new SearchIndices[newIndices.size()];
234 newIndicesArr = newIndices.toArray(newIndicesArr);
235 AppContext.addSearchIndices(newIndicesArr);
237 for(CalendarManagerInterface callback : aCallbackInterfaces) {
238 callback.onCalendarUpdateDone();
240 aCallbackInterfaces.clear();
241 bRequestRunning = false;
244 private long getTimeFromTimestamp(String timestamp) {
247 DateFormat df = new SimpleDateFormat("yyyyMMdd'T'kkmmss", Locale.ENGLISH);
249 Date result = df.parse(timestamp);
250 return result.getTime()/1000;
251 } catch (ParseException e) {
252 df = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
254 Date result = df.parse(timestamp);
255 return result.getTime()/1000;
256 } catch (ParseException e2) {
257 Log.i("CMSync", "Failed parsing: "+timestamp);
264 protected void onCalendarRequestFail(int statusCode, String errorMessage) {
265 Log.i("CMSync", "Calendar Error: "+statusCode);
266 for(CalendarManagerInterface callback : aCallbackInterfaces) {
267 callback.onCalendarUpdateFail("error " + statusCode + ": " + errorMessage);
269 aCallbackInterfaces.clear();
270 bRequestRunning = false;