/**
* 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.Collection;
import java.util.Comparator;
import java.util.Date;
import org.fenixedu.academic.domain.curriculum.EnrollmentState;
import org.fenixedu.academic.domain.curriculum.EnrolmentEvaluationContext;
import org.fenixedu.academic.domain.curriculum.GradeFactory;
import org.fenixedu.academic.domain.curriculum.IGrade;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.exceptions.EnrolmentNotPayedException;
import org.fenixedu.academic.domain.student.Registration;
import org.fenixedu.academic.domain.student.Student;
import org.fenixedu.academic.domain.thesis.Thesis;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.academic.util.EnrolmentEvaluationState;
import org.fenixedu.academic.util.FenixDigestUtils;
import org.fenixedu.academic.util.MarkType;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.joda.time.DateTime;
import org.joda.time.YearMonthDay;
public class EnrolmentEvaluation extends EnrolmentEvaluation_Base {
public static final Comparator<EnrolmentEvaluation> COMPARATORY_BY_WHEN = new Comparator<EnrolmentEvaluation>() {
@Override
public int compare(EnrolmentEvaluation o1, EnrolmentEvaluation o2) {
return o1.getWhenDateTime().compareTo(o2.getWhenDateTime());
}
};
public static final Comparator<EnrolmentEvaluation> SORT_BY_STUDENT_NUMBER = new Comparator<EnrolmentEvaluation>() {
@Override
public int compare(EnrolmentEvaluation o1, EnrolmentEvaluation o2) {
final Student s1 = o1.getRegistration().getStudent();
final Student s2 = o2.getRegistration().getStudent();
return s1.getNumber().compareTo(s2.getNumber());
}
};
static final public Comparator<EnrolmentEvaluation> COMPARATOR_BY_EXAM_DATE = new Comparator<EnrolmentEvaluation>() {
@Override
public int compare(EnrolmentEvaluation o1, EnrolmentEvaluation o2) {
if (o1.getExamDateYearMonthDay() == null && o2.getExamDateYearMonthDay() == null) {
return 0;
}
if (o1.getExamDateYearMonthDay() == null) {
return -1;
}
if (o2.getExamDateYearMonthDay() == null) {
return 1;
}
return o1.getExamDateYearMonthDay().compareTo(o2.getExamDateYearMonthDay());
}
};
public EnrolmentEvaluation() {
super();
setRootDomainObject(Bennu.getInstance());
setEnrolmentEvaluationState(EnrolmentEvaluationState.TEMPORARY_OBJ);
setGrade(Grade.createEmptyGrade());
setContext(EnrolmentEvaluationContext.MARK_SHEET_EVALUATION);
}
public EnrolmentEvaluation(Enrolment enrolment, EvaluationSeason season) {
this();
if (enrolment == null || season == null) {
throw new DomainException("error.enrolmentEvaluation.invalid.parameters");
}
setEnrolment(enrolment);
setEvaluationSeason(season);
}
private EnrolmentEvaluation(Enrolment enrolment, EnrolmentEvaluationState enrolmentEvaluationState, EvaluationSeason season,
Person responsibleFor, Grade grade, Date availableDate, Date examDate) {
this(enrolment, season);
if (enrolmentEvaluationState == null || responsibleFor == null) {
throw new DomainException("error.enrolmentEvaluation.invalid.parameters");
}
setEnrolmentEvaluationState(enrolmentEvaluationState);
setPersonResponsibleForGrade(responsibleFor);
setGrade(grade);
setGradeAvailableDate(availableDate);
setExamDate(examDate);
generateCheckSum();
}
protected EnrolmentEvaluation(Enrolment enrolment, EnrolmentEvaluationState enrolmentEvaluationState,
EvaluationSeason season, Person responsibleFor, Grade grade, Date availableDate, Date examDate, DateTime when) {
this(enrolment, enrolmentEvaluationState, season, responsibleFor, grade, availableDate, examDate);
setWhenDateTime(when);
}
protected EnrolmentEvaluation(Enrolment enrolment, EvaluationSeason season, EnrolmentEvaluationState evaluationState) {
this(enrolment, season);
if (evaluationState == null) {
throw new DomainException("error.enrolmentEvaluation.invalid.parameters");
}
setEnrolmentEvaluationState(evaluationState);
setWhenDateTime(new DateTime());
}
protected EnrolmentEvaluation(Enrolment enrolment, EvaluationSeason season, EnrolmentEvaluationState evaluationState,
Person person) {
this(enrolment, season, evaluationState);
if (person == null) {
throw new DomainException("error.enrolmentEvaluation.invalid.parameters");
}
setPerson(person);
}
protected EnrolmentEvaluation(Enrolment enrolment, EvaluationSeason season, EnrolmentEvaluationState evaluationState,
Person person, ExecutionSemester executionSemester) {
this(enrolment, season, evaluationState, person);
if (executionSemester == null) {
throw new DomainException("error.enrolmentEvaluation.invalid.parameters");
}
setExecutionPeriod(executionSemester);
}
private int compareMyExamDateToAnotherExamDate(Date examDate) {
if (this.getExamDate() == null) {
return -1;
}
if (examDate == null) {
return 1;
}
return this.getExamDate().compareTo(examDate);
}
public EnrollmentState getEnrollmentStateByGrade() {
return getGrade().getEnrolmentState();
}
@Override
public GradeScale getGradeScale() {
return getGradeScaleChain();
}
public GradeScale getGradeScaleChain() {
return super.getGradeScale() != null ? super.getGradeScale() : getEnrolment().getGradeScaleChain();
}
public GradeScale getAssociatedGradeScale() {
return super.getGradeScale();
}
public boolean isNotEvaluated() {
return getEnrollmentStateByGrade() == EnrollmentState.NOT_EVALUATED;
}
public boolean isFlunked() {
return getEnrollmentStateByGrade() == EnrollmentState.NOT_APROVED;
}
public boolean isApproved() {
return getEnrollmentStateByGrade() == EnrollmentState.APROVED;
}
public void edit(Person responsibleFor, Date evaluationDate) {
if (responsibleFor == null) {
throw new DomainException("error.enrolmentEvaluation.invalid.parameters");
}
setPersonResponsibleForGrade(responsibleFor);
setExamDate(evaluationDate);
generateCheckSum();
}
public void edit(Person responsibleFor, String gradeValue, Date availableDate, Date examDate, String bookReference,
String page, String examReference) {
edit(responsibleFor, gradeValue, availableDate, examDate);
setBookReference(bookReference);
setPage(page);
}
public void edit(Person responsibleFor, String gradeValue, Date availableDate, Date examDate) {
edit(responsibleFor, Grade.createGrade(gradeValue, getGradeScale()), availableDate, examDate);
}
public void edit(Person responsibleFor, Grade grade, Date availableDate, Date examDate) {
if (responsibleFor == null) {
throw new DomainException("error.enrolmentEvaluation.invalid.parameters");
}
if (examDate != null) {
if (!grade.isNotEvaluated()) {
checkRegistrationState();
}
setExamDateYearMonthDay(YearMonthDay.fromDateFields(examDate));
} else if (grade.isEmpty()) {
setExamDateYearMonthDay(null);
} else {
setExamDateYearMonthDay(YearMonthDay.fromDateFields(availableDate));
}
setGrade(grade);
setGradeAvailableDateYearMonthDay(YearMonthDay.fromDateFields(availableDate));
setPersonResponsibleForGrade(responsibleFor);
generateCheckSum();
}
private void checkRegistrationState() {
if (getRegistration().hasAnyActiveState(getExecutionYear()) || getRegistration().isTransited(getExecutionYear())
|| (getRegistration().isConcluded() && getEvaluationSeason().isImprovement())) {
return;
}
throw new DomainException("error.EnrolmentEvaluation.registration.with.invalid.state", getRegistration().getNumber()
.toString());
}
private ExecutionYear getExecutionYear() {
return getExecutionPeriod().getExecutionYear();
}
public void confirmSubmission(Person person, String observation) {
confirmSubmission(EnrolmentEvaluationState.FINAL_OBJ, person, observation);
}
public void confirmSubmission(EnrolmentEvaluationState enrolmentEvaluationState, Person person, String observation) {
if (!isTemporary()) {
throw new DomainException("EnrolmentEvaluation.cannot.submit.not.temporary");
}
if (!hasGrade()) {
throw new DomainException("EnrolmentEvaluation.cannot.submit.with.empty.grade");
}
/*
*
* Due to curriculum validation the exam date is not required
*
* if (!hasExamDateYearMonthDay()) { throw new
* DomainException("EnrolmentEvaluation.cannot.submit.without.exam.date"
* ); }
*/
if (isPayable() && !isPayed()) {
throw new EnrolmentNotPayedException("EnrolmentEvaluation.cannot.set.grade.on.not.payed.enrolment.evaluation",
getEnrolment());
}
if (enrolmentEvaluationState == EnrolmentEvaluationState.RECTIFICATION_OBJ && getRectified() != null) {
getRectified().setEnrolmentEvaluationState(EnrolmentEvaluationState.RECTIFIED_OBJ);
}
setEnrolmentEvaluationState(enrolmentEvaluationState);
setPerson(person);
setObservation(observation);
setWhenDateTime(new DateTime());
EnrollmentState newEnrolmentState = EnrollmentState.APROVED;
if (!this.getEvaluationSeason().isImprovement()) {
if (MarkType.getRepMarks().contains(getGradeValue())) {
newEnrolmentState = EnrollmentState.NOT_APROVED;
} else if (MarkType.getNaMarks().contains(getGradeValue())) {
newEnrolmentState = EnrollmentState.NOT_EVALUATED;
}
}
this.getEnrolment().setEnrollmentState(newEnrolmentState);
}
@Override
protected void checkForDeletionBlockers(Collection<String> blockers) {
super.checkForDeletionBlockers(blockers);
if (!isTemporary() || hasConfirmedMarkSheet()) {
blockers.add(BundleUtil.getString(Bundle.APPLICATION,
"error.enrolmentEvaluation.isTemporary.or.hasConfirmedMarksheet"));
}
if (getImprovementOfApprovedEnrolmentEvent() != null && getImprovementOfApprovedEnrolmentEvent().isPayed()) {
blockers.add(BundleUtil.getString(Bundle.APPLICATION, "error.enrolmentEvaluation.has.been.payed"));
}
}
public boolean hasConfirmedMarkSheet() {
return getMarkSheet() != null && getMarkSheet().isConfirmed();
}
public boolean isTemporary() {
return getEnrolmentEvaluationState() != null
&& getEnrolmentEvaluationState().equals(EnrolmentEvaluationState.TEMPORARY_OBJ);
}
public boolean isFinal() {
return getEnrolmentEvaluationState().equals(EnrolmentEvaluationState.FINAL_OBJ)
|| getEnrolmentEvaluationState().equals(EnrolmentEvaluationState.RECTIFICATION_OBJ);
}
public boolean isRectification() {
return this.getEnrolmentEvaluationState().equals(EnrolmentEvaluationState.RECTIFICATION_OBJ);
}
public boolean isRectified() {
return this.getEnrolmentEvaluationState().equals(EnrolmentEvaluationState.RECTIFIED_OBJ);
}
public void delete() {
DomainException.throwWhenDeleteBlocked(getDeletionBlockers());
setPersonResponsibleForGrade(null);
setPerson(null);
setEnrolment(null);
setMarkSheet(null);
setRectification(null);
setRectified(null);
if (getImprovementOfApprovedEnrolmentEvent() != null) {
getImprovementOfApprovedEnrolmentEvent().removeImprovementEnrolmentEvaluations(this);
}
setExecutionPeriod(null);
setEvaluationSeason(null);
setRootDomainObject(null);
super.deleteDomainObject();
}
public void removeFromMarkSheet() {
if (hasConfirmedMarkSheet()) {
throw new DomainException("error.enrolmentEvaluation.cannot.be.removed.from.markSheet");
}
setCheckSum(null);
setExamDateYearMonthDay(null);
setGradeAvailableDateYearMonthDay(null);
setMarkSheet(null);
}
protected void generateCheckSum() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(getExamDateYearMonthDay() != null ? getExamDateYearMonthDay().toString() : "").append(
getGradeValue());
stringBuilder.append(getEvaluationSeason().getExternalId());
stringBuilder.append(getEnrolment().getStudentCurricularPlan().getRegistration().getNumber());
setCheckSum(FenixDigestUtils.createDigest(stringBuilder.toString()));
}
public IGrade getGradeWrapper() {
return GradeFactory.getInstance().getGrade(getGradeValue());
}
@Override
public String getGradeValue() {
return getGrade().getValue();
}
@Override
@Deprecated
public void setGradeValue(final String grade) {
setGrade(grade);
}
public void setGrade(final String grade) {
setGrade(Grade.createGrade(grade, getGradeScale()));
}
@Override
public void setGrade(final Grade grade) {
if (isFinal()) {
throw new DomainException("EnrolmentEvaluation.cannot.set.grade.final");
}
super.setGrade(grade);
final Enrolment enrolment = getEnrolment();
if (enrolment != null && enrolment.getCurricularCourse().isDissertation()) {
final Thesis thesis = enrolment.getThesis();
if (thesis != null) {
if (grade.isEmpty()) {
thesis.removeMark();
} else {
thesis.setMark(Integer.valueOf(grade.getValue()));
}
}
}
// TODO remove this once we're sure migration to Grade went OK
super.setGradeValue(grade.getValue());
}
@Deprecated
public Registration getStudent() {
return this.getRegistration();
}
public Registration getRegistration() {
return getStudentCurricularPlan().getRegistration();
}
public DegreeCurricularPlan getDegreeCurricularPlan() {
return getStudentCurricularPlan().getDegreeCurricularPlan();
}
public StudentCurricularPlan getStudentCurricularPlan() {
return getEnrolment().getStudentCurricularPlan();
}
public MarkSheet getRectificationMarkSheet() {
if (this.getEnrolmentEvaluationState().equals(EnrolmentEvaluationState.RECTIFIED_OBJ) && getRectification() != null) {
return getRectification().getMarkSheet();
} else {
return null;
}
}
public boolean hasGrade() {
return !getGrade().isEmpty();
}
final public boolean hasExamDateYearMonthDay() {
return getExamDateYearMonthDay() != null;
}
public boolean isPayable() {
return getImprovementOfApprovedEnrolmentEvent() != null && !getImprovementOfApprovedEnrolmentEvent().isCancelled();
}
public boolean isPayed() {
return getImprovementOfApprovedEnrolmentEvent().isPayed();
}
@Override
public ExecutionSemester getExecutionPeriod() {
if (getEvaluationSeason().isImprovement()) {
return super.getExecutionPeriod();
}
if (getEnrolment() != null) {
return getEnrolment().getExecutionPeriod();
}
return null;
}
@Deprecated
public java.util.Date getExamDate() {
org.joda.time.YearMonthDay ymd = getExamDateYearMonthDay();
return (ymd == null) ? null : new java.util.Date(ymd.getYear() - 1900, ymd.getMonthOfYear() - 1, ymd.getDayOfMonth());
}
@Deprecated
public void setExamDate(java.util.Date date) {
if (date == null) {
setExamDateYearMonthDay(null);
} else {
setExamDateYearMonthDay(org.joda.time.YearMonthDay.fromDateFields(date));
}
}
@Deprecated
public java.util.Date getGradeAvailableDate() {
org.joda.time.YearMonthDay ymd = getGradeAvailableDateYearMonthDay();
return (ymd == null) ? null : new java.util.Date(ymd.getYear() - 1900, ymd.getMonthOfYear() - 1, ymd.getDayOfMonth());
}
@Deprecated
public void setGradeAvailableDate(java.util.Date date) {
if (date == null) {
setGradeAvailableDateYearMonthDay(null);
} else {
setGradeAvailableDateYearMonthDay(org.joda.time.YearMonthDay.fromDateFields(date));
}
}
@Deprecated
public java.util.Date getWhen() {
org.joda.time.DateTime dt = getWhenDateTime();
return (dt == null) ? null : new java.util.Date(dt.getMillis());
}
@Deprecated
public void setWhen(java.util.Date date) {
if (date == null) {
setWhenDateTime(null);
} else {
setWhenDateTime(new org.joda.time.DateTime(date.getTime()));
}
}
}