Java tutorial
/** * Copyright 2013 Instituto Superior Tcnico * * This file is part of FenixEdu IST Integration. * * FenixEdu IST Integration 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 IST Integration 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 IST Integration. If not, see <http://www.gnu.org/licenses/>. */ package pt.ist.fenixedu.integration.api; import static org.fenixedu.academic.dto.SummariesManagementBean.SummaryType.NORMAL_SUMMARY; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.servlet.ServletContext; import javax.servlet.UnavailableException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; import org.fenixedu.academic.domain.AdHocEvaluation; import org.fenixedu.academic.domain.Attends; import org.fenixedu.academic.domain.CompetenceCourse; import org.fenixedu.academic.domain.Coordinator; import org.fenixedu.academic.domain.CurricularCourse; import org.fenixedu.academic.domain.Degree; import org.fenixedu.academic.domain.DegreeCurricularPlan; import org.fenixedu.academic.domain.DegreeInfo; import org.fenixedu.academic.domain.Enrolment; import org.fenixedu.academic.domain.Evaluation; import org.fenixedu.academic.domain.Exam; import org.fenixedu.academic.domain.ExecutionCourse; import org.fenixedu.academic.domain.ExecutionDegree; import org.fenixedu.academic.domain.ExecutionInterval; import org.fenixedu.academic.domain.ExecutionSemester; import org.fenixedu.academic.domain.ExecutionYear; import org.fenixedu.academic.domain.Grouping; import org.fenixedu.academic.domain.Lesson; import org.fenixedu.academic.domain.LessonInstance; import org.fenixedu.academic.domain.Person; import org.fenixedu.academic.domain.Photograph; import org.fenixedu.academic.domain.Professorship; import org.fenixedu.academic.domain.Project; import org.fenixedu.academic.domain.Shift; import org.fenixedu.academic.domain.ShiftType; import org.fenixedu.academic.domain.StudentCurricularPlan; import org.fenixedu.academic.domain.Summary; import org.fenixedu.academic.domain.Teacher; import org.fenixedu.academic.domain.WrittenEvaluation; import org.fenixedu.academic.domain.WrittenEvaluationEnrolment; import org.fenixedu.academic.domain.accessControl.ActiveStudentsGroup; import org.fenixedu.academic.domain.accessControl.ActiveTeachersGroup; import org.fenixedu.academic.domain.accessControl.AllAlumniGroup; import org.fenixedu.academic.domain.accounting.Entry; import org.fenixedu.academic.domain.accounting.Event; import org.fenixedu.academic.domain.accounting.paymentCodes.AccountingEventPaymentCode; import org.fenixedu.academic.domain.contacts.EmailAddress; import org.fenixedu.academic.domain.contacts.WebAddress; import org.fenixedu.academic.domain.degreeStructure.BibliographicReferences.BibliographicReference; import org.fenixedu.academic.domain.degreeStructure.CourseGroup; import org.fenixedu.academic.domain.degreeStructure.DegreeModule; import org.fenixedu.academic.domain.degreeStructure.ProgramConclusion; import org.fenixedu.academic.domain.space.SpaceUtils; import org.fenixedu.academic.domain.student.Registration; import org.fenixedu.academic.domain.student.Student; import org.fenixedu.academic.domain.student.curriculum.ICurriculum; import org.fenixedu.academic.domain.student.curriculum.ICurriculumEntry; import org.fenixedu.academic.domain.studentCurriculum.CurriculumGroup; import org.fenixedu.academic.domain.studentCurriculum.Dismissal; import org.fenixedu.academic.domain.time.calendarStructure.AcademicInterval; import org.fenixedu.academic.domain.util.icalendar.CalendarFactory; import org.fenixedu.academic.domain.util.icalendar.ClassEventBean; import org.fenixedu.academic.domain.util.icalendar.EvaluationEventBean; import org.fenixedu.academic.domain.util.icalendar.EventBean; import org.fenixedu.academic.dto.InfoExam; import org.fenixedu.academic.dto.InfoExecutionCourse; import org.fenixedu.academic.dto.InfoLesson; import org.fenixedu.academic.dto.InfoLessonInstance; import org.fenixedu.academic.dto.InfoOccupation; import org.fenixedu.academic.dto.InfoShowOccupation; import org.fenixedu.academic.dto.InfoSiteRoomTimeTable; import org.fenixedu.academic.dto.InfoWrittenEvaluation; import org.fenixedu.academic.dto.InfoWrittenTest; import org.fenixedu.academic.dto.SummariesManagementBean; import org.fenixedu.academic.service.factory.RoomSiteComponentBuilder; import org.fenixedu.academic.service.services.exceptions.FenixServiceException; import org.fenixedu.academic.service.services.exceptions.InvalidArgumentsServiceException; import org.fenixedu.academic.service.services.student.EnrolStudentInWrittenEvaluation; import org.fenixedu.academic.service.services.student.UnEnrollStudentInWrittenEvaluation; import org.fenixedu.academic.service.services.teacher.CreateSummary; import org.fenixedu.academic.service.services.teacher.DeleteSummary; import org.fenixedu.academic.ui.struts.action.ICalendarSyncPoint; import org.fenixedu.academic.util.Bundle; import org.fenixedu.academic.util.ContentType; import org.fenixedu.academic.util.EvaluationType; import org.fenixedu.academic.util.HourMinuteSecond; import org.fenixedu.academic.util.MultiLanguageString; import org.fenixedu.bennu.core.domain.Bennu; import org.fenixedu.bennu.core.domain.User; import org.fenixedu.bennu.core.i18n.BundleUtil; import org.fenixedu.bennu.core.security.Authenticate; import org.fenixedu.bennu.oauth.annotation.OAuthEndpoint; import org.fenixedu.commons.i18n.I18N; import org.fenixedu.commons.i18n.LocalizedString; import org.fenixedu.commons.stream.StreamUtils; import org.fenixedu.spaces.domain.BlueprintFile; import org.fenixedu.spaces.domain.Space; import org.fenixedu.spaces.services.SpaceBlueprintsDWGProcessor; import org.joda.time.DateTime; import org.joda.time.DateTimeFieldType; import org.joda.time.Partial; import org.joda.time.TimeOfDay; import org.joda.time.YearMonthDay; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.CaseFormat; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.FluentIterable; import com.google.common.collect.Ordering; import com.google.common.io.ByteStreams; import com.google.common.net.HttpHeaders; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import net.fortuna.ical4j.model.Calendar; import pt.ist.fenixedu.contracts.domain.accessControl.ActiveEmployees; import pt.ist.fenixedu.integration.FenixEduIstIntegrationConfiguration; import pt.ist.fenixedu.integration.api.beans.FenixCalendar; import pt.ist.fenixedu.integration.api.beans.FenixCalendar.FenixCalendarEvent; import pt.ist.fenixedu.integration.api.beans.FenixCalendar.FenixClassEvent; import pt.ist.fenixedu.integration.api.beans.FenixCalendar.FenixEvaluationEvent; import pt.ist.fenixedu.integration.api.beans.FenixCourse; import pt.ist.fenixedu.integration.api.beans.FenixCurricularGroup; import pt.ist.fenixedu.integration.api.beans.FenixCurriculum; import pt.ist.fenixedu.integration.api.beans.FenixPayment; import pt.ist.fenixedu.integration.api.beans.FenixPayment.PaymentEvent; import pt.ist.fenixedu.integration.api.beans.FenixPayment.PendingEvent; import pt.ist.fenixedu.integration.api.beans.FenixPerson; import pt.ist.fenixedu.integration.api.beans.FenixPerson.FenixPhoto; import pt.ist.fenixedu.integration.api.beans.FenixPerson.FenixRole; import pt.ist.fenixedu.integration.api.beans.FenixPersonCourses; import pt.ist.fenixedu.integration.api.beans.FenixPersonCourses.FenixEnrolment; import pt.ist.fenixedu.integration.api.beans.publico.FenixAbout; import pt.ist.fenixedu.integration.api.beans.publico.FenixCourseEvaluation; import pt.ist.fenixedu.integration.api.beans.publico.FenixCourseExtended; import pt.ist.fenixedu.integration.api.beans.publico.FenixCourseExtended.FenixCompetence; import pt.ist.fenixedu.integration.api.beans.publico.FenixCourseExtended.FenixCompetence.BiblioRef; import pt.ist.fenixedu.integration.api.beans.publico.FenixCourseGroup; import pt.ist.fenixedu.integration.api.beans.publico.FenixCourseStudents; import pt.ist.fenixedu.integration.api.beans.publico.FenixDegree; import pt.ist.fenixedu.integration.api.beans.publico.FenixDegreeExtended; import pt.ist.fenixedu.integration.api.beans.publico.FenixDegreeExtended.FenixDegreeInfo; import pt.ist.fenixedu.integration.api.beans.publico.FenixDegreeExtended.FenixTeacher; import pt.ist.fenixedu.integration.api.beans.publico.FenixDomainModel; import pt.ist.fenixedu.integration.api.beans.publico.FenixExecutionCourse; import pt.ist.fenixedu.integration.api.beans.publico.FenixPeriod; import pt.ist.fenixedu.integration.api.beans.publico.FenixRoomEvent; import pt.ist.fenixedu.integration.api.beans.publico.FenixSchedule; import pt.ist.fenixedu.integration.api.beans.publico.FenixSpace; import pt.ist.fenixedu.integration.api.infra.FenixAPIFromExternalServer; import pt.ist.fenixedu.integration.dto.PersonInformationBean; import pt.ist.fenixedu.integration.service.services.externalServices.CreatePreEnrolment; import pt.ist.fenixframework.DomainObject; import pt.ist.fenixframework.FenixFramework; @Path("/fenix/v1") public class FenixAPIv1 { private static final Logger logger = LoggerFactory.getLogger(FenixAPIv1.class); public final static String PERSONAL_SCOPE = "INFO"; public final static String SCHEDULE_SCOPE = "SCHEDULE"; public final static String EVALUATIONS_SCOPE = "EVALUATIONS"; public final static String CURRICULAR_SCOPE = "CURRICULAR"; public final static String PAYMENTS_SCOPE = "PAYMENTS"; public final static String DEGREE_CURRICULAR_MANAGEMENT = "DEGREE_CURRICULAR_MANAGEMENT"; public final static String JSON_UTF8 = "application/json; charset=utf-8"; public final static String dayPattern = "dd/MM/yyyy"; public final static String dayHourPattern = "dd/MM/yyyy HH:mm"; public final static String hourPattern = "HH:mm"; public final static String dayHourSecondPattern = "yyyy-MM-dd HH:mm:ss"; public static final DateTimeFormatter formatDayHour = DateTimeFormat.forPattern(dayHourPattern); public static final DateTimeFormatter formatDay = DateTimeFormat.forPattern(dayPattern); public static final DateTimeFormatter formatHour = DateTimeFormat.forPattern(hourPattern); public static final DateTimeFormatter formatDayHourSecond = DateTimeFormat.forPattern(dayHourSecondPattern); private static Gson gson; private static final String ENROL = "yes"; private static final String UNENROL = "no"; public final static String ROLE_TEACHER = "TEACHER"; public final static String ROLE_STUDENT = "STUDENT"; public final static String ROLE_EMPLOYEE = "EMPLOYEE"; public final static String ROLE_ALUMNI = "ALUMNI"; static { gson = new GsonBuilder().setPrettyPrinting().create(); } private String mls(MultiLanguageString mls) { if (mls == null) { return ""; } return mls.getContent(); } private FenixPhoto getPhoto(final Person person) { FenixPhoto photo = null; try { final Photograph personalPhoto = person.getPersonalPhoto(); if (person.isPhotoAvailableToCurrentUser()) { final byte[] avatar = personalPhoto.getDefaultAvatar(); String type = ContentType.PNG.getMimeType(); String data = Base64.getEncoder().encodeToString(avatar); photo = new FenixPhoto(type, data); } } catch (Exception npe) { } return photo; } private Person getPerson() { User user = Authenticate.getUser(); if (user != null) { return user.getPerson(); } return null; } /** * It will return name, istid, campus, email, photo and contacts * * @return only public contacts and photo are available */ @GET @Produces(JSON_UTF8) @Path("person") @OAuthEndpoint(PERSONAL_SCOPE) public FenixPerson person() { final Person person = getPerson(); final User user = person.getUser(); PersonInformationBean pib = new PersonInformationBean(person, true); final Set<FenixRole> roles = new HashSet<FenixRole>(); if (new ActiveTeachersGroup().isMember(user)) { roles.add(new FenixPerson.TeacherFenixRole(pib.getTeacherDepartment())); } if (new ActiveStudentsGroup().isMember(user)) { roles.add(new FenixPerson.StudentFenixRole(pib.getStudentRegistrations())); } if (new AllAlumniGroup().isMember(user)) { ArrayList<Registration> concludedRegistrations = new ArrayList<>(); if (person.getStudent() != null) { concludedRegistrations.addAll(person.getStudent().getConcludedRegistrations()); } roles.add(new FenixPerson.AlumniFenixRole(concludedRegistrations)); } if (new ActiveEmployees().isMember(user)) { roles.add(new FenixPerson.EmployeeFenixRole()); } final String name = pib.getName(); final String displayName = person.getDisplayName(); final String gender = person.getGender().name(); final String birthday = person.getDateOfBirthYearMonthDay().toString(formatDay); final String username = person.getUsername(); final String campus = pib.getCampus(); final String email = pib.getEmail(); final String institutionalEmail = person.getInstitutionalEmailAddress() == null ? null : person.getInstitutionalEmailAddress().getValue(); final List<String> personalEmails = pib.getPersonalEmails(); final List<String> workEmails = pib.getWorkEmails(); List<String> personalWebAdresses = pib.getPersonalWebAdresses(); List<String> workWebAdresses = pib.getWorkWebAdresses(); final FenixPhoto photo = getPhoto(person); return new FenixPerson(campus, roles, photo, name, displayName, gender, birthday, username, email, institutionalEmail, personalEmails, workEmails, personalWebAdresses, workWebAdresses); } /** * Person courses (enrolled if student and teaching if teacher) * * @param academicTerm * @return enrolled courses and teaching courses */ @OAuthEndpoint(CURRICULAR_SCOPE) @GET @Produces(JSON_UTF8) @Path("person/courses/") public FenixPersonCourses personCourses(@QueryParam("academicTerm") String academicTerm) { final Person person = getPerson(); Set<ExecutionSemester> semesters = getExecutionSemesters(academicTerm); List<FenixEnrolment> enrolments = new ArrayList<FenixEnrolment>(); List<FenixCourse> teachingCourses = new ArrayList<FenixCourse>(); List<FenixCourse> attendingCourses = new ArrayList<>(); for (ExecutionSemester executionSemester : semesters) { fillEnrolments(person, enrolments, executionSemester); fillTeachingCourses(person, teachingCourses, executionSemester); fillAttendingCourses(person, attendingCourses, executionSemester); } return new FenixPersonCourses(enrolments, teachingCourses, attendingCourses); } public Set<ExecutionSemester> getExecutionSemesters(String academicTerm) { ExecutionInterval executionInterval = ExecutionInterval .getExecutionInterval(getAcademicInterval(academicTerm)); Set<ExecutionSemester> semesters = new HashSet<ExecutionSemester>(); if (executionInterval instanceof ExecutionYear) { semesters.addAll(((ExecutionYear) executionInterval).getExecutionPeriodsSet()); } else if (executionInterval instanceof ExecutionSemester) { semesters.add((ExecutionSemester) executionInterval); } return semesters; } public void fillTeachingCourses(final Person person, List<FenixCourse> teachingCourses, ExecutionSemester executionSemester) { for (final Professorship professorship : person.getProfessorships(executionSemester)) { final ExecutionCourse executionCourse = professorship.getExecutionCourse(); if (executionCourse.getExecutionPeriod().equals(executionSemester)) { teachingCourses.add(new FenixCourse(executionCourse)); } } } public void fillEnrolments(final Person person, List<FenixEnrolment> enrolments, ExecutionSemester executionSemester) { final Student foundStudent = person.getStudent(); if (foundStudent != null) { for (Registration registration : foundStudent.getAllRegistrations()) { for (Enrolment enrolment : registration.getEnrolments(executionSemester)) { final ExecutionCourse executionCourse = enrolment.getExecutionCourseFor(executionSemester); String grade = enrolment.getGrade().getValue(); double ects = enrolment.getEctsCredits(); enrolments.add(new FenixEnrolment(executionCourse, grade, ects)); } } } } public void fillAttendingCourses(final Person person, List<FenixCourse> attendingCourses, ExecutionSemester executionSemester) { final Student foundStudent = person.getStudent(); if (foundStudent != null) { foundStudent.getRegistrationsSet().stream() .flatMap(r -> r.getAttendingExecutionCoursesFor(executionSemester).stream()) .map(FenixCourse::new).forEach(attendingCourses::add); } } /* CALENDARS */ private enum EventType { CLASS, EVALUATION; } private FenixCalendar getFenixCalendar(String academicTerm, List<EventBean> eventBeans, EventType eventType) { List<FenixCalendarEvent> events = new ArrayList<FenixCalendarEvent>(); for (EventBean eventBean : eventBeans) { String start = formatDayHour.print(eventBean.getBegin()); String end = formatDayHour.print(eventBean.getEnd()); FenixPeriod eventPeriod = new FenixPeriod(start, end); String title = eventBean.getOriginalTitle(); Set<FenixSpace> rooms = new HashSet<>(); if (eventBean.getRooms() != null) { for (Space room : eventBean.getRooms()) { if (room != null) { rooms.add(FenixSpace.getSimpleSpace(room)); } } } FenixCalendarEvent event = null; switch (eventType) { case CLASS: final Shift classShift = ((ClassEventBean) eventBean).getClassShift(); event = new FenixClassEvent(eventPeriod, rooms, title, new FenixCourse(classShift.getExecutionCourse())); break; case EVALUATION: Set<FenixCourse> fenixCourses = FluentIterable.from(((EvaluationEventBean) eventBean).getCourses()) .transform(new Function<ExecutionCourse, FenixCourse>() { @Override public FenixCourse apply(ExecutionCourse course) { return new FenixCourse(course); } }).toSet(); FenixSpace assignedRoom = FenixSpace .getSimpleSpace(((EvaluationEventBean) eventBean).getAssignedRoom()); event = new FenixEvaluationEvent(eventPeriod, assignedRoom, rooms, title, fenixCourses); break; } events.add(event); } return new FenixCalendar(academicTerm, events); } private FenixCalendar getFenixClassCalendar(String academicTerm, List<EventBean> eventBeans) { return getFenixCalendar(academicTerm, eventBeans, EventType.CLASS); } private FenixCalendar getFenixEvaluationsCalendar(String academicTerm, List<EventBean> eventBeans) { return getFenixCalendar(academicTerm, eventBeans, EventType.EVALUATION); } private String evaluationCalendarICal(Person person) { ICalendarSyncPoint calendarSyncPoint = new ICalendarSyncPoint(); List<EventBean> listEventBean = calendarSyncPoint.getExams(person.getUser()); listEventBean.addAll(calendarSyncPoint.getTeachingExams(person.getUser())); Calendar createCalendar = CalendarFactory.createCalendar(listEventBean); return createCalendar.toString(); } private FenixCalendar evaluationCalendarJson(Person person) { final User user = person.getUser(); String academicTerm = ExecutionYear.readCurrentExecutionYear().getQualifiedName(); ICalendarSyncPoint calendarSyncPoint = new ICalendarSyncPoint(); List<EventBean> listEventBean = calendarSyncPoint.getExams(user); listEventBean.addAll(calendarSyncPoint.getTeachingExams(user)); return getFenixEvaluationsCalendar(academicTerm, listEventBean); } /** * calendar of all written evaluations (tests and exams). Available for * students and teachers. * * @param format * ("calendar" or "json") * @return If format is "calendar", returns iCal format. If not returns the * following json. */ @OAuthEndpoint(SCHEDULE_SCOPE) @GET @Path("person/calendar/evaluations") public Response calendarEvaluation(@QueryParam("format") String format) { validateFormat(format); final Person person = getPerson(); if (!new ActiveStudentsGroup().isMember(person.getUser())) { return Response.status(Status.OK).header(HttpHeaders.CONTENT_TYPE, JSON_UTF8).entity("{}").build(); } if ("calendar".equals(format)) { String evaluationCalendarICal = evaluationCalendarICal(person); return Response.ok(evaluationCalendarICal, "text/calendar;charset=UTF-8").build(); } else { return Response.status(Status.OK).header(HttpHeaders.CONTENT_TYPE, JSON_UTF8) .entity(evaluationCalendarJson(person)).build(); } } private String classesCalendarICal(Person person) { ICalendarSyncPoint calendarSyncPoint = new ICalendarSyncPoint(); List<EventBean> listEventBean = calendarSyncPoint.getClasses(person.getUser()); listEventBean.addAll(calendarSyncPoint.getTeachingClasses(person.getUser())); Calendar createCalendar = CalendarFactory.createCalendar(listEventBean); return createCalendar.toString(); } private FenixCalendar classesCalendarJson(Person person) { final User user = person.getUser(); String academicTerm = ExecutionYear.readCurrentExecutionYear().getQualifiedName(); ICalendarSyncPoint calendarSyncPoint = new ICalendarSyncPoint(); List<EventBean> listEventBean = calendarSyncPoint.getClasses(user); listEventBean.addAll(calendarSyncPoint.getTeachingClasses(user)); return getFenixClassCalendar(academicTerm, listEventBean); } /** * calendar of all lessons of students and teachers * * @param format * ("calendar" or "json") * @return If format is "calendar", returns iCal format. If not returns the * following json. */ @OAuthEndpoint(SCHEDULE_SCOPE) @GET @Path("person/calendar/classes") public Response calendarClasses(@QueryParam("format") String format) { validateFormat(format); Person person = getPerson(); if ("calendar".equals(format)) { String classesCalendarICal = classesCalendarICal(person); return Response.ok(classesCalendarICal, "text/calendar; charset=UTF-8").build(); } else { return Response.status(Status.OK).header(HttpHeaders.CONTENT_TYPE, JSON_UTF8) .entity(classesCalendarJson(person)).build(); } } /** * Complete curriculum (for students) * * @return */ @OAuthEndpoint(CURRICULAR_SCOPE) @GET @Path("person/curriculum") @Produces(JSON_UTF8) public List<FenixCurriculum> personCurriculum() { Person person = getPerson(); List<FenixCurriculum> curriculum = new ArrayList<>(); if (person.getStudent() != null) { curriculum = getStudentStatistics(person.getStudent().getRegistrationsSet()); } return curriculum; } private List<FenixCurriculum> getStudentStatistics(Set<Registration> registrationsList) { final List<FenixCurriculum> curriculums = new ArrayList<FenixCurriculum>(); for (Registration registration : registrationsList) { String start = registration.getFirstStudentCurricularPlan().getStartDateYearMonthDay() .toString(formatDay); StudentCurricularPlan lastCurricularPlan = registration.getLastStudentCurricularPlan(); String end = null; if (lastCurricularPlan.getEndDate() != null) { end = lastCurricularPlan.getEndDate().toString(formatDay); } ICurriculum icurriculum = lastCurricularPlan.getCurriculum(new DateTime(), null); final Integer curricularYear = icurriculum.getCurricularYear(); BigDecimal credits = icurriculum.getSumEctsCredits(); BigDecimal average = icurriculum.getRawGrade().getNumericValue(); Integer calculatedAverage = icurriculum.getFinalGrade().getIntegerValue(); boolean isFinished = lastCurricularPlan.isConcluded(); final List<FenixCurriculum.ApprovedCourse> courseInfos = new ArrayList<>(); for (StudentCurricularPlan studentCurricularPlan : registration.getStudentCurricularPlansSet()) { Stream<CurriculumGroup> curriculumGroups = getAllGroupsForConclusion(studentCurricularPlan); curriculumGroups.forEach(curriculumGroup -> { for (ICurriculumEntry iCurriculumEntry : curriculumGroup.getCurriculum() .getCurriculumEntries()) { String entryGradeValue = iCurriculumEntry.getGradeValue(); BigDecimal entryEcts = iCurriculumEntry.getEctsCreditsForCurriculum(); FenixCourse course = null; if (iCurriculumEntry instanceof Enrolment) { Enrolment enrolment = (Enrolment) iCurriculumEntry; ExecutionCourse executionCourse = enrolment .getExecutionCourseFor(enrolment.getExecutionPeriod()); if (executionCourse != null) { course = new FenixCourse(executionCourse); } else { CurricularCourse curricularCourse = enrolment.getCurricularCourse(); String entryName = mls(iCurriculumEntry.getPresentationName()); course = new FenixCourse(curricularCourse.getExternalId(), curricularCourse.getAcronym(), entryName); } } else if (iCurriculumEntry instanceof Dismissal) { Dismissal dismissal = (Dismissal) iCurriculumEntry; CurricularCourse curricularCourse = dismissal.getCurricularCourse(); String entryName = mls(iCurriculumEntry.getPresentationName()); course = new FenixCourse(curricularCourse.getExternalId(), curricularCourse.getAcronym(), entryName); } else { continue; } courseInfos.add(new FenixCurriculum.ApprovedCourse(course, entryGradeValue, entryEcts)); } }); } curriculums.add(new FenixCurriculum(new FenixDegree(lastCurricularPlan.getDegree()), start, end, credits, average, calculatedAverage, isFinished, curricularYear, courseInfos)); } return curriculums; } protected Stream<CurriculumGroup> getAllGroupsForConclusion(StudentCurricularPlan studentCurricularPlan) { final Stream<ProgramConclusion> conclusions = ProgramConclusion.conclusionsFor(studentCurricularPlan); Stream<CurriculumGroup> curriculumGroups = conclusions.map(pc -> pc.groupFor(studentCurricularPlan)) .filter(Optional::isPresent).map(Optional::get); return curriculumGroups; } private List<Event> calculateNotPayedEvents(final Person person) { final List<Event> result = new ArrayList<Event>(); result.addAll(person.getNotPayedEventsPayableOn(null, false)); result.addAll(person.getNotPayedEventsPayableOn(null, true)); return result; } /** * Information about gratuity payments (payed and not payed) * * @return */ @OAuthEndpoint(PAYMENTS_SCOPE) @GET @Path("person/payments") @Produces(JSON_UTF8) public FenixPayment personPayments() { Person person = getPerson(); List<PaymentEvent> payed = new ArrayList<>(); for (Entry entry : person.getPayments()) { String id = entry.getExternalId(); String amount = entry.getOriginalAmount().getAmountAsString(); String name = entry.getPaymentMode().getName(); String description = entry.getDescription().toString(); String shortDescription = getShortDescriptionForEntry(entry); String date = formatDay.print(entry.getWhenRegistered()); payed.add(new PaymentEvent(id, amount, name, description, shortDescription, date)); } List<Event> notPayedEvents = calculateNotPayedEvents(person); List<PendingEvent> notPayed = new ArrayList<>(); for (Event event : notPayedEvents) { for (AccountingEventPaymentCode accountingEventPaymentCode : event.getNonProcessedPaymentCodes()) { String id = accountingEventPaymentCode.getExternalId(); String description = accountingEventPaymentCode.getDescription(); String startDate = formatDay.print(accountingEventPaymentCode.getStartDate()) + " 00:00"; String endDate = formatDay.print(accountingEventPaymentCode.getEndDate()) + " 23:59"; String entity = accountingEventPaymentCode.getEntityCode(); String reference = accountingEventPaymentCode.getFormattedCode(); String amount = accountingEventPaymentCode.getMinAmount().getAmountAsString(); notPayed.add(new PendingEvent(id, description, new FenixPeriod(startDate, endDate), entity, reference, amount)); } } return new FenixPayment(payed, notPayed); } private String getShortDescriptionForEntry(Entry entry) { return BundleUtil.getString(Bundle.ENUMERATION, entry.getEntryType().getName()); } /** * Written evaluations for students * * @return enrolled and not enrolled student's evaluations */ @OAuthEndpoint(EVALUATIONS_SCOPE) @GET @Path("person/evaluations") @Produces(JSON_UTF8) public List<FenixCourseEvaluation.WrittenEvaluation> evaluations(@Context HttpServletResponse response, @Context HttpServletRequest request, @Context ServletContext context) { Person person = getPerson(); final Student student = person.getStudent(); if (!new ActiveStudentsGroup().isMember(person.getUser()) || student == null) { return new ArrayList<FenixCourseEvaluation.WrittenEvaluation>(); } List<FenixCourseEvaluation.WrittenEvaluation> evaluations = new ArrayList<>(); ExecutionYear executionYear = ExecutionYear.readCurrentExecutionYear(); for (Registration registration : student.getRegistrationsSet()) { for (ExecutionSemester executionSemester : executionYear.getExecutionPeriodsSet()) { List<ExecutionCourse> studentExecutionCourses = registration .getAttendingExecutionCoursesFor(executionSemester); List<Evaluation> unenroledEvaluation = new ArrayList<Evaluation>(); unenroledEvaluation.addAll(registration.getUnenroledExams(executionSemester)); unenroledEvaluation.addAll(registration.getUnenroledWrittenTests(executionSemester)); List<Evaluation> enroledEvaluation = new ArrayList<Evaluation>(); enroledEvaluation.addAll(registration.getEnroledExams(executionSemester)); enroledEvaluation.addAll(registration.getEnroledWrittenTests(executionSemester)); for (Evaluation evaluation : unenroledEvaluation) { Set<ExecutionCourse> examExecutionCourses = new HashSet<ExecutionCourse>( evaluation.getAssociatedExecutionCoursesSet()); examExecutionCourses.retainAll(studentExecutionCourses); evaluations.addAll( processEvaluation(evaluation, examExecutionCourses, false, student, executionSemester)); } for (Evaluation evaluation : enroledEvaluation) { Set<ExecutionCourse> examExecutionCourses = new HashSet<ExecutionCourse>( evaluation.getAssociatedExecutionCoursesSet()); examExecutionCourses.retainAll(studentExecutionCourses); evaluations.addAll( processEvaluation(evaluation, examExecutionCourses, true, student, executionSemester)); } } } return evaluations; } private List<FenixCourseEvaluation.WrittenEvaluation> processEvaluation(Evaluation evaluation, Set<ExecutionCourse> executionCourses, final Boolean isEnrolled, final Student student, final ExecutionSemester executionSemester) { List<FenixCourseEvaluation.WrittenEvaluation> evaluations = new ArrayList<FenixCourseEvaluation.WrittenEvaluation>(); if (!executionSemester.equals(ExecutionSemester.readActualExecutionSemester())) { if (!(evaluation instanceof Exam) || !((Exam) evaluation).isSpecialSeason()) { return evaluations; } } for (ExecutionCourse executionCourse : executionCourses) { if (evaluation instanceof Exam) { Exam exam = (Exam) evaluation; if (!exam.isExamsMapPublished()) { continue; } } evaluations.add( getWrittenEvaluationJSON((WrittenEvaluation) evaluation, executionCourse, isEnrolled, student)); } return evaluations; } /** * Enrols in evaluation represented by oid if enrol is "yes". unenrols * evaluation if enrol is "no". * * @param oid * evaluations id * @param enrol * ( "yes" or "no") * @return all evaluations */ @OAuthEndpoint(EVALUATIONS_SCOPE) @PUT @Produces(JSON_UTF8) @Path("person/evaluations/{id}") public List<FenixCourseEvaluation.WrittenEvaluation> evaluations(@PathParam("id") String oid, @QueryParam("enrol") String enrol, @Context HttpServletResponse response, @Context HttpServletRequest request, @Context ServletContext context) { validateEnrol(enrol); WrittenEvaluation eval = getDomainObject(oid, WrittenEvaluation.class); try { if (enrol != null && !Strings.isNullOrEmpty(enrol.trim())) { if (enrol.equalsIgnoreCase(ENROL)) { EnrolStudentInWrittenEvaluation.runEnrolStudentInWrittenEvaluation(getPerson().getUsername(), eval.getExternalId()); } else if (enrol.equalsIgnoreCase(UNENROL)) { UnEnrollStudentInWrittenEvaluation .runUnEnrollStudentInWrittenEvaluation(getPerson().getUsername(), eval.getExternalId()); } } return evaluations(response, request, context); } catch (InvalidArgumentsServiceException e) { if (e.getMessage() == null) { final Set<ExecutionCourse> associatedExecutionCoursesSet = eval.getAssociatedExecutionCoursesSet(); for (final Registration registration : getPerson().getStudent().getRegistrationsSet()) { for (final Attends attends : registration.getAssociatedAttendsSet()) { final ExecutionCourse executionCourse = attends.getExecutionCourse(); if (associatedExecutionCoursesSet.contains(executionCourse)) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid_registration", "student registration is " + registration.getActiveStateType().name()); } } } throw newApplicationError(Status.PRECONDITION_FAILED, "student_not_registered", "the student does not have a registration in a degree associated with this evaluation"); } throw newApplicationError(Status.PRECONDITION_FAILED, e.getMessage(), e.getMessage()); } catch (FenixServiceException e) { throw newApplicationError(Status.PRECONDITION_FAILED, e.getMessage(), e.getMessage()); } } private final <T extends DomainObject> T getDomainObject(final String externalId, final Class<T> clazz) { try { T domainObject = FenixFramework.getDomainObject(externalId); if (!FenixFramework.isDomainObjectValid(domainObject) || !clazz.isAssignableFrom(domainObject.getClass())) { throw newApplicationError(Status.NOT_FOUND, "id not found", "id not found"); } return domainObject; } catch (Exception nfe) { throw newApplicationError(Status.NOT_FOUND, "id not found", "id not found"); } } private WebApplicationException newApplicationError(Status status, String error, String description) { JsonObject errorObject = new JsonObject(); errorObject.addProperty("error", error); errorObject.addProperty("description", description); return new WebApplicationException(Response.status(status).entity(errorObject.toString()).build()); } /** * generic information about the institution * * @return news and events rss */ @GET @Produces(JSON_UTF8) @Path("about") public FenixAbout about() { return FenixAbout.getInstance(); } /** * Academic Terms * * @return all the academic terms available to be used in other endpoints as academicTerm query parameter. */ @GET @Produces(JSON_UTF8) @Path("academicterms") public String academicTerms() { JsonObject obj = new JsonObject(); for (ExecutionYear year : Bennu.getInstance().getExecutionYearsSet()) { JsonArray sems = new JsonArray(); for (ExecutionSemester semester : year.getExecutionPeriodsSet()) { sems.add(new JsonPrimitive(semester.getQualifiedName())); } obj.add(year.getQualifiedName(), sems); } return gson.toJson(obj); } private List<String> getTeacherPublicMail(Teacher teacher) { final List<String> emails = new ArrayList<>(); if (teacher != null) { for (EmailAddress emailAddress : teacher.getPerson().getEmailAddresses()) { if (emailAddress.getVisibleToPublic()) { emails.add(emailAddress.getPresentationValue()); } } } return emails; } private List<String> getTeacherPublicWebAddress(Teacher teacher) { final List<String> urls = new ArrayList<>(); if (teacher != null) { for (WebAddress webAddress : teacher.getPerson().getWebAddresses()) { if (webAddress.getVisibleToPublic()) { urls.add(webAddress.getUrl()); } } } return urls; } /** * All information about degrees available * * @param academicTerm * @see academicTerms * */ @GET @Produces(JSON_UTF8) @Path("degrees") public List<FenixDegreeExtended> degrees(@QueryParam("academicTerm") String academicTerm) { AcademicInterval academicInterval = getAcademicInterval(academicTerm); List<FenixDegreeExtended> fenixDegrees = new ArrayList<>(); for (final ExecutionDegree executionDegree : ExecutionDegree.filterByAcademicInterval(academicInterval)) { fenixDegrees.add(getFenixDegree(executionDegree)); } return fenixDegrees; } @GET @Produces(JSON_UTF8) @Path("canteen") public String canteen(@QueryParam("day") String day, @QueryParam("name") String canteenName) { validateDay(day); if (day == null || Strings.isNullOrEmpty(day.trim())) { day = formatDay.print(new DateTime()); } if (canteenName == null || Strings.isNullOrEmpty(canteenName.trim())) { canteenName = FenixEduIstIntegrationConfiguration.getConfiguration().getFenixAPICanteenDefaultName(); } return FenixAPIFromExternalServer.getCanteen(day, canteenName); } @GET @Produces(JSON_UTF8) @Path("contacts") public String contacts() { return FenixAPIFromExternalServer.getContacts(); } @GET @Produces(JSON_UTF8) @Path("shuttle") public String shuttle() { return FenixAPIFromExternalServer.getShuttle(); } @GET @Produces(JSON_UTF8) @Path("degrees/all") public Set<FenixDegree> degreesAll() { Set<FenixDegree> degrees = new HashSet<FenixDegree>(); for (final Degree degree : Degree.readNotEmptyDegrees()) { degrees.add(new FenixDegree(degree, true)); } return degrees; } private FenixDegreeExtended getFenixDegree(ExecutionDegree executionDegree) { final Degree degree = executionDegree.getDegree(); List<FenixSpace> degreeCampus = new ArrayList<>(); ExecutionYear executionYear = executionDegree.getExecutionYear(); String name = degree.getNameI18N(executionYear).getContent(I18N.getLocale()); String type = degree.getDegreeTypeName(); String typeName = degree.getDegreeType().getName().getContent(); String degreeUrl = degree.getSiteUrl(); for (Space campus : degree.getCampus(executionYear)) { degreeCampus.add(FenixSpace.getSimpleSpace(campus)); } FenixDegreeExtended.FenixDegreeInfo fenixDegreeInfo = null; DegreeInfo degreeInfo = degree.getDegreeInfoFor(executionYear); if (degreeInfo == null) { degreeInfo = degree.getMostRecentDegreeInfo(executionYear); } if (degreeInfo != null) { String description = mls(degreeInfo.getDescription()); String objectives = mls(degreeInfo.getObjectives()); String designFor = mls(degreeInfo.getDesignedFor()); String requisites = mls(degreeInfo.getDegreeInfoCandidacy().getAccessRequisites()); String profissionalExits = mls(degreeInfo.getProfessionalExits()); String history = mls(degreeInfo.getHistory()); String operationRegime = mls(degreeInfo.getOperationalRegime()); String gratuity = mls(degreeInfo.getGratuity()); String links = mls(degreeInfo.getLinks()); fenixDegreeInfo = new FenixDegreeInfo(description, objectives, designFor, requisites, profissionalExits, history, operationRegime, gratuity, links); } final List<FenixTeacher> teachers = new ArrayList<>(); final Collection<Teacher> responsibleCoordinatorsTeachers = degree .getResponsibleCoordinatorsTeachers(executionYear); for (Teacher teacher : responsibleCoordinatorsTeachers) { String teacherName = teacher.getPerson().getName(); String istId = teacher.getPerson().getUsername(); List<String> mails = getTeacherPublicMail(teacher); List<String> urls = getTeacherPublicWebAddress(teacher); teachers.add(new FenixTeacher(teacherName, istId, mails, urls)); } FenixDegreeExtended fenixDegree = new FenixDegreeExtended(executionYear.getQualifiedName(), name, degree, type, typeName, degreeUrl, degreeCampus, fenixDegreeInfo, teachers); return fenixDegree; } /** * * Retrieves information about degree with id * * @param oid * degree id * @param academicTerm * ("yyyy/yyyy") */ @GET @Produces(JSON_UTF8) @Path("degrees/{id}") public FenixDegree degreesByOid(@PathParam("id") String oid, @QueryParam("academicTerm") String academicTerm) { Degree degree = getDomainObject(oid, Degree.class); final AcademicInterval academicInterval = getAcademicInterval(academicTerm, true); List<ExecutionDegree> executionDegrees = degree.getExecutionDegrees(academicInterval); if (!executionDegrees.isEmpty()) { final ExecutionDegree max = Ordering.from(ExecutionDegree.EXECUTION_DEGREE_COMPARATORY_BY_YEAR) .max(executionDegrees); if (max != null) { return getFenixDegree(max); } } throw newApplicationError(Status.NOT_FOUND, "resource_not_found", "No degree information found for " + degree.getName() + " on " + academicInterval.getPresentationName()); } /** * Courses for degree with id * * @param oid * degree id * @param academicTerm * ("yyyy/yyyy") */ @GET @Produces(JSON_UTF8) @Path("degrees/{id}/courses") public List<FenixExecutionCourse> coursesByODegreesId(@PathParam("id") String oid, @QueryParam("academicTerm") String academicTerm) { Degree degree = getDomainObject(oid, Degree.class); ExecutionSemester[] executionSemesters = getExecutionSemesters(academicTerm) .toArray(new ExecutionSemester[0]); final Set<ExecutionCourse> executionCourses = new HashSet<ExecutionCourse>(); degree.getDegreeCurricularPlansSet().stream().filter(DegreeCurricularPlan::isActive) .forEach(plan -> addExecutionCourses(plan.getRoot(), executionCourses, executionSemesters)); List<FenixExecutionCourse> fenixExecutionCourses = new ArrayList<>(); for (ExecutionCourse executionCourse : executionCourses) { String sigla = executionCourse.getSigla(); String credits = getCredits(executionCourse, degree); String name = executionCourse.getName(); String id = executionCourse.getExternalId(); String academicTermValue = executionCourse.getExecutionPeriod().getQualifiedName(); fenixExecutionCourses.add(new FenixExecutionCourse(sigla, credits, name, id, academicTermValue)); } return fenixExecutionCourses; } /** * Set the previously chosen courses for students * * @param oid degree id * @param academicTerm * @param preEnrolments * */ @POST @Produces(JSON_UTF8) @Path("degrees/{id}/preEnrolmentsCurricularGroups") @OAuthEndpoint(value = DEGREE_CURRICULAR_MANAGEMENT) public Response defaultEnrolments(@PathParam("id") String oid, @QueryParam("academicTerm") String academicTerm, JsonObject preEnrolments) { AcademicInterval academicInterval = getAcademicInterval(academicTerm, true); if (academicInterval == null) { throw newApplicationError(Status.BAD_REQUEST, "format_error", "academicTerm parameter must not be null"); } ExecutionInterval executionInterval = ExecutionInterval.getExecutionInterval(academicInterval); if (!(executionInterval instanceof ExecutionSemester)) { throw newApplicationError(Status.BAD_REQUEST, "format_error", "academicTerm parameter must be a semester"); } ExecutionSemester executionSemester = (ExecutionSemester) executionInterval; Degree degree = getDomainObject(oid, Degree.class); final Person coordinator = Authenticate.getUser().getPerson(); boolean isCoordinator = degree.getResponsibleCoordinators(executionSemester.getExecutionYear()).stream() .map(Coordinator::getPerson).anyMatch(p -> p == coordinator); if (!isCoordinator) { throw newApplicationError(Status.BAD_REQUEST, "notAllowed", "must be a responsible coordinator of the degree in the given semester"); } JsonObject report = new JsonObject(); report.add("errors", new JsonArray()); JsonArray jArray = preEnrolments.getAsJsonArray("defaultEnrolments"); for (JsonElement jsonElement : jArray) { JsonObject jsonObject = jsonElement.getAsJsonObject(); String userId = jsonObject.get("student").getAsString(); User user = User.findByUsername(userId); if (user == null) { report.get("errors").getAsJsonArray().add(new JsonPrimitive( "User " + userId + " not found. Pre enrolments for this user were not processed")); break; } for (JsonElement jsonPreEnrol : jsonObject.get("preEnrolments").getAsJsonArray()) { JsonObject jsonEnrolLine = jsonPreEnrol.getAsJsonObject(); String curricularCourseId = jsonEnrolLine.get("course").getAsString(); String groupId = jsonEnrolLine.get("group").getAsString(); CurricularCourse curricularCourse = null; try { curricularCourse = FenixFramework.getDomainObject(curricularCourseId); } catch (Exception e) { report.get("errors").getAsJsonArray().add(new JsonPrimitive( "Curricular course " + curricularCourseId + " not found for user " + userId)); break; } CourseGroup courseGroup = null; try { courseGroup = FenixFramework.getDomainObject(groupId); } catch (Exception e) { report.get("errors").getAsJsonArray() .add(new JsonPrimitive("Course group " + groupId + " not found for user " + userId)); break; } try { CreatePreEnrolment.create(executionSemester, degree, user, curricularCourse, courseGroup); } catch (Exception e) { report.get("errors").getAsJsonArray() .add(new JsonPrimitive("An error occured for user " + userId + " course group " + groupId + " and curricular course " + curricularCourseId + " - this pre enrolment was not successful - Exception: " + e.getMessage())); } } } return Response.ok(report).build(); } /** * Courses group structure for degree with id * * @param oid * degree id * @param academicTerm * */ @GET @Produces(JSON_UTF8) @Path("degrees/{id}/curricularGroups") public List<FenixCurricularGroup> curricularGroupsByDegreeId(@PathParam("id") String oid, @QueryParam("academicTerm") String academicTerm) { Degree degree = getDomainObject(oid, Degree.class); Set<ExecutionSemester> executionSemesters = getExecutionSemesters(academicTerm); ExecutionYear executionYear = executionSemesters.iterator().next().getExecutionYear(); Set<FenixCurricularGroup> result = new HashSet<FenixCurricularGroup>(); degree.getDegreeCurricularPlansForYear(executionYear).stream().filter(DegreeCurricularPlan::isActive) .forEach(dcp -> { result.add(new FenixCurricularGroup(dcp.getRoot(), executionYear)); addCurricularGroup(executionYear, result, dcp.getRoot()); }); return new ArrayList<FenixCurricularGroup>(result); } private void addCurricularGroup(ExecutionYear executionYear, Set<FenixCurricularGroup> result, CourseGroup group) { for (DegreeModule degreeModule : group.getChildDegreeModulesValidOn(executionYear)) { if (degreeModule.isCourseGroup()) { result.add(new FenixCurricularGroup((CourseGroup) degreeModule, executionYear)); addCurricularGroup(executionYear, result, (CourseGroup) degreeModule); } } } /** * Curricular courses for degree with id * * @param oid * degree id * @param academicTerm * */ @GET @Produces(JSON_UTF8) @Path("degrees/{id}/curricularCourses") public String curricularCoursesByDegreeId(@PathParam("id") String oid, @QueryParam("academicTerm") String academicTerm) { Degree degree = getDomainObject(oid, Degree.class); Set<ExecutionSemester> executionSemesters = getExecutionSemesters(academicTerm); ExecutionYear executionYear = executionSemesters.iterator().next().getExecutionYear(); final Set<CurricularCourse> curricularCourses = new HashSet<CurricularCourse>(); degree.getDegreeCurricularPlansForYear(executionYear).stream().filter(DegreeCurricularPlan::isActive) .forEach(plan -> addCurricularCourses(plan.getRoot(), curricularCourses, executionSemesters)); return curricularCourses.stream().map(cc -> { JsonObject object = new JsonObject(); object.addProperty("id", cc.getExternalId()); object.addProperty("name", cc.getName()); return object; }).collect(StreamUtils.toJsonArray()).toString(); } private void addCurricularCourses(final CourseGroup courseGroup, final Set<CurricularCourse> curricularCourses, final Set<ExecutionSemester> executionSemesters) { for (ExecutionSemester executionSemester : executionSemesters) { for (DegreeModule degreeModule : courseGroup.getChildDegreeModulesValidOn(executionSemester)) { if (degreeModule.isLeaf()) { final CurricularCourse curricularCourse = (CurricularCourse) degreeModule; curricularCourses.add(curricularCourse); } else { final CourseGroup childCourseGroup = (CourseGroup) degreeModule; addCurricularCourses(childCourseGroup, curricularCourses, executionSemesters); } } } } @GET @Produces(JSON_UTF8) @Path("degrees/{id}/students") @OAuthEndpoint(value = CURRICULAR_SCOPE, serviceOnly = true) public String enrolledByDegreeAndCurricularYear(@PathParam("id") String degreeId, @QueryParam("curricularYear") Integer year) { Degree degree = getDomainObject(degreeId, Degree.class); Stream<Registration> registrations = degree.getActiveDegreeCurricularPlans().stream() .flatMap(dcp -> dcp.getStudentCurricularPlansSet().stream()).filter(StudentCurricularPlan::isActive) .map(StudentCurricularPlan::getRegistration); if (year != null) { registrations = registrations.filter(r -> r.getCurricularYear() == year); } return registrations.map(r -> { JsonObject object = new JsonObject(); object.addProperty("username", r.getPerson().getUsername()); object.addProperty("name", r.getPerson().getUser().getProfile().getDisplayName()); return object; }).collect(StreamUtils.toJsonArray()).toString(); } private void addExecutionCourses(final CourseGroup courseGroup, final Collection<ExecutionCourse> executionCourseViews, final ExecutionSemester... executionPeriods) { for (final org.fenixedu.academic.domain.degreeStructure.Context context : courseGroup .getChildContextsSet()) { for (final ExecutionSemester executionSemester : executionPeriods) { if (context.isValid(executionSemester)) { final DegreeModule degreeModule = context.getChildDegreeModule(); if (degreeModule.isLeaf()) { final CurricularCourse curricularCourse = (CurricularCourse) degreeModule; for (final ExecutionCourse executionCourse : curricularCourse .getAssociatedExecutionCoursesSet()) { if (executionCourse.getExecutionPeriod() == executionSemester) { executionCourseViews.add(executionCourse); } } } else { final CourseGroup childCourseGroup = (CourseGroup) degreeModule; addExecutionCourses(childCourseGroup, executionCourseViews, executionPeriods); } } } } } private String getCredits(ExecutionCourse ec, Degree degree) { for (CurricularCourse curricularCourse : ec.getAssociatedCurricularCoursesSet()) { if (degree.equals(curricularCourse.getDegree())) { return curricularCourse.getEctsCredits().toString(); } } return "N/A"; } /** * Detailed information about course * * @param oid * course id * @return */ @GET @Produces(JSON_UTF8) @Path("courses/{id}/") public FenixCourseExtended coursesByOid(@PathParam("id") String oid) { ExecutionCourse executionCourse = getDomainObject(oid, ExecutionCourse.class); String acronym = executionCourse.getSigla(); String name = executionCourse.getName(); String evaluationMethod = executionCourse.getEvaluationMethodText(); String academicTerm = executionCourse.getExecutionPeriod().getQualifiedName(); String courseUrl = executionCourse.getSiteUrl(); if (courseUrl == null) { courseUrl = ""; } Map<CompetenceCourse, Set<CurricularCourse>> curricularCourses = executionCourse .getCurricularCoursesIndexedByCompetenceCourse(); List<FenixCourseExtended.FenixCompetence> moreInfo = new ArrayList<>(); for (Map.Entry<CompetenceCourse, Set<CurricularCourse>> entry : curricularCourses.entrySet()) { List<FenixCourseExtended.FenixCompetence.BiblioRef> biblios = new ArrayList<>(); final CompetenceCourse competenceCourse = entry.getKey(); for (BibliographicReference bibliographicReference : competenceCourse.getBibliographicReferences() .getBibliographicReferencesSortedByOrder()) { String author = bibliographicReference.getAuthors(); String reference = bibliographicReference.getReference(); String title = bibliographicReference.getTitle(); String bibYear = bibliographicReference.getYear(); String type = bibliographicReference.getType().getName(); String url = bibliographicReference.getUrl(); biblios.add(new BiblioRef(author, reference, title, bibYear, type, url)); } List<FenixCourseExtended.FenixCompetence.Degree> degrees = new ArrayList<>(); for (CurricularCourse curricularCourse : entry.getValue()) { String id = curricularCourse.getDegree().getExternalId(); String dName = curricularCourse.getDegree().getPresentationName(); String dacronym = curricularCourse.getAcronym(); degrees.add(new FenixCourseExtended.FenixCompetence.Degree(id, dName, dacronym)); } String program = competenceCourse.getProgram(); moreInfo.add(new FenixCompetence(competenceCourse.getExternalId(), program, biblios, degrees)); } int numberOfStudents = executionCourse.getAttendsSet().size(); List<FenixTeacher> teachers = new ArrayList<>(); for (Professorship professorship : executionCourse.getProfessorshipsSet()) { String tname = professorship.getPerson().getName(); String istid = professorship.getPerson().getUsername(); List<String> mail = getTeacherPublicMail(professorship.getTeacher()); List<String> url = getTeacherPublicWebAddress(professorship.getTeacher()); teachers.add(new FenixTeacher(tname, istid, mail, url)); } String summaryLink = courseUrl.concat("/rss/summary"); String announcementLink = courseUrl.concat("/rss/announcement"); return new FenixCourseExtended(acronym, name, evaluationMethod, academicTerm, numberOfStudents, summaryLink, announcementLink, courseUrl, moreInfo, teachers); } /** * Retrieve groups for course given by oid * * @param oid * course id */ @GET @Produces(JSON_UTF8) @Path("courses/{id}/groups") public List<FenixCourseGroup> groupsCoursesByOid(@PathParam("id") final String oid) { final ExecutionCourse executionCourse = getDomainObject(oid, ExecutionCourse.class); final List<FenixCourseGroup> groupings = new ArrayList<>(); for (final Grouping grouping : executionCourse.getGroupings()) { groupings.add(new FenixCourseGroup(grouping)); } return groupings; } /** * Returns summaries for course by id * * @param oid * course id * @return */ @GET @Produces(JSON_UTF8) @Path("courses/{id}/summaries") @OAuthEndpoint(PERSONAL_SCOPE) public List<FenixLessonSummary> summariesCoursesByOid(@PathParam("id") String oid) { final ExecutionCourse executionCourse = getDomainObject(oid, ExecutionCourse.class); List<FenixLessonSummary> summaries = new ArrayList<>(); for (Shift shift : executionCourse.getAssociatedShifts()) { for (Lesson lesson : shift.getAssociatedLessonsSet()) { lesson.getAllLessonDates().stream().sorted().map(ld -> { LessonInstance lessonInstance = lesson.getLessonInstanceFor(ld); HourMinuteSecond time = lesson.getBeginHourMinuteSecond(); TimeOfDay lessonTime = new TimeOfDay(time.getHour(), time.getMinuteOfHour(), time.getSecondOfMinute()); return new FenixLessonSummary(shift, ld.toDateTime(lessonTime), lesson.getSala(), lessonInstance); }).forEach(summaries::add); } } return summaries; } /** * Adds a summary for a lesson in a course by id * * @param oid * course id * @param summaryInfo * JSON object containing the summary info: * { * "shift": "shift_id", * "date": "yyyy-MM-dd HH:mm:ss", * "room": "room_id", * "taught": true/false, * "attendance": 0, * "title": { * "pt-PT": "pt title", * "en-GB": "en title" * }, * "content": { * "pt-PT": "pt content", * "en-GB": "en content" * } * } * @return */ @POST @Produces(JSON_UTF8) @Path("courses/{id}/summaries") @OAuthEndpoint(PERSONAL_SCOPE) public FenixLessonSummary createSummaryCourseByOid(@PathParam("id") String oid, JsonObject summaryInfo) { return addOrUpdateSummary(oid, summaryInfo, (bean) -> { try { CreateSummary.runCreateSummary(bean); } catch (Exception e) { throw newApplicationError(Status.PRECONDITION_FAILED, "validation error", e.getMessage()); } }); } /** * Edits a summary for a lesson in a course by id * * @param oid * course id * @param summaryInfo * JSON object containing the summary info: * { * "shift": "shift_id", * "date": "yyyy-MM-dd HH:mm:ss", * "room": "room_id", * "taught": true/false, * "attendance": 0, * "title": { * "pt-PT": "pt title", * "en-GB": "en title" * }, * "content": { * "pt-PT": "pt content", * "en-GB": "en content" * } * } * @return */ @PUT @Produces(JSON_UTF8) @Path("courses/{id}/summaries") @OAuthEndpoint(PERSONAL_SCOPE) public FenixLessonSummary updateSummaryCourseByOid(@PathParam("id") String oid, JsonObject summaryInfo) { return addOrUpdateSummary(oid, summaryInfo, (bean) -> { try { CreateSummary.runEditSummary(bean); } catch (Exception e) { throw newApplicationError(Status.PRECONDITION_FAILED, "validation error", e.getMessage()); } }); } private FenixLessonSummary addOrUpdateSummary(String courseOid, JsonObject summaryInfo, Consumer<SummariesManagementBean> service) { final String room, shiftId, date; final Boolean taught; final int attendance; final JsonObject title, content; try { room = summaryInfo.get("room").getAsString(); shiftId = summaryInfo.get("shift").getAsString(); date = summaryInfo.get("date").getAsString(); } catch (Exception ignored) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "missing keys 'room', 'shift' or 'date'"); } try { taught = summaryInfo.get("taught").getAsBoolean(); attendance = summaryInfo.get("attendance").getAsInt(); } catch (Exception ignored) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "missing keys 'taught' or 'attendance'"); } try { title = summaryInfo.getAsJsonObject("title"); content = summaryInfo.getAsJsonObject("content"); } catch (Exception ignored) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "missing keys 'title' or 'content'"); } final ExecutionCourse executionCourse = getDomainObject(courseOid, ExecutionCourse.class); final Space space = getDomainObject(room, Space.class); final Shift shift = getDomainObject(shiftId, Shift.class); if (!executionCourse.getAssociatedShifts().contains(shift)) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "invalid shift for this execution course"); } SummariesManagementBean bean = fillSummaryManagementBean(executionCourse, shift, space, date, title, content, taught, attendance); service.accept(bean); Lesson lesson = bean.getLesson(); DateTime lessonDateTime = DateTimeFormat.forPattern(dayHourSecondPattern).parseDateTime(date); LessonInstance lessonInstance = lesson.getLessonInstanceFor(lessonDateTime.toYearMonthDay()); return new FenixLessonSummary(shift, lessonDateTime, space, lessonInstance); } private SummariesManagementBean fillSummaryManagementBean(ExecutionCourse executionCourse, Shift shift, Space space, String date, JsonObject title, JsonObject content, Boolean taught, int attendance) { MultiLanguageString titleMLS, contentMLS; try { titleMLS = MultiLanguageString.fromLocalizedString(LocalizedString.fromJson(title)); contentMLS = MultiLanguageString.fromLocalizedString(LocalizedString.fromJson(content)); } catch (Exception e) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "'title' or 'content' is not a valid multi-language string"); } DateTime lessonDateTime = DateTimeFormat.forPattern(dayHourSecondPattern).parseDateTime(date); YearMonthDay lessonDate = lessonDateTime.toYearMonthDay(); Partial lessonTime = new Partial().with(DateTimeFieldType.hourOfDay(), lessonDateTime.getHourOfDay()) .with(DateTimeFieldType.minuteOfHour(), lessonDateTime.getMinuteOfHour()) .with(DateTimeFieldType.secondOfDay(), lessonDateTime.getSecondOfMinute()); Optional<Lesson> lesson = shift.getAssociatedLessonsSet().stream() .filter(l -> l.getAllLessonDates().stream().anyMatch(lessonDate::equals)) .filter(l -> l.getSala().equals(space)).findFirst(); if (!lesson.isPresent()) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "invalid lesson date or room"); } Person person = getPerson(); Professorship professorship = executionCourse.getProfessorship(person); String teacherName = person.getName(); LessonInstance lessonInstance = lesson.get().getLessonInstanceFor(lessonDate); Summary summary = lessonInstance != null ? lessonInstance.getSummary() : null; ShiftType shiftType = shift.getSortedTypes().first(); return new SummariesManagementBean(titleMLS, contentMLS, attendance, NORMAL_SUMMARY, professorship, teacherName, null, shift, lesson.get(), lessonDate, space, lessonTime, summary, professorship, shiftType, taught); } /** * Deletes a summary in a lesson of a course by id * * @param oid * course id * @param summaryInfo * JSON object containing the summary info: * { * "shift": "shift_id", * "date": "yyyy-MM-dd HH:mm:ss", * "room": "room_id", * } * @return */ @DELETE @Produces(JSON_UTF8) @Path("courses/{id}/summaries") @OAuthEndpoint(PERSONAL_SCOPE) public Response deleteSummaryCourseByOid(@PathParam("id") String oid, JsonObject summaryInfo) { final String shiftId, date, room; try { shiftId = summaryInfo.get("shift").getAsString(); date = summaryInfo.get("date").getAsString(); room = summaryInfo.get("room").getAsString(); } catch (Exception e) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "missing keys 'shift', 'date' or 'room'"); } final ExecutionCourse executionCourse = getDomainObject(oid, ExecutionCourse.class); final Space space = getDomainObject(room, Space.class); final Shift shift = getDomainObject(shiftId, Shift.class); DateTime lessonDateTime = DateTimeFormat.forPattern(dayHourSecondPattern).parseDateTime(date); YearMonthDay lessonDate = lessonDateTime.toYearMonthDay(); Optional<LessonInstance> lessonInstance = shift.getAssociatedLessonsSet().stream() .map(l -> l.getLessonInstanceFor(lessonDate)).filter(l -> l != null && l.getRoom().equals(space)) .findFirst(); if (!lessonInstance.isPresent()) { throw newApplicationError(Status.PRECONDITION_FAILED, "invalid parameters", "invalid lesson date or room"); } final Person person = getPerson(); Summary summary = lessonInstance.get().getSummary(); Professorship professorship = executionCourse.getProfessorship(person); try { DeleteSummary.runDeleteSummary(executionCourse, summary, professorship); } catch (Exception e) { throw newApplicationError(Status.PRECONDITION_FAILED, "validation error", e.getMessage()); } return Response.noContent().build(); } /** * All students for course by id * * @param oid * course id * @return */ @GET @Produces(JSON_UTF8) @Path("courses/{id}/students") public FenixCourseStudents studentsCoursesByOid(@PathParam("id") String oid) { ExecutionCourse executionCourse = getDomainObject(oid, ExecutionCourse.class); return new FenixCourseStudents(executionCourse); } /** * * Returns evaluations for course by id (Test, Exams, Project, AdHoc, * OnlineTest) * * @param oid * @return */ @GET @Produces(JSON_UTF8) @Path("courses/{id}/evaluations") public List<FenixCourseEvaluation> evaluationCoursesByOid(@PathParam("id") String oid) { ExecutionCourse executionCourse = getDomainObject(oid, ExecutionCourse.class); final List<FenixCourseEvaluation> evals = new ArrayList<>(); for (Evaluation evaluation : executionCourse.getAssociatedEvaluationsSet()) { if (evaluation instanceof WrittenEvaluation) { evals.add(getWrittenEvaluationJSON((WrittenEvaluation) evaluation, executionCourse)); } else if (evaluation instanceof Project) { evals.add(getProjectEvaluationJSON((Project) evaluation)); } else if (evaluation instanceof AdHocEvaluation) { evals.add(getAdhocEvaluationJSON((AdHocEvaluation) evaluation)); } else { evals.add(getGenericTestJSON(evaluation)); } } return evals; } private FenixCourseEvaluation.AdHocEvaluation getAdhocEvaluationJSON(AdHocEvaluation adHocEvaluation) { return new FenixCourseEvaluation.AdHocEvaluation(adHocEvaluation.getPresentationName(), adHocEvaluation.getDescription()); } private FenixCourseEvaluation.GenericTest getGenericTestJSON(Evaluation evaluation) { String type = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, evaluation.getClass().getSimpleName()); return new FenixCourseEvaluation.GenericTest(evaluation.getPresentationName(), type); } private FenixCourseEvaluation.Project getProjectEvaluationJSON(Project projectEvaluation) { String name = projectEvaluation.getPresentationName(); String start = null; String end = null; if (projectEvaluation.getProjectBeginDateTime() != null) { start = formatDayHour.print(projectEvaluation.getProjectBeginDateTime()); } if (projectEvaluation.getProjectEndDateTime() != null) { end = formatDayHour.print(projectEvaluation.getProjectEndDateTime()); } return new FenixCourseEvaluation.Project(name, new FenixPeriod(start, end)); } private FenixCourseEvaluation.WrittenEvaluation getWrittenEvaluationJSON(WrittenEvaluation writtenEvaluation, ExecutionCourse executionCourse) { return getWrittenEvaluationJSON(writtenEvaluation, executionCourse, null, null); } private FenixCourseEvaluation.WrittenEvaluation getWrittenEvaluationJSON(WrittenEvaluation writtenEvaluation, ExecutionCourse executionCourse, Boolean isEnrolled, Student student) { String name = writtenEvaluation.getPresentationName(); EvaluationType type = writtenEvaluation.getEvaluationType(); String day = formatDay.print(writtenEvaluation.getDay().getTimeInMillis()); String beginningTime = formatHour.print(writtenEvaluation.getBeginning().getTimeInMillis()); String endTime = formatHour.print(writtenEvaluation.getEnd().getTimeInMillis()); FenixPeriod evaluationPeriod = new FenixPeriod(Joiner.on(" ").join(day, beginningTime), Joiner.on(" ").join(day, endTime)); boolean isEnrolmentPeriod = writtenEvaluation.getIsInEnrolmentPeriod(); final DateTime start = writtenEvaluation.getEnrolmentPeriodStart(); final DateTime end = writtenEvaluation.getEnrolmentPeriodEnd(); final String enrollmentPeriodStart = start == null ? null : formatDayHourSecond.print(start); final String enrollmentPeriodEnd = end == null ? null : formatDayHourSecond.print(end); String writtenEvaluationId = writtenEvaluation.getExternalId(); if (student != null) { Space assignedRoom = null; final WrittenEvaluationEnrolment evalEnrolment = writtenEvaluation .getWrittenEvaluationEnrolmentFor(student); if (evalEnrolment != null) { assignedRoom = evalEnrolment.getRoom(); } if (type.equals(EvaluationType.EXAM_TYPE)) { return new FenixCourseEvaluation.Exam(writtenEvaluationId, name, evaluationPeriod, isEnrolmentPeriod, enrollmentPeriodStart, enrollmentPeriodEnd, writtenEvaluation.getAssociatedRooms(), isEnrolled, Collections.singleton(executionCourse), assignedRoom); } else { return new FenixCourseEvaluation.Test(writtenEvaluationId, name, evaluationPeriod, isEnrolmentPeriod, enrollmentPeriodStart, enrollmentPeriodEnd, writtenEvaluation.getAssociatedRooms(), isEnrolled, Collections.singleton(executionCourse), assignedRoom); } } if (type.equals(EvaluationType.EXAM_TYPE)) { return new FenixCourseEvaluation.Exam(writtenEvaluationId, name, evaluationPeriod, isEnrolmentPeriod, enrollmentPeriodStart, enrollmentPeriodEnd, writtenEvaluation.getAssociatedRooms(), isEnrolled, Collections.singleton(executionCourse)); } else { return new FenixCourseEvaluation.Test(writtenEvaluationId, name, evaluationPeriod, isEnrolmentPeriod, enrollmentPeriodStart, enrollmentPeriodEnd, writtenEvaluation.getAssociatedRooms(), isEnrolled, Collections.singleton(executionCourse)); } } /** * All lessons and lesson period of course by id * * @param oid * @return */ @GET @Produces(JSON_UTF8) @Path("courses/{id}/schedule") public FenixSchedule scheduleCoursesByOid(@PathParam("id") String oid) { ExecutionCourse executionCourse = getDomainObject(oid, ExecutionCourse.class); return new FenixSchedule(executionCourse); } /** * Campus spaces * * @return */ @GET @Produces(JSON_UTF8) @Path("spaces") public List<FenixSpace> spaces() { List<FenixSpace> campi = new ArrayList<>(); for (Space campus : Space.getTopLevelSpaces()) { campi.add(FenixSpace.getSimpleSpace(campus)); } return campi; } /** * Space information regarding space type (Campus, Building, Floor or Room) * * @param oid * @param day * ("dd/mm/yyyy") * @return */ @GET @Produces(JSON_UTF8) @Path("spaces/{id}") public FenixSpace spacesByOid(@PathParam("id") String oid, @QueryParam("day") String day) { Space space = getDomainObject(oid, Space.class); if (SpaceUtils.isRoom(space)) { return getFenixRoom(space, getRoomDay(day)); } return FenixSpace.getSpace(space); } /** * Returns the blueprint of this space * * @param oid * @param format * ("dd/mm/yyyy") * @return */ @GET @Path("spaces/{id}/blueprint") public Response spaceBlueprint(@PathParam("id") String oid, final @QueryParam("format") String format) { final boolean isDwgFormat = format != null && format.equals("dwg"); final Space space = getDomainObject(oid, Space.class); if (space == null) { return Response.noContent().build(); } StreamingOutput stream; if (isDwgFormat) { Optional<BlueprintFile> optional = space.getBlueprintFile(); if (!optional.isPresent()) { optional = SpaceBlueprintsDWGProcessor.getSuroundingSpaceMostRecentBlueprint(space) .getBlueprintFile(); } final InputStream inputStream = optional.get().getStream(); stream = new StreamingOutput() { @Override public void write(OutputStream output) throws IOException, WebApplicationException { ByteStreams.copy(inputStream, output); } }; } else { stream = new StreamingOutput() { @Override public void write(OutputStream os) throws IOException, WebApplicationException { Boolean isToViewOriginalSpaceBlueprint = false; Boolean viewBlueprintNumbers = true; Boolean isToViewIdentifications = true; Boolean isToViewDoorNumbers = false; BigDecimal scalePercentage = new BigDecimal(100); DateTime now = new DateTime(); try { SpaceBlueprintsDWGProcessor.writeBlueprint(space, now, isToViewOriginalSpaceBlueprint, viewBlueprintNumbers, isToViewIdentifications, isToViewDoorNumbers, scalePercentage, os); } catch (UnavailableException e) { throw newApplicationError(Status.BAD_REQUEST, "problem found", "problem found"); } os.flush(); } }; } final String contentType = isDwgFormat ? "application/dwg" : "image/jpeg"; final String filename = space.getExternalId() + (isDwgFormat ? ".dwg" : ".jpg"); return Response.ok(stream, contentType).header("Content-Disposition", "attachment; filename=" + filename) .build(); } private FenixSpace.Room getFenixRoom(Space room, java.util.Calendar rightNow) { InfoSiteRoomTimeTable bodyComponent = RoomSiteComponentBuilder.getInfoSiteRoomTimeTable(rightNow, room, null); List<FenixRoomEvent> roomEvents = new ArrayList<FenixRoomEvent>(); try { for (Object occupation : bodyComponent.getInfoShowOccupation()) { InfoShowOccupation showOccupation = (InfoShowOccupation) occupation; DateTime date = new DateTime(rightNow); DateTime newDate = date .withDayOfWeek(showOccupation.getDiaSemana().getDiaSemanaInDayOfWeekJodaFormat()); String day = formatDay.print(newDate); FenixRoomEvent roomEvent = null; if (showOccupation instanceof InfoLesson || showOccupation instanceof InfoLessonInstance) { InfoShowOccupation lesson = showOccupation; InfoExecutionCourse infoExecutionCourse = lesson.getInfoShift().getInfoDisciplinaExecucao(); String start = formatHour.print(lesson.getInicio().getTimeInMillis()); String end = formatHour.print(lesson.getFim().getTimeInMillis()); String weekday = lesson.getDiaSemana().getDiaSemanaString(); FenixPeriod period = new FenixPeriod(day + " " + start, day + " " + end); String info = lesson.getInfoShift().getShiftTypesCodePrettyPrint(); FenixCourse course = new FenixCourse(infoExecutionCourse.getExecutionCourse()); roomEvent = new FenixRoomEvent.LessonEvent(start, end, weekday, day, period, info, course); } else if (showOccupation instanceof InfoWrittenEvaluation) { InfoWrittenEvaluation infoWrittenEvaluation = (InfoWrittenEvaluation) showOccupation; List<FenixCourse> courses = new ArrayList<>(); for (int iterEC = 0; iterEC < infoWrittenEvaluation.getAssociatedExecutionCourse() .size(); iterEC++) { InfoExecutionCourse infoEC = infoWrittenEvaluation.getAssociatedExecutionCourse() .get(iterEC); courses.add(new FenixCourse(infoEC.getExecutionCourse())); } String start = null; String end = null; String weekday = null; if (infoWrittenEvaluation instanceof InfoExam) { InfoExam infoExam = (InfoExam) infoWrittenEvaluation; start = infoExam.getBeginningHour(); end = infoExam.getEndHour(); weekday = infoWrittenEvaluation.getDiaSemana().getDiaSemanaString(); FenixPeriod period = new FenixPeriod(day + " " + start, day + " " + end); Integer season = infoExam.getSeason().getSeason(); roomEvent = new FenixRoomEvent.WrittenEvaluationEvent.ExamEvent(start, end, weekday, day, period, courses, season); } else if (infoWrittenEvaluation instanceof InfoWrittenTest) { InfoWrittenTest infoWrittenTest = (InfoWrittenTest) infoWrittenEvaluation; String description = infoWrittenTest.getDescription(); start = formatHour.print(infoWrittenTest.getInicio().getTimeInMillis()); end = formatHour.print(infoWrittenTest.getFim().getTimeInMillis()); weekday = infoWrittenTest.getDiaSemana().getDiaSemanaString(); FenixPeriod period = new FenixPeriod(day + " " + start, day + " " + end); roomEvent = new FenixRoomEvent.WrittenEvaluationEvent.TestEvent(start, end, weekday, day, period, courses, description); } } else if (showOccupation instanceof InfoOccupation) { InfoOccupation infoGenericEvent = (InfoOccupation) showOccupation; String description = infoGenericEvent.getDescription(); String title = infoGenericEvent.getTitle(); String start = formatHour.print(infoGenericEvent.getInicio().getTimeInMillis()); String end = formatHour.print(infoGenericEvent.getFim().getTimeInMillis()); ; String weekday = infoGenericEvent.getDiaSemana().getDiaSemanaString(); FenixPeriod period = new FenixPeriod(day + " " + start, day + " " + end); roomEvent = new FenixRoomEvent.GenericEvent(start, end, weekday, day, period, description, title); } if (roomEvent != null) { roomEvents.add(roomEvent); } } return new FenixSpace.Room(room, roomEvents); } catch (Exception e) { logger.error(e.getMessage(), e); throw newApplicationError(Status.INTERNAL_SERVER_ERROR, "berserk!", "something went wrong"); } } private java.util.Calendar getRoomDay(String day) { validateDay(day); java.util.Calendar rightNow = java.util.Calendar.getInstance(); Date date = null; if (day != null && !Strings.isNullOrEmpty(day.trim())) { date = formatDay.parseDateTime(day).toDate(); rightNow.setTime(date); } return rightNow; } private AcademicInterval getDefaultAcademicTerm() { return ExecutionSemester.readActualExecutionSemester().getAcademicInterval(); } private AcademicInterval getAcademicInterval(String academicTerm) { return getAcademicInterval(academicTerm, false); } private AcademicInterval getAcademicInterval(String academicTerm, Boolean nullDefault) { if (Strings.isNullOrEmpty(academicTerm)) { return nullDefault ? null : getDefaultAcademicTerm(); } ExecutionInterval interval = ExecutionInterval.getExecutionInterval(academicTerm); if (interval == null) { throw newApplicationError(Status.NOT_FOUND, "resource_not_found", "Can't find the academic term : " + academicTerm); } return interval.getAcademicInterval(); } private void validateDay(String day) { if (day != null && !Strings.isNullOrEmpty(day.trim())) { boolean invalid = false; try { DateTime parse = formatDay.parseDateTime(day); invalid = parse == null; } catch (IllegalArgumentException | UnsupportedOperationException e) { invalid = true; } finally { if (invalid) { throw newApplicationError(Status.BAD_REQUEST, "format_error", "day must be " + dayPattern); } } } } private void validateFormat(String format) { if (format != null && !Strings.isNullOrEmpty(format.trim())) { if (!("calendar".equals(format) || "json".equals(format))) { throw newApplicationError(Status.BAD_REQUEST, "format_error", "format must be calendar or json"); } } } private void validateEnrol(String enrol) { if (enrol == null || Strings.isNullOrEmpty(enrol.trim()) || !(ENROL.equals(enrol) || UNENROL.equals(enrol))) { throw newApplicationError(Status.BAD_REQUEST, "format_error", "enrol must be yes or no"); } } /** * information about the domain model implemented by this application * * @return domain model */ @GET @Produces(JSON_UTF8) @Path("domainModel") public String domainModel() { return new FenixDomainModel().toJSONString(); } }