/** * Copyright © 2011 Instituto Superior Técnico * * This file is part of FenixEdu Teacher Credits. * * FenixEdu Teacher Credits 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 Teacher Credits 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 Teacher Credits. If not, see <http://www.gnu.org/licenses/>. */ package pt.ist.fenixedu.teacher.dto.externalServices; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.collections.comparators.ReverseComparator; import org.apache.commons.lang.StringUtils; import org.fenixedu.academic.domain.CourseLoad; import org.fenixedu.academic.domain.CurricularCourse; import org.fenixedu.academic.domain.Degree; import org.fenixedu.academic.domain.Department; import org.fenixedu.academic.domain.ExecutionCourse; import org.fenixedu.academic.domain.ExecutionSemester; import org.fenixedu.academic.domain.Professorship; import org.fenixedu.academic.domain.Qualification; import org.fenixedu.academic.domain.QualificationType; import org.fenixedu.academic.domain.ShiftType; import org.fenixedu.academic.domain.Teacher; import org.fenixedu.academic.domain.phd.InternalPhdParticipant; import org.fenixedu.academic.domain.phd.PhdIndividualProgramProcess; import org.fenixedu.academic.domain.thesis.ThesisEvaluationParticipant; import org.fenixedu.academic.domain.thesis.ThesisParticipationType; import org.fenixedu.commons.StringNormalizer; import org.joda.time.Interval; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pt.ist.fenixedu.contracts.domain.personnelSection.contracts.GiafProfessionalData; import pt.ist.fenixedu.contracts.domain.personnelSection.contracts.PersonProfessionalData; import pt.ist.fenixedu.contracts.domain.personnelSection.contracts.ProfessionalCategory; import pt.ist.fenixedu.contracts.domain.personnelSection.contracts.ProfessionalRegime; import pt.ist.fenixedu.teacher.domain.teacher.DegreeTeachingService; import pt.ist.fenixedu.teacher.domain.teacher.DegreeTeachingServiceCorrection; import pt.ist.fenixedu.teacher.domain.teacher.OtherService; import pt.ist.fenixedu.teacher.domain.teacher.TeacherService; public class TeacherCurricularInformation implements Serializable { private static final Logger logger = LoggerFactory.getLogger(TeacherCurricularInformation.class); protected Teacher teacher; protected Degree degree; protected SortedSet<ExecutionSemester> executionSemesters = new TreeSet<ExecutionSemester>( ExecutionSemester.COMPARATOR_BY_SEMESTER_AND_YEAR); protected SortedSet<QualificationBean> qualificationBeans = new TreeSet<QualificationBean>(new ReverseComparator( new Comparator<QualificationBean>() { @Override public int compare(final QualificationBean o1, final QualificationBean o2) { int compareType = o1.type.compareTo(o2.type); if (compareType == 0) { if (o1.year == null && o2.year == null) { return 0; } else if (o1.year == null) { return -1; } else if (o2.year == null) { return 1; } return o1.year.compareTo(o2.year); } if ((o1.getType().equals(QualificationType.AGGREGATION) && o2.getType().isDoctorate()) || (o2.getType().equals(QualificationType.AGGREGATION) && o1.getType().isDoctorate())) { return -compareType; } return compareType; } })); protected List<LecturedCurricularUnit> lecturedUCs = new ArrayList<LecturedCurricularUnit>(); protected List<String> teacherPublications = new ArrayList<String>(); public TeacherCurricularInformation(Teacher teacher, Degree degree, List<ExecutionSemester> executionSemester, List<String> list) { super(); this.teacher = teacher; this.degree = degree; this.executionSemesters.addAll(executionSemester); for (Qualification qualification : teacher.getPerson().getAssociatedQualificationsSet()) { if (qualification.getType() != null && (qualification.getType().isDegree() || qualification.getType().isMaster() || qualification.getType().isDoctorate() || qualification.getType().equals( QualificationType.AGGREGATION))) { this.qualificationBeans.add(new QualificationBean(qualification)); } } if (list != null) { this.teacherPublications = list; } setlecturedUCs(); } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } public SortedSet<QualificationBean> getQualifications() { return qualificationBeans; } public void setQualifications(SortedSet<QualificationBean> qualificationBeans) { this.qualificationBeans = qualificationBeans; } public String getUnitName() { Department lastDepartment = getTeacher() .getLatestTeacherAuthorizationInInterval( new Interval(executionSemesters.first().getBeginDateYearMonthDay().toDateTimeAtMidnight(), executionSemesters.last().getEndDateYearMonthDay().plusDays(1).toDateTimeAtMidnight())) .map(a -> a.getDepartment()).orElse(null); return lastDepartment == null ? null : lastDepartment.getName(); } public String getProfessionalCategoryName() { ProfessionalCategory lastCategory = ProfessionalCategory.getLastCategory(getTeacher(), executionSemesters.first().getBeginDateYearMonthDay() .toLocalDate(), executionSemesters.last().getEndDateYearMonthDay().toLocalDate()); if (lastCategory != null) { if (lastCategory.getName().getContent().equalsIgnoreCase("Assistente")) { return "Assistente"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Assistente Convidado")) { return "Assistente convidado"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Equip. Assistente") || lastCategory.getName().getContent().equalsIgnoreCase("Equiparado Assistente")) { return "Equiparado a Assistente"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Equip. Assistente Convidado")) { return "Equiparado a Assistente"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Equip. Prof. Auxiliar") || lastCategory.getName().getContent().equalsIgnoreCase("Equiparado Professor Auxiliar") || lastCategory.getName().getContent().equalsIgnoreCase("Professor Auxiliar")) { return "Professor Auxiliar"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Equip.Assistente Estagiario")) { return "Assistente Estagiário"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Equip.Monitor S/Lic") || lastCategory.getName().getContent().equalsIgnoreCase("Monitor-E.C.D.U. c/Licenciatura") || lastCategory.getName().getContent().equalsIgnoreCase("Monitor-E.C.D.U.s/Licenciatura")) { return "Monitor"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Equip.Prof.Auxiliar Convidado") || lastCategory.getName().getContent().equalsIgnoreCase("Prof Auxiliar Convidado")) { return "Professor Auxiliar convidado"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Professor Associado")) { return "Professor Associado"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Professor Associado Convidado")) { return "Professor Associado convidado"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Professor Catedrático")) { return "Professor Catedrático"; } else if (lastCategory.getName().getContent().equalsIgnoreCase("Professor Catedrático Convidado")) { return "Professor Catedrático convidado"; } logger.debug("Invalid category: " + lastCategory.getName().getContent()); } return lastCategory == null ? null : lastCategory.getName().getContent(); } public Float getProfessionalRegimeTime() { float maxRegimeTime = 100f; PersonProfessionalData personProfessionalData = getTeacher().getPerson().getPersonProfessionalData(); ProfessionalRegime lastProfessionalRegime = null; if (personProfessionalData != null) { GiafProfessionalData giafProfessionalData = personProfessionalData.getGiafProfessionalData(); if (giafProfessionalData != null) { lastProfessionalRegime = personProfessionalData.getLastProfessionalRegime(giafProfessionalData, executionSemesters.first() .getBeginDateYearMonthDay().toLocalDate(), executionSemesters.last().getEndDateYearMonthDay() .toLocalDate()); } } if (lastProfessionalRegime != null) { String regime = StringNormalizer.normalize(lastProfessionalRegime.getName().getContent()); if (regime.matches(".*?" + StringNormalizer.normalize("Tempo Integral") + ".*?")) { return maxRegimeTime; } else if (regime.matches(".*?" + StringNormalizer.normalize("Exclusividade") + ".*?")) { return maxRegimeTime; } else if (regime.matches(".*?" + StringNormalizer.normalize("Tempo Parcial") + ".*?")) { Integer weighting = lastProfessionalRegime.getWeighting(); if (weighting != null) { return Math.min(maxRegimeTime, weighting); } } } Float authorizationRegimeTime = getAuthorizationRegimeTime(executionSemesters.last()); if (authorizationRegimeTime == 0f) { authorizationRegimeTime = getAuthorizationRegimeTime(executionSemesters.first()); } return authorizationRegimeTime; } protected Float getAuthorizationRegimeTime(ExecutionSemester executionSemester) { return getTeacher().getTeacherAuthorization(executionSemester.getAcademicInterval()) .map(a -> new Float(Math.round(a.getLessonHours() * 100 / 12))).orElse(0f); } public List<String> getTop5ResultParticipation() { return addUntil5Elements(teacherPublications); } public List<String> getTop5ProfessionalDevelomentActivities() { return addUntil5Elements(new ArrayList<String>()); } public List<String> getTop5ProfessionalCareer() { List<String> result = new ArrayList<String>(); // List<ProfessionalCareer> sorted = new ArrayList<ProfessionalCareer>(); // for (Career career : teacher.getPerson().getAssociatedCareersSet()) { // if (career instanceof ProfessionalCareer) { // sorted.add((ProfessionalCareer) career); // } // } // Collections.sort(sorted, ProfessionalCareer.CAREER_DATE_COMPARATOR); // for (ProfessionalCareer professionalCareer : sorted.subList(0, Math.min(5, sorted.size()))) { // result.add(professionalCareer.getBeginYear() // + (professionalCareer.getEndYear() != null ? " - " + professionalCareer.getEndYear() : "") + " " // + professionalCareer.getFunction() + " (" + professionalCareer.getEntity() + ")"); // } return addUntil5Elements(result); } private List<String> addUntil5Elements(List<String> top5) { for (int i = top5.size(); i < 5; i++) { top5.add(StringUtils.EMPTY); } return top5; } private static String formatParticipant(String name) { String[] parts = name.split("\\s+"); return name.charAt(0) + ". " + parts[parts.length - 1]; } private String filter(String... text) { Set<String> parts = new HashSet<String>(); for (String string : text) { if (StringUtils.isNotBlank(string)) { parts.add(string.replace('\n', ' ').replace('\r', ' ').trim()); } } return StringUtils.join(parts, ", "); } private String join(String journal, String volume, Integer year) { StringBuilder builder = new StringBuilder(); if (StringUtils.isNotBlank(journal)) { builder.append(journal); } if (StringUtils.isNotBlank(volume)) { builder.append(" - " + volume); } if (year != null) { builder.append(" " + year); } return builder.toString(); } private void insert(List<String> publication, Integer part) { if (part != null) { publication.add(Integer.toString(part)); } } private void insert(List<String> publication, String part) { if (StringUtils.isNotBlank(part)) { publication.add(part); } } public void setlecturedUCs() { for (ExecutionSemester executionSemester : executionSemesters) { for (Professorship professorship : teacher.getProfessorships(executionSemester)) { getLecturedCurricularUnitForProfessorship(professorship, executionSemester); } for (ThesisEvaluationParticipant thesisEvaluationParticipant : teacher.getPerson() .getThesisEvaluationParticipantsSet()) { if (thesisEvaluationParticipant.getThesis().getEnrolment().getExecutionYear() .equals(executionSemester.getExecutionYear())) { final ThesisParticipationType type = thesisEvaluationParticipant.getType(); if (type == ThesisParticipationType.ORIENTATOR || type == ThesisParticipationType.COORIENTATOR) { ExecutionCourse executionCourse = thesisEvaluationParticipant.getThesis().getEnrolment().getExecutionCourseFor(executionSemester); if (executionCourse != null) { addLecturedCurricularUnit(executionCourse.getDegreePresentationString(), executionCourse.getName(), "OT", (float) 0); } } } } if (degree.getPhdProgram() != null) { for (InternalPhdParticipant participant : teacher.getPerson().getInternalParticipantsSet()) { PhdIndividualProgramProcess phdIndividualProgramProcess = participant.getIndividualProcess(); if (phdIndividualProgramProcess.getPhdProgram().equals(degree.getPhdProgram()) && phdIndividualProgramProcess.isActive(executionSemester.getAcademicInterval().toInterval()) && phdIndividualProgramProcess.isGuiderOrAssistentGuider(teacher.getPerson()) && PersonProfessionalData.isTeacherActiveOrHasAuthorizationForSemester(teacher, executionSemester)) { addLecturedCurricularUnit(phdIndividualProgramProcess.getPhdProgram().getAcronym(), "Dissertação", "OT", (float) 0); } } } } return; } public List<LecturedCurricularUnit> getLecturedUCs() { Collections.sort(lecturedUCs); return lecturedUCs; } public String getDegreeSiglas(ExecutionCourse executionCourse) { Set<String> degreeSiglas = new HashSet<String>(); for (CurricularCourse curricularCourse : executionCourse.getAssociatedCurricularCoursesSet()) { degreeSiglas.add(curricularCourse.getDegreeCurricularPlan().getDegree().getSigla()); } return StringUtils.join(degreeSiglas, ", "); } protected void getLecturedCurricularUnitForProfessorship(Professorship professorship, ExecutionSemester executionSemester) { Map<String, Float> hoursByTypeMap = new HashMap<String, Float>(); TeacherService teacherService = TeacherService.getTeacherServiceByExecutionPeriod(teacher, executionSemester); final StringBuilder shiftTypeDescription = new StringBuilder(); if (teacherService != null) { List<DegreeTeachingService> degreeTeachingServices = teacherService.getDegreeTeachingServiceByProfessorship(professorship); for (DegreeTeachingService degreeTeachingService : degreeTeachingServices) { for (CourseLoad courseLoad : degreeTeachingService.getShift().getCourseLoadsSet()) { final ShiftType type = courseLoad.getType(); appendShiftType(shiftTypeDescription, type); Float duration = hoursByTypeMap.get(StringUtils.EMPTY); Float weeklyHours = courseLoad.getTotalQuantity().floatValue() * (degreeTeachingService.getPercentage().floatValue() / 100); hoursByTypeMap.put(StringUtils.EMPTY, duration == null ? weeklyHours : duration + weeklyHours); } } for (OtherService otherService : teacherService.getOtherServices()) { if (otherService instanceof DegreeTeachingServiceCorrection) { DegreeTeachingServiceCorrection degreeTeachingServiceCorrection = (DegreeTeachingServiceCorrection) otherService; if (degreeTeachingServiceCorrection.getProfessorship().equals(professorship) && (!degreeTeachingServiceCorrection.getProfessorship().getExecutionCourse() .getProjectTutorialCourse())) { Float duration = hoursByTypeMap.get(StringUtils.EMPTY); Float weeklyHours = degreeTeachingServiceCorrection.getCorrection().floatValue(); hoursByTypeMap.put(StringUtils.EMPTY, duration == null ? weeklyHours : duration + weeklyHours); } } } } String name = professorship.getExecutionCourse().getName(); if (hoursByTypeMap.isEmpty()) { addLecturedCurricularUnit(professorship.getExecutionCourse().getDegreePresentationString(), name, "O", (float) 0); } else { for (String shiftType : hoursByTypeMap.keySet()) { addLecturedCurricularUnit(professorship.getExecutionCourse().getDegreePresentationString(), name, /*shiftType*/ shiftTypeDescription.toString(), hoursByTypeMap.get(StringUtils.EMPTY)); } } } private void appendShiftType(final StringBuilder builder, final ShiftType type) { if (type != null) { final String t = convertShiftType(type); if (t != null && !t.isEmpty()) { String string = builder.toString(); if (!string.equals(t) && !string.startsWith(t + ',') && !string.endsWith("," + t)) { if (!string.isEmpty()) { builder.append(','); } builder.append(t); } } } } private void addLecturedCurricularUnit(String degree, String name, String shiftType, Float hours) { for (LecturedCurricularUnit lecturedCurricularUnit : lecturedUCs) { if (lecturedCurricularUnit.getName().equals(name) && lecturedCurricularUnit.getOriginalShiftType().equals(shiftType)) { lecturedUCs.remove(lecturedCurricularUnit); lecturedCurricularUnit.addHours(hours); lecturedCurricularUnit.addDegree(degree); lecturedUCs.add(lecturedCurricularUnit); return; } } lecturedUCs.add(new LecturedCurricularUnit(degree, name, shiftType, hours)); } public class QualificationBean { protected QualificationType type; protected String degree; protected String scientificArea; protected Integer year; protected String institution; protected String classification; public QualificationBean(Qualification qualification) { type = qualification.getType(); degree = qualification.getType() != null ? qualification.getType().getLocalizedName().trim() : "Sem Grau"; if (qualification.getType().name().startsWith("DOCTORATE_DEGREE")) { degree = QualificationType.DOCTORATE_DEGREE.getLocalizedName(); } scientificArea = qualification.getDegree(); year = qualification.getYear() != null ? Integer.parseInt(qualification.getYear()) : null; institution = qualification.getSchool(); classification = qualification.getMark() != null ? qualification.getMark() : "-"; } public QualificationType getType() { return type; } public String getDegree() { return degree; } public String getScientificArea() { return scientificArea; } public Integer getYear() { return year; } public String getInstitution() { return institution; } public String getClassification() { return classification; } } private static String convertShiftType(final ShiftType shiftType) { if (shiftType == null) { return "0"; } if (shiftType == ShiftType.LABORATORIAL) { return "PL"; } if (shiftType == ShiftType.PROBLEMS) { return "TP"; } return shiftType.getSiglaTipoAula(); } public class LecturedCurricularUnit implements Comparable<LecturedCurricularUnit> { protected Set<String> degrees = new HashSet<String>(); protected String name; protected String shiftType; protected float hours; public LecturedCurricularUnit(String degree, String name, String shiftType, float hoursValue) { addDegree(degree); this.name = name; this.shiftType = shiftType; this.hours = hoursValue; } public void addDegree(String degrees) { for (String thisDegree : degrees.split(",")) { this.degrees.add(thisDegree.trim()); } } public void addHours(Float hours) { this.hours = this.hours + hours; } protected String getOriginalShiftType() { return shiftType; } public String getShiftType() { if (shiftType == null) { return null; } else if (shiftType.equals("T") || shiftType.equals("TP") || shiftType.equals("TC") || shiftType.equals("S") || shiftType.equals("E") || shiftType.equals("OT") || shiftType.equals("PL")) { return shiftType; } else if (shiftType.equals("L")) { return "PL"; } else if (shiftType.equals("PB")) { return "TP"; } else if (shiftType.equals(StringUtils.EMPTY)) { return StringUtils.EMPTY; } else if (shiftType.indexOf(',') > 0) { return shiftType; } return "O"; } public String getName() { return name; } public float getHours() { return ((float) Math.round(hours * 100)) / 100; } public String getDegree() { return StringUtils.join(degrees, ", "); } @Override public boolean equals(Object obj) { if (obj instanceof LecturedCurricularUnit) { LecturedCurricularUnit o = (LecturedCurricularUnit) obj; return equal(getDegree(), o.getDegree()) && equal(getName(), o.getName()) && equal(getShiftType(), o.getShiftType()) && equal(getHours(), o.getHours()); } return false; } protected boolean equal(Object obj1, Object obj2) { if (obj1 == null && obj2 == null) { return true; } if (obj1 == null || obj2 == null) { return false; } return obj1.equals(obj2); } @Override public int hashCode() { return getDegree().hashCode() + getName().hashCode() + (getShiftType() != null ? getShiftType().hashCode() : 0) + (int) getHours(); } @Override public int compareTo(LecturedCurricularUnit o) { String sigla = TeacherCurricularInformation.this.degree.getSigla(); if (getDegree().matches("(.*, )*" + sigla + "(, .*)*") && !o.getDegree().matches("(.*, )*" + sigla + "(, .*)*") && getHours() != 0) { return -1; } else if ((!getDegree().matches("(.*, )*" + sigla + "(, .*)*")) && o.getDegree().matches("(.*, )*" + sigla + "(, .*)*") && o.getHours() != 0) { return 1; } return ((Float) o.getHours()).compareTo(getHours()); } } }