/** * 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.domain; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.stream.Stream; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.fenixedu.academic.domain.exceptions.DomainException; import org.fenixedu.academic.domain.messaging.Forum; import org.fenixedu.academic.domain.time.calendarStructure.AcademicInterval; import org.fenixedu.academic.domain.time.calendarStructure.AcademicPeriod; import org.fenixedu.academic.util.PeriodState; import org.fenixedu.bennu.core.domain.Bennu; import org.fenixedu.bennu.core.domain.User; import org.fenixedu.spaces.domain.Space; import org.joda.time.DateTime; import org.joda.time.Interval; public class Teacher extends Teacher_Base { public static final Comparator<Teacher> TEACHER_COMPARATOR_BY_CATEGORY_AND_NUMBER = new Comparator<Teacher>() { @Override public int compare(Teacher teacher1, Teacher teacher2) { final int teacherIdCompare = teacher1.getPerson().getUsername().compareTo(teacher2.getPerson().getUsername()); if (teacher1.getLastCategory() == null && teacher2.getLastCategory() == null) { return teacherIdCompare; } else if (teacher1.getLastCategory() == null) { return 1; } else if (teacher2.getLastCategory() == null) { return -1; } else { final int categoryCompare = teacher1.getLastCategory().compareTo(teacher2.getLastCategory()); return categoryCompare == 0 ? teacherIdCompare : categoryCompare; } } }; public Teacher(Person person) { super(); setPerson(person); setRootDomainObject(Bennu.getInstance()); } public String getTeacherId() { return getPerson().getUsername(); } public static Teacher readByIstId(String istId) { User user = User.findByUsername(istId); if (user != null) { return user.getPerson().getTeacher(); } else { return null; } } @Override public void setPerson(Person person) { if (person == null) { throw new DomainException("error.teacher.no.person"); } super.setPerson(person); } /* * BUSINESS SERVICES * */ public List<Professorship> responsibleFors() { final List<Professorship> result = new ArrayList<Professorship>(); for (final Professorship professorship : this.getProfessorships()) { if (professorship.isResponsibleFor()) { result.add(professorship); } } return result; } public Professorship isResponsibleFor(ExecutionCourse executionCourse) { for (final Professorship professorship : this.getProfessorships()) { if (professorship.getResponsibleFor() && professorship.getExecutionCourse() == executionCourse) { return professorship; } } return null; } /** * Gets the latest department of the teacher for the given interval * * @param interval the time frame to consider * @return an {@code Optional} of the department. */ public Optional<Department> getDepartment(AcademicInterval interval) { return getTeacherAuthorization(interval).map(a -> a.getDepartment()); } /** * Same as {@link #getDepartment(AcademicInterval)} for the current semester * * @return The department or null */ public Department getDepartment() { return getDepartment(AcademicInterval.readDefaultAcademicInterval(AcademicPeriod.SEMESTER)).orElse(null); } /** * Gets the last department the teacher had up to the given interval (inclusive). Useful when we don't want to consider * authorization interruptions, and a teacher once belonging to a department stays with that status. * * @param interval the time frame to consider * @return an {@code Optional} of the department. */ public Department getLastDepartment(AcademicInterval interval) { return getLastTeacherAuthorization(interval).map(a -> a.getDepartment()).orElse(null); } /** * Same as {@link #getLastDepartment(AcademicInterval)} for the current semester * * @return The department or null */ public Department getLastDepartment() { return getLastDepartment(AcademicInterval.readDefaultAcademicInterval(AcademicPeriod.SEMESTER)); } /** * Gets the latest category of the teacher in the given interval. * * @param interval the time frame to consider * @return an {@code Optional} of the category. */ public Optional<TeacherCategory> getCategory(AcademicInterval interval) { return getTeacherAuthorization(interval).map(a -> a.getTeacherCategory()); } /** * Same as {@link #getCategory(AcademicInterval)} for the current semester * * @return the category or null */ public TeacherCategory getCategory() { return getCategory(AcademicInterval.readDefaultAcademicInterval(AcademicPeriod.SEMESTER)).orElse(null); } /** * Gets the last category the teacher had up to the given interval (inclusive). Useful when we don't want to consider * authorization interruptions, and a teacher once having a category preserves that status. * * @param interval the time frame to consider * @return an {@code Optional} of the category. */ public Optional<TeacherCategory> getLastCategory(AcademicInterval interval) { return getLastTeacherAuthorization(interval).map(a -> a.getTeacherCategory()); } /** * Same as {@link #getLastCategory(AcademicInterval)} for the current semester * * @return the category or null */ public TeacherCategory getLastCategory() { return getLastCategory(AcademicInterval.readDefaultAcademicInterval(AcademicPeriod.SEMESTER)).orElse(null); } public List<ExecutionCourse> getLecturedExecutionCoursesByExecutionYear(ExecutionYear executionYear) { List<ExecutionCourse> executionCourses = new ArrayList<ExecutionCourse>(); for (ExecutionSemester executionSemester : executionYear.getExecutionPeriodsSet()) { executionCourses.addAll(getLecturedExecutionCoursesByExecutionPeriod(executionSemester)); } return executionCourses; } public List<ExecutionCourse> getLecturedExecutionCoursesByExecutionPeriod(final ExecutionSemester executionSemester) { List<ExecutionCourse> executionCourses = new ArrayList<ExecutionCourse>(); for (Professorship professorship : getProfessorships()) { ExecutionCourse executionCourse = professorship.getExecutionCourse(); if (executionCourse.getExecutionPeriod().equals(executionSemester)) { executionCourses.add(executionCourse); } } return executionCourses; } public List<ExecutionCourse> getAllLecturedExecutionCourses() { List<ExecutionCourse> executionCourses = new ArrayList<ExecutionCourse>(); for (Professorship professorship : this.getProfessorships()) { executionCourses.add(professorship.getExecutionCourse()); } return executionCourses; } public Professorship getProfessorshipByExecutionCourse(final ExecutionCourse executionCourse) { return (Professorship) CollectionUtils.find(getProfessorships(), new Predicate() { @Override public boolean evaluate(Object arg0) { Professorship professorship = (Professorship) arg0; return professorship.getExecutionCourse() == executionCourse; } }); } public boolean hasProfessorshipForExecutionCourse(final ExecutionCourse executionCourse) { return (getProfessorshipByExecutionCourse(executionCourse) != null); } public List<Professorship> getDegreeProfessorshipsByExecutionPeriod(final ExecutionSemester executionSemester) { return (List<Professorship>) CollectionUtils.select(getProfessorships(), new Predicate() { @Override public boolean evaluate(Object arg0) { Professorship professorship = (Professorship) arg0; return professorship.getExecutionCourse().getExecutionPeriod() == executionSemester && !professorship.getExecutionCourse().isMasterDegreeDFAOrDEAOnly(); } }); } /* * PRIVATE METHODS * * */ public static Teacher readTeacherByUsername(final String userName) { final Person person = Person.readPersonByUsername(userName); return (person.getTeacher() != null) ? person.getTeacher() : null; } public static List<Teacher> readByNumbers(Collection<String> teacherId) { List<Teacher> selectedTeachers = new ArrayList<Teacher>(); for (final Teacher teacher : Bennu.getInstance().getTeachersSet()) { if (teacherId.contains(teacher.getPerson().getUsername())) { selectedTeachers.add(teacher); } // This isn't necessary, its just a fast optimization. if (teacherId.size() == selectedTeachers.size()) { break; } } return selectedTeachers; } public List<Professorship> getProfessorships(ExecutionSemester executionSemester) { return getPerson().getProfessorships(executionSemester); } public List<Professorship> getProfessorships(ExecutionYear executionYear) { return getPerson().getProfessorships(executionYear); } public SortedSet<ExecutionCourse> getCurrentExecutionCourses() { final SortedSet<ExecutionCourse> executionCourses = new TreeSet<ExecutionCourse>(ExecutionCourse.EXECUTION_COURSE_COMPARATOR_BY_EXECUTION_PERIOD_AND_NAME); final ExecutionSemester currentExecutionPeriod = ExecutionSemester.readActualExecutionSemester(); final ExecutionSemester previousExecutionPeriod = currentExecutionPeriod.getPreviousExecutionPeriod(); for (final Professorship professorship : getProfessorshipsSet()) { final ExecutionCourse executionCourse = professorship.getExecutionCourse(); final ExecutionSemester executionSemester = executionCourse.getExecutionPeriod(); if (executionSemester == currentExecutionPeriod || executionSemester == previousExecutionPeriod) { executionCourses.add(executionCourse); } } return executionCourses; } public boolean isResponsibleFor(CurricularCourse curricularCourse, ExecutionSemester executionSemester) { for (final ExecutionCourse executionCourse : curricularCourse.getAssociatedExecutionCoursesSet()) { if (executionCourse.getExecutionPeriod() == executionSemester) { if (isResponsibleFor(executionCourse) != null) { return true; } } } return false; } public boolean teachesAny(final Collection<ExecutionCourse> executionCourses, ExecutionYear executionYear) { for (final Professorship professorship : getProfessorships(executionYear)) { if (executionCourses.contains(professorship.getExecutionCourse())) { return true; } } return false; } public boolean teachesAny(final Collection<ExecutionCourse> executionCourses) { return getPerson().teachesAny(executionCourses); } public void delete() { super.setPerson(null); setRootDomainObject(null); deleteDomainObject(); } public boolean hasLessons(DateTime begin, DateTime end) { return hasLessons(begin, end, ExecutionYear.readCurrentExecutionYear()); } public boolean hasLessons(DateTime begin, DateTime end, ExecutionYear executionYear) { final Interval interval = new Interval(begin, end); for (Professorship professorship : getProfessorships(executionYear)) { Set<Shift> associatedShifts = professorship.getExecutionCourse().getAssociatedShifts(); for (Shift shift : associatedShifts) { Collection<Lesson> associatedLessons = shift.getAssociatedLessonsSet(); for (Lesson lesson : associatedLessons) { if (lesson.contains(interval)) { return true; } } } } return false; } public Collection<? extends Forum> getForuns(final ExecutionSemester executionSemester) { final Collection<Forum> res = new HashSet<Forum>(); for (Professorship professorship : getProfessorshipsSet()) { if (professorship.getExecutionCourse().getExecutionPeriod() == executionSemester) { res.addAll(professorship.getExecutionCourse().getForuns()); } } return res; } public boolean teachesAt(final Space campus) { for (final Professorship professorship : getProfessorshipsSet()) { final ExecutionCourse executionCourse = professorship.getExecutionCourse(); if (executionCourse.getExecutionPeriod().getState().equals(PeriodState.CURRENT)) { if (executionCourse.functionsAt(campus)) { return true; } } } return false; } public Set<Professorship> getProfessorshipsSet() { return getPerson().getProfessorshipsSet(); } public void addProfessorships(Professorship professorship) { getPerson().addProfessorships(professorship); } public void removeProfessorships(Professorship professorship) { getPerson().removeProfessorships(professorship); } public Collection<Professorship> getProfessorships() { return getPerson().getProfessorshipsSet(); } public Iterator<Professorship> getProfessorshipsIterator() { return getPerson().getProfessorshipsSet().iterator(); } public Stream<TeacherAuthorization> getRevokedTeacherAuthorizationStream() { return getRevokedAuthorizationSet().stream().sorted(Collections.reverseOrder()); } public Stream<TeacherAuthorization> getTeacherAuthorizationStream() { return getAuthorizationSet().stream().sorted(Collections.reverseOrder()); } public Optional<TeacherAuthorization> getTeacherAuthorization(AcademicInterval interval) { return getTeacherAuthorizationStream().filter(a -> a.getExecutionSemester().getAcademicInterval().equals(interval)) .findFirst(); } public Optional<TeacherAuthorization> getTeacherAuthorization() { return getTeacherAuthorization(AcademicInterval.readDefaultAcademicInterval(AcademicPeriod.SEMESTER)); } public boolean hasTeacherAuthorization(AcademicInterval interval) { return getTeacherAuthorization(interval).isPresent(); } public boolean hasTeacherAuthorization() { return getTeacherAuthorization().isPresent(); } protected Optional<TeacherAuthorization> getLastTeacherAuthorization(AcademicInterval interval) { return getTeacherAuthorizationStream().filter(a -> !a.getExecutionSemester().getAcademicInterval().isAfter(interval)) .findFirst(); } public Optional<TeacherAuthorization> getLatestTeacherAuthorizationInInterval(Interval interval) { return getTeacherAuthorizationStream().filter(a -> a.getExecutionSemester().getAcademicInterval().overlaps(interval)) .findFirst(); } public boolean isActiveContractedTeacher() { return getTeacherAuthorization().map(a -> a.isContracted()).orElse(false); } public boolean isErasmusCoordinator() { return !getMobilityCoordinationsSet().isEmpty(); } }