/**
* 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.resourceAllocationManager;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.fenixedu.academic.domain.FrequencyType;
import org.fenixedu.academic.domain.Lesson;
import org.fenixedu.academic.domain.LessonInstance;
import org.fenixedu.academic.domain.Shift;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.space.SpaceUtils;
import org.fenixedu.academic.dto.GenericPair;
import org.fenixedu.academic.dto.InfoLesson;
import org.fenixedu.academic.dto.InfoRoom;
import org.fenixedu.academic.dto.InfoRoomOccupationEditor;
import org.fenixedu.academic.dto.InfoShift;
import org.fenixedu.academic.dto.teacher.executionCourse.NextPossibleSummaryLessonsAndDatesBean;
import org.fenixedu.academic.service.services.exceptions.FenixServiceMultipleException;
import org.fenixedu.academic.service.services.resourceAllocationManager.CreateLesson;
import org.fenixedu.academic.service.services.resourceAllocationManager.DeleteLessonInstance;
import org.fenixedu.academic.service.services.resourceAllocationManager.DeleteLessons;
import org.fenixedu.academic.service.services.resourceAllocationManager.EditLesson;
import org.fenixedu.academic.ui.struts.action.exceptions.ExistingActionException;
import org.fenixedu.academic.ui.struts.action.exceptions.InterceptingActionException;
import org.fenixedu.academic.ui.struts.action.exceptions.InvalidTimeIntervalActionException;
import org.fenixedu.academic.ui.struts.action.resourceAllocationManager.base.FenixShiftAndExecutionCourseAndExecutionDegreeAndCurricularYearContextDispatchAction;
import org.fenixedu.academic.ui.struts.action.resourceAllocationManager.utils.PresentationConstants;
import org.fenixedu.academic.ui.struts.action.utils.ContextUtils;
import org.fenixedu.academic.ui.struts.config.FenixErrorExceptionHandler;
import org.fenixedu.academic.util.DiaSemana;
import org.fenixedu.bennu.struts.annotations.ExceptionHandling;
import org.fenixedu.bennu.struts.annotations.Exceptions;
import org.fenixedu.bennu.struts.annotations.Forward;
import org.fenixedu.bennu.struts.annotations.Forwards;
import org.fenixedu.bennu.struts.annotations.Mapping;
import org.fenixedu.spaces.domain.Space;
import org.joda.time.Interval;
import org.joda.time.YearMonthDay;
import pt.ist.fenixframework.FenixFramework;
/**
* @author Luis Cruz & Sara Ribeiro
*
*/
@Mapping(path = "/manageLesson", module = "resourceAllocationManager", input = "/manageLesson.do?method=findInput&page=0",
formBean = "manageLessonForm", functionality = ExecutionPeriodDA.class)
@Forwards({ @Forward(name = "ShowLessonForm", path = "/resourceAllocationManager/manageLesson_bd.jsp"),
@Forward(name = "EditShift", path = "/resourceAllocationManager/manageShift.do?method=prepareEditShift&page=0"),
@Forward(name = "LessonDeleted", path = "/resourceAllocationManager/manageShift.do?method=prepareEditShift&page=0"),
@Forward(name = "ViewAllLessonDates", path = "/resourceAllocationManager/showAllLessonDates.jsp"),
@Forward(name = "ChangeRoom", path = "/resourceAllocationManager/changeRoom_bd.jsp") })
@Exceptions({
@ExceptionHandling(key = "resources.Action.exceptions.ExistingActionException",
handler = FenixErrorExceptionHandler.class, type = ExistingActionException.class),
@ExceptionHandling(key = "resources.Action.exceptions.InterceptingActionException",
handler = FenixErrorExceptionHandler.class, type = InterceptingActionException.class),
@ExceptionHandling(key = "resources.Action.exceptions.InvalidTimeIntervalActionException",
handler = FenixErrorExceptionHandler.class, type = InvalidTimeIntervalActionException.class) })
public class ManageLessonDA extends FenixShiftAndExecutionCourseAndExecutionDegreeAndCurricularYearContextDispatchAction {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request,
HttpServletResponse response) throws Exception {
ContextUtils.setLessonContext(request);
ActionForward actionForward = super.execute(mapping, actionForm, request, response);
return actionForward;
}
public static String INVALID_TIME_INTERVAL = "errors.lesson.invalid.time.interval";
public static String INVALID_WEEKDAY = "errors.lesson.invalid.weekDay";
public static String UNKNOWN_ERROR = "errors.unknown";
public ActionForward findInput(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String action = request.getParameter("action");
if (action != null && action.equals("edit")) {
return prepareEdit(mapping, form, request, response);
}
return prepareCreate(mapping, form, request, response);
}
public ActionForward viewAllLessonDates(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
final InfoLesson infoLesson = (InfoLesson) request.getAttribute(PresentationConstants.LESSON);
final Lesson lesson = infoLesson.getLesson();
final Set<NextPossibleSummaryLessonsAndDatesBean> lessonDatesBean =
new TreeSet<NextPossibleSummaryLessonsAndDatesBean>(
NextPossibleSummaryLessonsAndDatesBean.COMPARATOR_BY_DATE_AND_HOUR);
for (final LessonInstance instance : infoLesson.getLesson().getLessonInstancesSet()) {
final NextPossibleSummaryLessonsAndDatesBean bean =
new NextPossibleSummaryLessonsAndDatesBean(lesson, instance.getDay());
bean.setRoom(instance.getRoom());
bean.setTime(instance.getStartTime());
lessonDatesBean.add(bean);
}
if (!lesson.wasFinished()) {
for (final YearMonthDay yearMonthDay : lesson.getAllLessonDatesWithoutInstanceDates()) {
final NextPossibleSummaryLessonsAndDatesBean bean =
new NextPossibleSummaryLessonsAndDatesBean(lesson, yearMonthDay);
bean.setRoom(lesson.getSala());
bean.setTime(lesson.getBeginHourMinuteSecond());
lessonDatesBean.add(bean);
}
}
request.setAttribute("lessonDates", lessonDatesBean);
request.setAttribute("lesson", lesson);
return mapping.findForward("ViewAllLessonDates");
}
public ActionForward deleteLessonInstance(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
NextPossibleSummaryLessonsAndDatesBean bean =
NextPossibleSummaryLessonsAndDatesBean.getNewInstance(request.getParameter("lessonDate"));
try {
DeleteLessonInstance.run(bean.getLesson(), bean.getDate());
ActionErrors actionErrors = new ActionErrors();
actionErrors.add(null, new ActionError("message.deleteLesson", bean.getDate()));
saveErrors(request, actionErrors);
} catch (UnsupportedOperationException unsupportedOperationException) {
ActionErrors actionErrors = new ActionErrors();
actionErrors.add(unsupportedOperationException.getMessage(),
new ActionError("error.Lesson.not.instanced", bean.getDate()));
saveErrors(request, actionErrors);
} catch (DomainException domainException) {
ActionErrors actionErrors = new ActionErrors();
actionErrors.add(domainException.getMessage(), new ActionError(domainException.getMessage()));
saveErrors(request, actionErrors);
}
return viewAllLessonDates(mapping, form, request, response);
}
public ActionForward deleteLessonInstances(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
final SortedSet<NextPossibleSummaryLessonsAndDatesBean> set = new TreeSet<NextPossibleSummaryLessonsAndDatesBean>();
for (final String lessonDate : request.getParameterValues("lessonDatesToDelete")) {
set.add(NextPossibleSummaryLessonsAndDatesBean.getNewInstance(lessonDate));
}
try {
DeleteLessonInstance.run(set);
ActionErrors actionErrors = new ActionErrors();
for (final NextPossibleSummaryLessonsAndDatesBean n : set) {
actionErrors.add(null, new ActionError("message.deleteLesson", n.getDate()));
}
saveErrors(request, actionErrors);
} catch (UnsupportedOperationException unsupportedOperationException) {
ActionErrors actionErrors = new ActionErrors();
for (final NextPossibleSummaryLessonsAndDatesBean n : set) {
actionErrors.add(unsupportedOperationException.getMessage(),
new ActionError("error.Lesson.not.instanced", n.getDate()));
}
saveErrors(request, actionErrors);
} catch (DomainException domainException) {
ActionErrors actionErrors = new ActionErrors();
actionErrors.add(domainException.getMessage(), new ActionError(domainException.getMessage()));
saveErrors(request, actionErrors);
}
return viewAllLessonDates(mapping, form, request, response);
}
public ActionForward prepareCreate(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
DynaActionForm manageLessonForm = (DynaActionForm) form;
InfoShift infoShift = (InfoShift) request.getAttribute(PresentationConstants.SHIFT);
Shift shift = FenixFramework.getDomainObject(infoShift.getExternalId());
GenericPair<YearMonthDay, YearMonthDay> maxLessonsPeriod = shift.getExecutionCourse().getMaxLessonsPeriod();
if (maxLessonsPeriod != null) {
request.setAttribute("executionDegreeLessonsStartDate", maxLessonsPeriod.getLeft().toString("dd/MM/yyyy"));
request.setAttribute("executionDegreeLessonsEndDate", maxLessonsPeriod.getRight().toString("dd/MM/yyyy"));
manageLessonForm.set("newBeginDate", maxLessonsPeriod.getLeft().toString("dd/MM/yyyy"));
manageLessonForm.set("newEndDate", maxLessonsPeriod.getRight().toString("dd/MM/yyyy"));
manageLessonForm.set("createLessonInstances", Boolean.TRUE);
} else {
ActionErrors actionErrors = new ActionErrors();
actionErrors.add("error.executionDegree.empty.lessonsPeriod", new ActionError(
"error.executionDegree.empty.lessonsPeriod"));
saveErrors(request, actionErrors);
return mapping.findForward("EditShift");
}
return mapping.findForward("ShowLessonForm");
}
public ActionForward prepareEdit(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
DynaActionForm manageLessonForm = (DynaActionForm) form;
InfoLesson infoLesson = (InfoLesson) request.getAttribute(PresentationConstants.LESSON);
manageLessonForm.set("diaSemana", infoLesson.getDiaSemana().getDiaSemana().toString());
manageLessonForm.set("horaInicio", "" + infoLesson.getInicio().get(Calendar.HOUR_OF_DAY));
manageLessonForm.set("minutosInicio", "" + infoLesson.getInicio().get(Calendar.MINUTE));
manageLessonForm.set("horaFim", "" + infoLesson.getFim().get(Calendar.HOUR_OF_DAY));
manageLessonForm.set("minutosFim", "" + infoLesson.getFim().get(Calendar.MINUTE));
final Space allocatableSpace = infoLesson.getAllocatableSpace();
if (allocatableSpace != null) {
manageLessonForm.set("nomeSala", "" + allocatableSpace.getName());
}
if (infoLesson.getFrequency().equals(FrequencyType.BIWEEKLY)) {
manageLessonForm.set("quinzenal", Boolean.TRUE);
}
if (infoLesson.getLessonBegin() != null) {
manageLessonForm.set("newBeginDate", infoLesson.getLessonBegin().toString("dd/MM/yyyy"));
}
if (infoLesson.getLessonEnd() != null) {
manageLessonForm.set("newEndDate", infoLesson.getLessonEnd().toString("dd/MM/yyyy"));
}
manageLessonForm.set("createLessonInstances", Boolean.TRUE);
Lesson lesson = FenixFramework.getDomainObject(infoLesson.getExternalId());
GenericPair<YearMonthDay, YearMonthDay> maxLessonsPeriod = lesson.getShift().getExecutionCourse().getMaxLessonsPeriod();
if (maxLessonsPeriod != null) {
request.setAttribute("executionDegreeLessonsStartDate", maxLessonsPeriod.getLeft().toString("dd/MM/yyyy"));
request.setAttribute("executionDegreeLessonsEndDate", maxLessonsPeriod.getRight().toString("dd/MM/yyyy"));
}
request.setAttribute("action", "edit");
return mapping.findForward("ShowLessonForm");
}
public ActionForward prepareChangeRoom(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
viewAllLessonDates(mapping, form, request, response);
final InfoLesson infoLesson = (InfoLesson) request.getAttribute(PresentationConstants.LESSON);
final Interval[] intervals = infoLesson.getLesson().getAllLessonIntervals().toArray(new Interval[0]);
final List<Space> emptySpaces = SpaceUtils.allocatableSpace(null, true, intervals);
Collections.sort(emptySpaces, SpaceUtils.COMPARATOR_BY_PRESENTATION_NAME);
request.setAttribute("emptySpaces", emptySpaces);
return mapping.findForward("ChangeRoom");
}
public ActionForward changeRoom(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
final InfoLesson infoLesson = (InfoLesson) request.getAttribute(PresentationConstants.LESSON);
final Space space = getDomainObject(request, "spaceOID");
try {
EditLesson.run(infoLesson.getLesson(), space);
} catch (final DomainException domainException) {
final ActionErrors actionErrors = new ActionErrors();
actionErrors.add(domainException.getMessage(),
new ActionError(domainException.getMessage(), domainException.getArgs()));
saveErrors(request, actionErrors);
}
return viewAllLessonDates(mapping, form, request, response);
}
public ActionForward createEditLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
DynaActionForm manageLessonForm = (DynaActionForm) form;
request.setAttribute("manageLessonForm", manageLessonForm);
ContextUtils.setExecutionPeriodContext(request);
DiaSemana weekDay = new DiaSemana(new Integer(formDay2EnumerateDay((String) manageLessonForm.get("diaSemana"))));
YearMonthDay newBeginDate = getDateFromForm(manageLessonForm, "newBeginDate");
YearMonthDay newEndDate = getDateFromForm(manageLessonForm, "newEndDate");
Boolean quinzenal = (Boolean) manageLessonForm.get("quinzenal");
if (quinzenal == null) {
quinzenal = new Boolean(false);
}
Calendar inicio = Calendar.getInstance();
inicio.set(Calendar.HOUR_OF_DAY, Integer.parseInt((String) manageLessonForm.get("horaInicio")));
inicio.set(Calendar.MINUTE, Integer.parseInt((String) manageLessonForm.get("minutosInicio")));
inicio.set(Calendar.SECOND, 0);
inicio.set(Calendar.MILLISECOND, 0);
Calendar fim = Calendar.getInstance();
fim.setTimeInMillis(inicio.getTimeInMillis());
fim.set(Calendar.HOUR_OF_DAY, Integer.parseInt((String) manageLessonForm.get("horaFim")));
fim.set(Calendar.MINUTE, Integer.parseInt((String) manageLessonForm.get("minutosFim")));
fim.set(Calendar.SECOND, 0);
fim.set(Calendar.MILLISECOND, 0);
InfoRoom infoSala = null;
if (!StringUtils.isEmpty((String) manageLessonForm.get("nomeSala"))) {
infoSala = new InfoRoom(SpaceUtils.findAllocatableSpaceForEducationByName((String) manageLessonForm.get("nomeSala")));
}
ActionErrors actionErrors = checkTimeIntervalAndWeekDay(inicio, fim, weekDay);
Lesson lesson = null;
if (actionErrors.isEmpty()) {
InfoShift infoShift = (InfoShift) (request.getAttribute(PresentationConstants.SHIFT));
InfoRoomOccupationEditor infoRoomOccupation = null;
if (infoSala != null) {
infoRoomOccupation = new InfoRoomOccupationEditor();
infoRoomOccupation.setDayOfWeek(weekDay);
infoRoomOccupation.setEndTime(fim);
infoRoomOccupation.setStartTime(inicio);
infoRoomOccupation.setInfoRoom(infoSala);
}
final FrequencyType frequency;
if (quinzenal.booleanValue()) {
frequency = FrequencyType.BIWEEKLY;
} else {
frequency = FrequencyType.WEEKLY;
}
if (infoRoomOccupation != null) {
infoRoomOccupation.setFrequency(frequency);
}
String action = request.getParameter("action");
if (action != null && action.equals("edit")) {
InfoLesson infoLessonOld = (InfoLesson) request.getAttribute(PresentationConstants.LESSON);
Boolean createLessonInstances = (Boolean) manageLessonForm.get("createLessonInstances");
try {
lesson =
EditLesson.run(infoLessonOld, weekDay, inicio, fim, frequency, infoRoomOccupation, infoShift,
newBeginDate, newEndDate, createLessonInstances);
} catch (DomainException domainException) {
actionErrors.add(domainException.getMessage(),
new ActionError(domainException.getMessage(), domainException.getArgs()));
saveErrors(request, actionErrors);
}
} else {
try {
lesson =
CreateLesson.run(weekDay, inicio, fim, frequency, infoRoomOccupation, infoShift, newBeginDate,
newEndDate);
} catch (DomainException domainException) {
actionErrors.add(domainException.getMessage(),
new ActionError(domainException.getMessage(), domainException.getArgs()));
saveErrors(request, actionErrors);
}
}
if (lesson != null) {
request.setAttribute(PresentationConstants.LESSON, InfoLesson.newInfoFromDomain(lesson));
request.setAttribute("action", action != null ? action : "create");
request.setAttribute("lesson", InfoLesson.newInfoFromDomain(lesson));
return prepareChangeRoom(mapping, manageLessonForm, request, response);
}
return mapping.findForward("EditShift");
}
saveErrors(request, actionErrors);
return mapping.getInputForward();
}
public ActionForward deleteLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
List<String> lessons = new ArrayList<String>();
lessons.add(request.getParameter(PresentationConstants.LESSON_OID));
try {
DeleteLessons.run(lessons);
} catch (FenixServiceMultipleException e) {
final ActionErrors actionErrors = new ActionErrors();
for (final DomainException domainException : e.getExceptionList()) {
actionErrors.add(domainException.getMessage(),
new ActionError(domainException.getMessage(), domainException.getArgs()));
}
saveErrors(request, actionErrors);
return mapping.findForward("LessonDeleted");
}
request.removeAttribute(PresentationConstants.LESSON_OID);
return mapping.findForward("LessonDeleted");
}
private YearMonthDay getDateFromForm(DynaActionForm manageLessonForm, String property) {
String newDateString = (String) manageLessonForm.get(property);
if (!StringUtils.isEmpty(newDateString)) {
try {
int day = Integer.parseInt(newDateString.substring(0, 2));
int month = Integer.parseInt(newDateString.substring(3, 5));
int year = Integer.parseInt(newDateString.substring(6, 10));
if (year == 0 || month == 0 || day == 0) {
return null;
} else {
return new YearMonthDay(year, month, day);
}
} catch (NumberFormatException e) {
return null;
}
}
return null;
}
private String formDay2EnumerateDay(String string) {
String result = string;
if (string.equalsIgnoreCase("2")) {
result = "2";
}
if (string.equalsIgnoreCase("3")) {
result = "3";
}
if (string.equalsIgnoreCase("4")) {
result = "4";
}
if (string.equalsIgnoreCase("5")) {
result = "5";
}
if (string.equalsIgnoreCase("6")) {
result = "6";
}
if (string.equalsIgnoreCase("S")) {
result = "7";
}
return result;
}
private ActionErrors checkTimeIntervalAndWeekDay(Calendar begining, Calendar end, DiaSemana weekday) {
ActionErrors actionErrors = new ActionErrors();
String beginMinAppend = "";
String endMinAppend = "";
if (begining.get(Calendar.MINUTE) == 0) {
beginMinAppend = "0";
}
if (end.get(Calendar.MINUTE) == 0) {
endMinAppend = "0";
}
if (begining.getTime().getTime() >= end.getTime().getTime()) {
actionErrors.add(
INVALID_TIME_INTERVAL,
new ActionError(INVALID_TIME_INTERVAL, "" + begining.get(Calendar.HOUR_OF_DAY) + ":"
+ begining.get(Calendar.MINUTE) + beginMinAppend + " - " + end.get(Calendar.HOUR_OF_DAY) + ":"
+ end.get(Calendar.MINUTE) + endMinAppend));
}
if (weekday.getDiaSemana().intValue() < 1 || weekday.getDiaSemana().intValue() > 7) {
actionErrors.add(INVALID_WEEKDAY, new ActionError(INVALID_WEEKDAY, ""));
}
return actionErrors;
}
}