/**
* Copyright © 2002 Instituto Superior Técnico
*
* This file is part of FenixEdu Academic.
*
* FenixEdu Academic is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FenixEdu Academic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.academic.ui.struts.action;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.fortuna.ical4j.model.Calendar;
import org.apache.commons.lang.CharEncoding;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.fenixedu.academic.domain.Attends;
import org.fenixedu.academic.domain.ExecutionCourse;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.Lesson;
import org.fenixedu.academic.domain.Professorship;
import org.fenixedu.academic.domain.Project;
import org.fenixedu.academic.domain.Shift;
import org.fenixedu.academic.domain.WrittenEvaluation;
import org.fenixedu.academic.domain.person.RoleType;
import org.fenixedu.academic.domain.student.Registration;
import org.fenixedu.academic.domain.util.icalendar.CalendarFactory;
import org.fenixedu.academic.domain.util.icalendar.EventBean;
import org.fenixedu.academic.ui.struts.action.base.FenixDispatchAction;
import org.fenixedu.academic.ui.struts.action.exceptions.FenixActionException;
import org.fenixedu.academic.ui.struts.action.student.ICalStudentTimeTable;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.util.CoreConfiguration;
import org.fenixedu.bennu.struts.annotations.Mapping;
import org.joda.time.DateTime;
import pt.ist.fenixframework.DomainObject;
import pt.ist.fenixframework.FenixFramework;
@Mapping(path = "/iCalendarSync", module = "external")
public class ICalendarSyncPoint extends FenixDispatchAction {
private Calendar getClassCalendar(User user, DateTime validity, HttpServletRequest request) {
List<EventBean> allEvents = getClasses(user);
String url = CoreConfiguration.getConfiguration().applicationUrl() + "/login";
EventBean event =
new EventBean("Renovar a chave do calendario.", validity.minusMinutes(30), validity.plusMinutes(30), false, null,
url, "A sua chave de sincronização do calendario vai expirar. Diriga-se ao Fénix para gerar nova chave");
allEvents.add(event);
return CalendarFactory.createCalendar(allEvents);
}
public List<EventBean> getClasses(User user) {
List<EventBean> allEvents = new ArrayList<EventBean>();
ExecutionSemester currentExecutionSemester = ExecutionSemester.readActualExecutionSemester();
if (user.getPerson().getStudent() != null) {
for (Registration registration : user.getPerson().getStudent().getRegistrationsSet()) {
for (Shift shift : registration.getShiftsForCurrentExecutionPeriod()) {
for (Lesson lesson : shift.getAssociatedLessonsSet()) {
allEvents.addAll(lesson.getAllLessonsEvents());
}
}
for (Shift shift : registration.getShiftsFor(currentExecutionSemester.getPreviousExecutionPeriod())) {
for (Lesson lesson : shift.getAssociatedLessonsSet()) {
allEvents.addAll(lesson.getAllLessonsEvents());
}
}
}
}
return allEvents;
}
public List<EventBean> getTeachingClasses(User user) {
List<EventBean> allEvents = new ArrayList<EventBean>();
for (Professorship professorShip : user.getPerson().getProfessorshipsSet()) {
ExecutionCourse executionCourse = professorShip.getExecutionCourse();
for (Lesson lesson : executionCourse.getLessons()) {
allEvents.addAll(lesson.getAllLessonsEvents());
}
}
return allEvents;
}
private Calendar getExamsCalendar(User user, DateTime validity, HttpServletRequest request) {
List<EventBean> allEvents = getExams(user);
String url = CoreConfiguration.getConfiguration().applicationUrl() + "/login";
EventBean event =
new EventBean("Renovar a chave do calendario.", validity.minusMinutes(30), validity.plusMinutes(30), false, null,
url, "A sua chave de sincronização do calendario vai expirar. Diriga-se ao Fénix para gerar nova chave");
allEvents.add(event);
return CalendarFactory.createCalendar(allEvents);
}
public List<EventBean> getExams(User user) {
List<EventBean> allEvents = new ArrayList<EventBean>();
ExecutionSemester currentExecutionSemester = ExecutionSemester.readActualExecutionSemester();
for (Registration registration : user.getPerson().getStudent().getRegistrationsSet()) {
for (WrittenEvaluation writtenEvaluation : registration.getWrittenEvaluations(currentExecutionSemester)) {
allEvents.addAll(writtenEvaluation.getAllEvents(registration));
}
for (Attends attends : registration.getAttendsForExecutionPeriod(currentExecutionSemester)) {
for (Project project : attends.getExecutionCourse().getAssociatedProjects()) {
allEvents.addAll(project.getAllEvents(attends.getExecutionCourse()));
}
}
for (WrittenEvaluation writtenEvaluation : registration.getWrittenEvaluations(currentExecutionSemester
.getPreviousExecutionPeriod())) {
allEvents.addAll(writtenEvaluation.getAllEvents(registration));
}
for (Attends attends : registration.getAttendsForExecutionPeriod(currentExecutionSemester
.getPreviousExecutionPeriod())) {
for (Project project : attends.getExecutionCourse().getAssociatedProjects()) {
allEvents.addAll(project.getAllEvents(attends.getExecutionCourse()));
}
}
}
return allEvents;
}
public List<EventBean> getTeachingExams(User user) {
List<EventBean> allEvents = new ArrayList<EventBean>();
for (Professorship professorShip : user.getPerson().getProfessorshipsSet()) {
ExecutionCourse executionCourse = professorShip.getExecutionCourse();
for (WrittenEvaluation writtenEvaluation : executionCourse.getWrittenEvaluations()) {
allEvents.addAll(writtenEvaluation.getAllEvents(null));
}
for (Project project : executionCourse.getAssociatedProjects()) {
allEvents.addAll(project.getAllEvents(executionCourse));
}
}
return allEvents;
}
private Calendar getCalendar(String method, User user, DateTime validity, HttpServletRequest request)
throws FenixActionException {
if (method == "syncClasses") {
return getClassCalendar(user, validity, request);
} else if (method == "syncExams") {
return getExamsCalendar(user, validity, request);
} else {
throw new FenixActionException("unexpected.syncing.method");
}
}
private void sync(HttpServletRequest request, final HttpServletResponse httpServletResponse, String method)
throws FenixActionException, Exception {
String userId = request.getParameter("user");
String payload = request.getParameter("payload");
String regId = request.getParameter("registrationID");
if (userId == null || payload == null || regId == null) {
throw new FenixActionException("error.expecting.parameter.not.found");
}
final DomainObject object = FenixFramework.getDomainObject(regId);
if (object instanceof Registration) {
User user = User.findByUsername(userId);
Registration registration = (Registration) object;
if (user.getPrivateKey() != null && user.getPrivateKey().getPrivateKeyValidity() != null) {
if (payload.equals(ICalStudentTimeTable.calculatePayload(method, registration, user))) {
if (user.getPrivateKey().getPrivateKeyValidity().isBeforeNow()) {
returnError(httpServletResponse, "private.key.validity.expired");
} else {
if (RoleType.STUDENT.isMember(user.getPerson().getUser())) {
encodeAndTransmitResponse(httpServletResponse,
getCalendar(method, user, user.getPrivateKey().getPrivateKeyValidity(), request));
} else {
returnError(httpServletResponse, "user.is.not.student");
}
}
} else {
returnError(httpServletResponse, "payload.checksum.doesnt.match");
}
} else {
returnError(httpServletResponse, "key.not.found");
}
} else {
returnError(httpServletResponse, "invalid.request");
}
}
public ActionForward syncExams(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request,
final HttpServletResponse httpServletResponse) throws Exception {
sync(request, httpServletResponse, "syncExams");
return null;
}
public ActionForward syncClasses(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request,
final HttpServletResponse httpServletResponse) throws Exception {
sync(request, httpServletResponse, "syncClasses");
return null;
}
@SuppressWarnings("deprecation")
private void returnError(HttpServletResponse httpServletResponse, String error) throws IOException {
httpServletResponse.setStatus(500);
httpServletResponse.getWriter().write(error);
}
private void encodeAndTransmitResponse(HttpServletResponse httpServletResponse, Calendar calendar) throws Exception {
httpServletResponse.setHeader("Content-Type", "text/calendar; charset=" + CharEncoding.UTF_8);
final OutputStream outputStream = httpServletResponse.getOutputStream();
outputStream.write(calendar.toString().getBytes(CharEncoding.UTF_8));
outputStream.close();
}
}