/**
* 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.thesis;
import static org.fenixedu.academic.predicate.AccessControl.check;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
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.DomainObjectUtil;
import org.fenixedu.academic.domain.Enrolment;
import org.fenixedu.academic.domain.EnrolmentEvaluation;
import org.fenixedu.academic.domain.ExecutionCourse;
import org.fenixedu.academic.domain.ExecutionDegree;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.ExecutionYear;
import org.fenixedu.academic.domain.Grade;
import org.fenixedu.academic.domain.GradeScale;
import org.fenixedu.academic.domain.MarkSheet;
import org.fenixedu.academic.domain.MarkSheetType;
import org.fenixedu.academic.domain.Person;
import org.fenixedu.academic.domain.Professorship;
import org.fenixedu.academic.domain.ScientificCommission;
import org.fenixedu.academic.domain.StudentCurricularPlan;
import org.fenixedu.academic.domain.Teacher;
import org.fenixedu.academic.domain.curriculum.EnrolmentEvaluationType;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.exceptions.FieldIsRequiredException;
import org.fenixedu.academic.domain.organizationalStructure.ScientificCouncilUnit;
import org.fenixedu.academic.domain.student.Student;
import org.fenixedu.academic.domain.util.email.Message;
import org.fenixedu.academic.domain.util.email.Recipient;
import org.fenixedu.academic.domain.util.email.Sender;
import org.fenixedu.academic.dto.degreeAdministrativeOffice.gradeSubmission.MarkSheetEnrolmentEvaluationBean;
import org.fenixedu.academic.predicate.AccessControl;
import org.fenixedu.academic.predicate.ThesisPredicates;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.academic.util.EvaluationType;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.groups.UserGroup;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.joda.time.DateTime;
import org.joda.time.YearMonthDay;
import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.dml.runtime.RelationAdapter;
import pt.utl.ist.fenix.tools.util.i18n.MultiLanguageString;
public class Thesis extends Thesis_Base {
static {
getRelationThesisEnrolment().addListener(new RelationAdapter<Thesis, Enrolment>() {
@Override
public void beforeAdd(Thesis thesis, Enrolment enrolment) {
super.beforeAdd(thesis, enrolment);
if (thesis == null || enrolment == null) {
return;
}
Collection<Thesis> theses = enrolment.getThesesSet();
String number = enrolment.getStudentCurricularPlan().getRegistration().getNumber().toString();
switch (theses.size()) {
case 0: // can have at least one
return;
case 1: // can have another if existing is not final
Thesis existing = theses.iterator().next();
if (existing.isFinalThesis() || !existing.isEvaluated()) {
throw new DomainException("thesis.enrolment.thesis.notEvaluated", number);
}
default: // never more than 2
throw new DomainException("thesis.enrolment.hasFinalThesis", number);
}
}
});
}
public static final Comparator<Thesis> COMPARATOR_BY_STUDENT = new Comparator<Thesis>() {
@Override
public int compare(Thesis t1, Thesis t2) {
final int n = Student.NUMBER_COMPARATOR.compare(t1.getStudent(), t2.getStudent());
return n == 0 ? DomainObjectUtil.COMPARATOR_BY_ID.compare(t1, t2) : n;
}
};
private final static double CREDITS = 1;
public static class ThesisCondition {
private final String key;
public ThesisCondition(String key) {
super();
this.key = key;
}
public String getKey() {
return this.key;
}
}
protected Thesis() {
super();
setRootDomainObject(Bennu.getInstance());
setDeclarationAccepted(false);
create();
}
public Thesis(Degree degree, Enrolment enrolment, MultiLanguageString title) {
this();
if (degree == null) {
throw new FieldIsRequiredException("enrolment", "thesis.degree.required");
}
if (enrolment == null) {
throw new FieldIsRequiredException("enrolment", "thesis.enrolment.required");
}
setDegree(degree);
setEnrolment(enrolment);
setTitle(title);
checkIsScientificCommissionMember();
}
private void checkIsScientificCommissionMember() {
final Enrolment enrolment = getEnrolment();
final ExecutionYear executionYear = enrolment.getExecutionYear();
final DegreeCurricularPlan degreeCurricularPlan = enrolment.getDegreeCurricularPlanOfStudent();
final Person person = AccessControl.getPerson();
if (person != null) {
for (final ScientificCommission scientificCommission : person.getScientificCommissionsSet()) {
final ExecutionDegree executionDegree = scientificCommission.getExecutionDegree();
if (executionDegree.getExecutionYear() == executionYear
&& executionDegree.getDegreeCurricularPlan() == degreeCurricularPlan) {
return;
}
}
}
throw new DomainException("degree.scientificCommission.notMember");
}
public boolean isDeclarationAccepted() {
Boolean accepted = getDeclarationAccepted();
return accepted == null ? false : accepted;
}
@Override
public void setTitle(MultiLanguageString title) {
if (title == null || title.isEmpty()) {
throw new FieldIsRequiredException("title", "thesis.title.required");
}
super.setTitle(title);
}
public MultiLanguageString getFinalTitle() {
ThesisFile dissertation = getDissertation();
if (dissertation == null) {
return getTitle();
} else {
final Locale dlanguage = dissertation.getLanguage();
final Locale language = dlanguage == null ? Locale.getDefault() : dlanguage;
return new MultiLanguageString(language, dissertation.getTitle());
}
}
public MultiLanguageString getFinalSubtitle() {
ThesisFile dissertation = getDissertation();
if (dissertation == null) {
return null;
} else {
String subTitle = dissertation.getSubTitle();
if (subTitle == null) {
return null;
}
return new MultiLanguageString(dissertation.getLanguage(), subTitle);
}
}
public void setFinalTitle(final MultiLanguageString finalTitle) {
setTitle(finalTitle);
final ThesisFile dissertation = getDissertation();
if (dissertation != null) {
final Locale language = dissertation.getLanguage();
if (language == null) {
dissertation.setLanguage(finalTitle.getContentLocale());
dissertation.setTitle(finalTitle.getContent());
} else {
final String content = finalTitle.getContent(language);
if (content == null) {
dissertation.setLanguage(finalTitle.getContentLocale());
dissertation.setTitle(finalTitle.getContent());
} else {
dissertation.setTitle(content);
}
}
}
}
public void setFinalSubtitle(final MultiLanguageString finalSubtitle) {
final ThesisFile dissertation = getDissertation();
if (dissertation != null) {
final Locale language = dissertation.getLanguage();
if (language == null) {
dissertation.setLanguage(finalSubtitle.getContentLocale());
dissertation.setSubTitle(finalSubtitle.getContent());
} else {
final String content = finalSubtitle.getContent(language);
if (content == null) {
dissertation.setLanguage(finalSubtitle.getContentLocale());
dissertation.setSubTitle(finalSubtitle.getContent());
} else {
dissertation.setSubTitle(content);
}
}
}
}
public Locale getLanguage() {
ThesisFile dissertation = getDissertation();
return dissertation == null ? null : dissertation.getLanguage();
}
final public MultiLanguageString getFinalFullTitle() {
final ThesisFile dissertation = getDissertation();
if (dissertation == null) {
return getTitle();
} else {
final StringBuilder result = new StringBuilder();
result.append(dissertation.getTitle());
result.append(StringUtils.isEmpty(dissertation.getSubTitle()) ? "" : ": " + dissertation.getSubTitle());
final Locale language = dissertation.getLanguage();
return language == null ? new MultiLanguageString(result.toString()) : new MultiLanguageString(language,
result.toString());
}
}
@Override
public void setDiscussed(DateTime discussed) {
check(this, ThesisPredicates.studentOrAcademicAdministrativeOfficeOrScientificCouncil);
if (discussed != null && getEnrolment().getCreationDateDateTime().isAfter(discussed)) {
throw new DomainException("thesis.invalid.discussed.date.time");
}
super.setDiscussed(discussed);
}
@Override
public void setThesisAbstract(MultiLanguageString thesisAbstract) {
check(this, ThesisPredicates.waitingConfirmation);
super.setThesisAbstract(thesisAbstract);
}
@Override
public void setKeywords(MultiLanguageString keywords) {
check(this, ThesisPredicates.waitingConfirmation);
super.setKeywords(keywords);
}
public List<ThesisEvaluationParticipant> getOrientation() {
ThesisEvaluationParticipant orientator = getOrientator();
ThesisEvaluationParticipant coorientator = getCoorientator();
List<ThesisEvaluationParticipant> result = new ArrayList<ThesisEvaluationParticipant>();
if (orientator != null) {
result.add(orientator);
}
if (coorientator != null) {
result.add(coorientator);
}
return result;
}
public ThesisEvaluationParticipant getOrientator() {
return getParticipant(ThesisParticipationType.ORIENTATOR);
}
public ThesisEvaluationParticipant getCoorientator() {
return getParticipant(ThesisParticipationType.COORIENTATOR);
}
public ThesisEvaluationParticipant getPresident() {
return getParticipant(ThesisParticipationType.PRESIDENT);
}
public ThesisEvaluationParticipant getCreator() {
return getParticipant(ThesisParticipationType.STATE_CREATOR);
}
public ThesisEvaluationParticipant getSubmitter() {
return getParticipant(ThesisParticipationType.STATE_SUBMITTER);
}
public ThesisEvaluationParticipant getProposalApprover() {
return getParticipant(ThesisParticipationType.STATE_PROPOSAL_APPROVER);
}
public ThesisEvaluationParticipant getConfirmer() {
return getParticipant(ThesisParticipationType.STATE_CONFIRMER);
}
public ThesisEvaluationParticipant getEvaluationApprover() {
return getParticipant(ThesisParticipationType.STATE_EVALUATION_APPROVER);
}
public List<ThesisEvaluationParticipant> getVowels() {
return getAllParticipants(ThesisParticipationType.VOWEL);
}
public ThesisEvaluationParticipant getParticipant(ThesisParticipationType type) {
for (ThesisEvaluationParticipant participant : getParticipationsSet()) {
if (participant.getType() == type) {
return participant;
}
}
return null;
}
public List<ThesisEvaluationParticipant> getAllParticipants(ThesisParticipationType type) {
List<ThesisEvaluationParticipant> result = new ArrayList<ThesisEvaluationParticipant>();
for (ThesisEvaluationParticipant participant : getParticipationsSet()) {
if (participant.getType() == type) {
result.add(participant);
}
}
return result;
}
public void delete() {
check(this, ThesisPredicates.isScientificCommission);
DomainException.throwWhenDeleteBlocked(getDeletionBlockers());
setRootDomainObject(null);
for (; !getParticipationsSet().isEmpty(); getParticipationsSet().iterator().next().delete()) {
;
}
// Unnecessary, the student could not submit files while in draft
// setDissertation(null);
// setExtendedAbstract(null);
setDegree(null);
removeEnrolment();
deleteDomainObject();
}
@Override
protected void checkForDeletionBlockers(Collection<String> blockers) {
super.checkForDeletionBlockers(blockers);
if (getState() != ThesisState.DRAFT) {
blockers.add(BundleUtil.getString(Bundle.APPLICATION, "thesis.delete.notDraft"));
}
if (getReaders() != null) {
blockers.add(BundleUtil.getString(Bundle.APPLICATION, "thesis.delete.notDraft"));
}
}
public boolean isDeletable() {
return getDeletionBlockers().isEmpty();
}
protected static Collection<Thesis> getThesisInState(Degree degree, ExecutionYear year, ThesisState state) {
List<Thesis> theses = new ArrayList<Thesis>();
for (Thesis thesis : Bennu.getInstance().getThesesSet()) {
if (thesis.getState() != state) {
continue;
}
if (degree != null && thesis.getDegree() != degree) {
continue;
}
if (year != null && thesis.getEnrolment().getExecutionYear() != year) {
continue;
}
theses.add(thesis);
}
return theses;
}
public static Collection<Thesis> getDraftThesis(Degree degree) {
return getThesisInState(degree, null, ThesisState.DRAFT);
}
public static Collection<Thesis> getSubmittedThesis() {
return getSubmittedThesis(null);
}
public static Collection<Thesis> getSubmittedThesis(Degree degree) {
return getSubmittedThesis(degree, null);
}
public static Collection<Thesis> getSubmittedThesis(Degree degree, ExecutionYear executionYear) {
return getThesisInState(degree, executionYear, ThesisState.SUBMITTED);
}
public static Collection<Thesis> getApprovedThesis() {
return getApprovedThesis(null);
}
public static Collection<Thesis> getApprovedThesis(Degree degree) {
return getApprovedThesis(degree, null);
}
public static Collection<Thesis> getApprovedThesis(Degree degree, ExecutionYear executionYear) {
List<Thesis> result = new ArrayList<Thesis>();
result.addAll(getThesisInState(degree, executionYear, ThesisState.APPROVED));
return result;
}
public static Collection<Thesis> getRevisionThesis() {
return getRevisionThesis(null);
}
public static Collection<Thesis> getRevisionThesis(Degree degree) {
return getRevisionThesis(degree, null);
}
public static Collection<Thesis> getRevisionThesis(Degree degree, ExecutionYear executionYear) {
List<Thesis> result = new ArrayList<Thesis>();
result.addAll(getThesisInState(degree, executionYear, ThesisState.REVISION));
return result;
}
public static Collection<Thesis> getConfirmedThesis() {
return getConfirmedThesis(null);
}
public static Collection<Thesis> getConfirmedThesis(Degree degree) {
return getConfirmedThesis(degree, null);
}
public static Collection<Thesis> getConfirmedThesis(Degree degree, ExecutionYear executionYear) {
return getThesisInState(degree, executionYear, ThesisState.CONFIRMED);
}
public static Collection<Thesis> getEvaluatedThesis() {
return getEvaluatedThesis(null);
}
public static Collection<Thesis> getEvaluatedThesis(Degree degree) {
return getEvaluatedThesis(degree, null);
}
public static Collection<Thesis> getEvaluatedThesis(Degree degree, ExecutionYear executionYear) {
return getThesisInState(degree, executionYear, ThesisState.EVALUATED);
}
// the credits calculation always depends on the current credits' value for
// the thesis (no history)
public static double getCredits() {
return CREDITS;
}
public boolean hasCredits() {
if (isEvaluated() && hasFinalEnrolmentEvaluation()) {
return true;
} else {
return false;
}
}
private ExecutionDegree getExecutionDegree(final Enrolment enrolment) {
final ExecutionYear executionYear = enrolment.getExecutionYear();
final DegreeCurricularPlan degreeCurricularPlan = enrolment.getDegreeCurricularPlanOfDegreeModule();
return degreeCurricularPlan.getExecutionDegreeByYear(executionYear);
}
@Override
public void setEnrolment(Enrolment enrolment) {
final ExecutionDegree executionDegree = getExecutionDegree(enrolment);
final YearMonthDay beginThesisCreationPeriod = executionDegree.getBeginThesisCreationPeriod();
final YearMonthDay endThesisCreationPeriod = executionDegree.getEndThesisCreationPeriod();
final YearMonthDay today = new YearMonthDay();
if (beginThesisCreationPeriod == null || beginThesisCreationPeriod.isAfter(today)) {
throw new DomainException("thesis.creation.not.allowed.because.out.of.period");
}
if (endThesisCreationPeriod != null && endThesisCreationPeriod.isBefore(today)) {
throw new DomainException("thesis.creation.not.allowed.because.out.of.period");
}
if (enrolment != null) {
CurricularCourse curricularCourse = enrolment.getCurricularCourse();
if (!curricularCourse.isDissertation()) {
throw new DomainException("thesis.enrolment.notDissertationEnrolment");
}
}
super.setEnrolment(enrolment);
}
public void removeEnrolment() {
super.setEnrolment(null);
}
public String getDepartmentName() {
final CompetenceCourse competenceCourse = getEnrolment().getCurricularCourse().getCompetenceCourse();
if (getEnrolment().isBolonhaDegree()) {
return competenceCourse.getDepartmentUnit().getDepartment().getRealName();
}
if (!competenceCourse.getDepartmentsSet().isEmpty()) {
return competenceCourse.getDepartmentsSet().iterator().next().getRealName();
}
return null;
}
public Student getStudent() {
return getEnrolment().getStudentCurricularPlan().getRegistration().getStudent();
}
// -> DRAFT
private void create() {
setCreation(new DateTime());
setCreator(AccessControl.getPerson());
setState(ThesisState.DRAFT);
}
// / DRAFT -> SUBMITTED
public void submit() {
check(this, ThesisPredicates.isScientificCommission);
if (getState() != ThesisState.DRAFT) {
throw new DomainException("thesis.submit.notDraft");
}
if (!isValid()) {
throw new DomainException("thesis.submit.hasConditions");
}
Person person = AccessControl.getPerson();
if (person.getTeacher() == null) {
throw new DomainException("thesis.submit.needsTeacher");
}
setSubmission(new DateTime());
setSubmitter(person);
setRejectionComment(null);
setState(ThesisState.SUBMITTED);
}
// / SUBMITTED -> DRAFT
public void cancelSubmit() {
check(this, ThesisPredicates.isScientificCommission);
switch (getState()) {
case SUBMITTED:
break;
case APPROVED:
throw new DomainException("thesis.submit.cancel.alreadyApproved");
case DRAFT:
if (isRejected()) {
throw new DomainException("thesis.submit.cancel.alreadyRejected");
}
default:
throw new DomainException("thesis.submit.cancel.unable");
}
setSubmission(null); // really undo step
setSubmitter(null);
setState(ThesisState.DRAFT);
}
public boolean isValid() {
return getConditions().isEmpty();
}
// SUBMITTED -> DRAFT
// public void reject() {
// if (getState() != ThesisState.SUBMITTED) {
// throw new DomainException("thesis.approve.notSubmitted");
// }
//
// setSubmitter(null);
// setState(ThesisState.DRAFT);
// }
// SUBMITTED -> APPROVED
public void approveProposal() {
check(this, ThesisPredicates.isScientificCouncilOrCoordinatorAndNotOrientatorOrCoorientator);
if (getState() != ThesisState.APPROVED) {
if (getState() != ThesisState.SUBMITTED) {
throw new DomainException("thesis.approve.notSubmitted");
}
setApproval(new DateTime());
setProposalApprover(AccessControl.getPerson());
setState(ThesisState.APPROVED);
}
}
// (SUBMITTED | APPROVED) -> DRAFT
public void rejectProposal(String rejectionComment) {
check(this, ThesisPredicates.isScientificCouncilOrCoordinatorAndNotOrientatorOrCoorientator);
if (getState() != ThesisState.SUBMITTED && getState() != ThesisState.APPROVED) {
throw new DomainException("thesis.reject.notSubmittedNorApproved");
}
setSubmitter(null);
setProposalApprover(null);
setRejectionComment(rejectionComment);
setState(ThesisState.DRAFT);
sendRejectionEmail(rejectionComment);
}
private void sendRejectionEmail(final String rejectionComment) {
final Collection<Person> persons = new HashSet<Person>();
final ExecutionYear executionYear = getEnrolment().getExecutionYear();
for (ScientificCommission member : getDegree().getScientificCommissionMembers(executionYear)) {
if (member.isContact()) {
persons.add(member.getPerson());
}
}
for (final ThesisEvaluationParticipant thesisEvaluationParticipant : getParticipationsSet()) {
final ThesisParticipationType thesisParticipationType = thesisEvaluationParticipant.getType();
if (thesisParticipationType == ThesisParticipationType.ORIENTATOR
|| thesisParticipationType == ThesisParticipationType.COORIENTATOR) {
persons.add(thesisEvaluationParticipant.getPerson());
}
}
final Recipient recipient =
new Recipient("Membros da tese " + getTitle().toString(), UserGroup.of(Person.convertToUsers(persons)));
final String studentNumber = getStudent().getNumber().toString();
final String title = getFinalFullTitle().getContent();
final String subject = getMessage("message.thesis.reject.submission.email.subject", studentNumber);
final String body = getMessage("message.thesis.reject.submission.email.body", studentNumber, title, rejectionComment);
//
final Sender sender = ScientificCouncilUnit.getScientificCouncilUnit().getUnitBasedSenderSet().iterator().next();
new Message(sender, sender.getConcreteReplyTos(), recipient.asCollection(), subject, body, "");
}
protected String getMessage(final String key, final Object... args) {
final String message = BundleUtil.getString(Bundle.SCIENTIFIC, key);
return MessageFormat.format(message, args);
}
// Not an actual state change... but it is an aparent state change (whatever
// that means).
@Override
public void setConfirmmedDocuments(final DateTime confirmmedDocuments) {
if (getState() != ThesisState.APPROVED && getState() != ThesisState.REVISION) {
throw new DomainException("thesis.confirm.notApprovedOrInRevision");
}
if (!isThesisAbstractInBothLanguages()) {
throw new DomainException("thesis.confirm.noAbstract");
}
if (!isKeywordsInBothLanguages()) {
throw new DomainException("thesis.confirm.noKeywords");
}
if (getExtendedAbstract() == null) {
throw new DomainException("thesis.confirm.noExtendedAbstract");
}
if (getDissertation() == null) {
throw new DomainException("thesis.confirm.noDissertation");
}
if (getDiscussed() == null) {
throw new DomainException("thesis.confirm.noDiscussionDate");
}
setConfirmer(AccessControl.getPerson());
super.setConfirmmedDocuments(confirmmedDocuments);
}
// APPROVED -> CONFIRMED
public void confirm(Integer mark) {
if (getState() != ThesisState.APPROVED && getState() != ThesisState.REVISION) {
throw new DomainException("thesis.confirm.notApprovedOrInRevision");
}
if (!isThesisAbstractInBothLanguages()) {
throw new DomainException("thesis.confirm.noAbstract");
}
if (!isKeywordsInBothLanguages()) {
throw new DomainException("thesis.confirm.noKeywords");
}
if (getExtendedAbstract() == null) {
throw new DomainException("thesis.confirm.noExtendedAbstract");
}
if (getDissertation() == null) {
throw new DomainException("thesis.confirm.noDissertation");
}
if (getDiscussed() == null) {
throw new DomainException("thesis.confirm.noDiscussionDate");
}
setMark(mark);
setConfirmation(new DateTime());
setConfirmer(AccessControl.getPerson());
setState(ThesisState.CONFIRMED);
}
// CONFIRMED -> REVISION
public void allowRevision() {
if (getState() != ThesisState.REVISION) {
if (getState() != ThesisState.CONFIRMED) {
throw new DomainException("thesis.confirm.notConfirmed");
}
setConfirmer(null);
setState(ThesisState.REVISION);
}
}
// CONFIRMED -> EVALUATED
public void approveEvaluation() {
if (getState() != ThesisState.EVALUATED) {
if (getState() != ThesisState.CONFIRMED) {
throw new DomainException("thesis.confirm.notConfirmed");
}
setEvaluation(new DateTime());
setEvaluationApprover(AccessControl.getPerson());
setState(ThesisState.EVALUATED);
updateMarkSheet();
setDocumentsAvailableAfter(new DateTime().plusMonths(9));
} else {
throw new DomainException("thesis.already.evaluated");
}
}
public ThesisLibraryState getLibraryState() {
if (getLastLibraryOperation() != null) {
return getLastLibraryOperation().getState();
}
return ThesisLibraryState.NOT_DEALT;
}
/**
* Do not use this. Create instances of {@link ThesisLibraryOperation} instead.
*/
public void setLibraryState(ThesisLibraryState state) {
throw new UnsupportedOperationException();
}
public String getLibraryReference() {
if (getLastLibraryOperation() != null) {
return getLastLibraryOperation().getLibraryReference();
}
return null;
}
/**
* Do not use this. Create instances of {@link ThesisLibraryOperation} instead.
*/
public void setLibraryReference(String reference) {
throw new UnsupportedOperationException();
}
public Person getLibraryOperationPerformer() {
if (getLastLibraryOperation() != null) {
return getLastLibraryOperation().getPerformer();
}
return null;
}
/**
* Do not use this. Create instances of {@link ThesisLibraryOperation} instead.
*/
public void setLibraryOperationPerformer(Person performer) {
throw new UnsupportedOperationException();
}
public boolean hasFinalEnrolmentEvaluation() {
return getEnrolment().isApproved();
}
/**
* Generates a new mark sheet in the administrative office or merges the
* grade for this enrolment in an existing, unconfirmed, mark sheet for this
* enrolment.
*
* <p>
* This is only done if there isn't already a MarkSheet with an evaluation for the Enrolment related to this Thesis and if
* this Thesis has a positive grade or is the second Thesis of the enrolment.
*/
public void updateMarkSheet() {
if (hasAnyEvaluations()) {
return;
}
if (!isFinalThesis()) {
return;
}
MarkSheet markSheet = getExistingMarkSheet();
if (markSheet == null) {
markSheet = createMarkSheet();
} else {
mergeInMarkSheet(markSheet);
}
}
/**
* Indicates if this thesis is the last one that can be created for this
* enrolment, that is, if the student can have any other thesis after this
* one for the same enrolment. A student can present up to two theses in a
* single enrolment. This corresponds to 2 distinct evaluation chances:
* first semester, second semester.
*
* @return <code>true</code> if the student can have a second thesis
*/
public boolean isFinalThesis() {
final Enrolment enrolment = getEnrolment();
return enrolment.getThesesSet().size() != 1 || !getEvaluationMark().getValue().equals(GradeScale.RE);
}
/**
* Same as the above but also ensures that the student had a positive grade.
*
* @return <code>true</code> if the student had a positive grade
*/
public boolean isFinalAndApprovedThesis() {
return !getEvaluationMark().getValue().equals(GradeScale.RE);
}
/**
* Verifies if the student has any EnrolmentEvaluation crated by a
* MarkSheet.
*
* @return <code>true</code> if the Enrolment related to this Thesis has at
* least one EnrolmentEvaluation connected to a MarkSheet
*/
public boolean hasAnyEvaluations() {
for (EnrolmentEvaluation evaluation : getEnrolment().getEvaluationsSet()) {
if (!evaluation.getEnrolmentEvaluationType().equals(EnrolmentEvaluationType.NORMAL)) {
continue;
}
if (evaluation.getMarkSheet() == null) {
continue;
}
final String gradeValue = evaluation.getGradeValue();
final Grade evaluationMark = getEvaluationMark();
final String evaluationMarkValue = evaluationMark == null ? null : evaluationMark.getValue();
if (gradeValue.equals(evaluationMarkValue)) {
return true;
} else {
throw new DomainException("thesis.approve.evaluation.has.different.mark", gradeValue);
}
}
return false;
}
protected MarkSheet getExistingMarkSheet() {
CurricularCourse curricularCourse = getEnrolment().getCurricularCourse();
Teacher teacher = getResponsibleTeacher();
for (MarkSheet markSheet : curricularCourse.getMarkSheetsSet()) {
if (getEnrolment().getExecutionPeriod() != markSheet.getExecutionPeriod()) {
continue;
}
if (markSheet.isConfirmed()) {
continue;
}
if (markSheet.getMarkSheetType() != MarkSheetType.SPECIAL_AUTHORIZATION) {
continue;
}
if (markSheet.getResponsibleTeacher() != teacher) {
continue;
}
return markSheet;
}
return null;
}
private Teacher getResponsibleTeacher() {
Teacher responsible = getExecutionCourseTeacher();
if (responsible == null) {
responsible = AccessControl.getPerson().getTeacher();
}
return responsible;
}
private void mergeInMarkSheet(MarkSheet markSheet) {
List<MarkSheetEnrolmentEvaluationBean> empty = Collections.emptyList();
markSheet.editNormal(empty, getStudentEvalutionBean(), empty);
}
protected MarkSheet createMarkSheet() {
CurricularCourse curricularCourse = getEnrolment().getCurricularCourse();
ExecutionSemester executionSemester = getEnrolment().getExecutionPeriod();
Teacher responsible = getExecutionCourseTeacher();
Date evaluationDate = getDiscussed().toDate();
MarkSheetType type = MarkSheetType.SPECIAL_AUTHORIZATION;
if (responsible == null) {
responsible = AccessControl.getPerson().getTeacher();
}
List<MarkSheetEnrolmentEvaluationBean> evaluations = getStudentEvalutionBean();
return curricularCourse.createNormalMarkSheet(executionSemester, responsible, evaluationDate, type, true, evaluations,
responsible.getPerson());
}
private List<MarkSheetEnrolmentEvaluationBean> getStudentEvalutionBean() {
return Arrays.asList(new MarkSheetEnrolmentEvaluationBean(getEnrolment(), getDiscussed().toDate(), getEvaluationMark()));
}
private Teacher getExecutionCourseTeacher() {
final List<Teacher> teachers = new ArrayList<Teacher>();
final ExecutionCourse executionCourse = getExecutionCourse();
if (executionCourse != null) {
for (Professorship professorship : executionCourse.getProfessorshipsSet()) {
if (professorship.isResponsibleFor() && professorship.hasTeacher()) {
return professorship.getTeacher();
}
}
}
CurricularCourse curricularCourse = getEnrolment().getCurricularCourse();
Degree degree = curricularCourse.getDegree();
for (final ExecutionDegree executionDegree : curricularCourse.getDegreeCurricularPlan().getExecutionDegreesSet()) {
if (executionDegree.getExecutionYear() == getEnrolment().getExecutionYear()) {
for (Coordinator coordinator : executionDegree.getCoordinatorsListSet()) {
if (coordinator.isResponsible()) {
return coordinator.getPerson().getTeacher();
}
}
}
}
return null;
}
private ExecutionCourse getExecutionCourse() {
Enrolment enrolment = getEnrolment();
CurricularCourse curricularCourse = enrolment.getCurricularCourse();
List<ExecutionCourse> executionCourses =
curricularCourse.getExecutionCoursesByExecutionPeriod(enrolment.getExecutionPeriod());
if (!executionCourses.isEmpty()) {
return executionCourses.iterator().next();
}
executionCourses = curricularCourse.getExecutionCoursesByExecutionYear(enrolment.getExecutionYear());
if (!executionCourses.isEmpty()) {
return executionCourses.iterator().next();
}
return null;
}
private Grade getEvaluationMark() {
Integer mark = getMark();
GradeScale scale = getEnrolment().getCurricularCourse().getGradeScaleChain();
if (scale != GradeScale.TYPE20) {
throw new DomainException("thesis.grade.type20.expected");
}
return Grade.createGrade((mark == null || mark < 10) ? GradeScale.RE : mark.toString(), scale);
}
public void acceptDeclaration(ThesisVisibilityType visibility, DateTime availableAfter) {
if (visibility == null) {
throw new DomainException("thesis.acceptDeclaration.visibility.required");
}
if (!isWaitingConfirmation()) {
throw new DomainException("thesis.acceptDeclaration.notAllowed");
}
setDeclarationAccepted(true);
setVisibility(visibility);
setDocumentsAvailableAfter(availableAfter);
setDeclarationAcceptedTime(new DateTime());
}
public void rejectDeclaration() {
setDeclarationAccepted(false);
setVisibility(null);
setDocumentsAvailableAfter(null);
setDeclarationAcceptedTime(null);
if (!isWaitingConfirmation()) {
throw new DomainException("thesis.rejectDeclaration.notAllowed");
}
if (getDissertation() != null) {
getDissertation().delete();
}
if (getExtendedAbstract() != null) {
getExtendedAbstract().delete();
}
}
@Atomic
public void swapFilesVisibility() {
ThesisVisibilityType visibility = getVisibility();
if (visibility == null) {
throw new DomainException("thesis.acceptDeclaration.visibility.required");
}
if (visibility.equals(ThesisVisibilityType.INTRANET)) {
setVisibility(ThesisVisibilityType.PUBLIC);
} else {
setVisibility(ThesisVisibilityType.INTRANET);
}
}
public boolean isDraft() {
return getState() == ThesisState.DRAFT;
}
public boolean isSubmitted() {
return getState() == ThesisState.SUBMITTED;
}
public boolean isApproved() {
ThesisState state = getState();
return state == ThesisState.APPROVED;
}
public boolean isWaitingConfirmation() {
ThesisState state = getState();
return state == ThesisState.APPROVED || state == ThesisState.REVISION;
}
public boolean isSubmittedAndIsCoordinatorAndNotOrientator() {
return isSubmitted() && isCoordinatorAndNotOrientator();
}
public boolean isCoordinatorAndNotOrientator() {
final Person loggedPerson = AccessControl.getPerson();
return loggedPerson != null && isCoordinator(loggedPerson) && !isOrientatorOrCoorientator(loggedPerson);
}
public boolean isCoordinator() {
final Person loggedPerson = AccessControl.getPerson();
return loggedPerson != null && isCoordinator(loggedPerson);
}
private boolean isCoordinator(final Person loggedPerson) {
for (final Coordinator coordinator : loggedPerson.getCoordinatorsSet()) {
if (coordinator.isResponsible() && getDegree() == coordinator.getExecutionDegree().getDegree()) {
return true;
}
}
return false;
}
private boolean isOrientatorOrCoorientator(final Person person) {
for (final ThesisEvaluationParticipant thesisEvaluationParticipant : getParticipationsSet()) {
final ThesisParticipationType type = thesisEvaluationParticipant.getType();
if ((type == ThesisParticipationType.ORIENTATOR || type == ThesisParticipationType.COORIENTATOR)
&& thesisEvaluationParticipant.getPerson() == person) {
return true;
}
}
return false;
}
public boolean isConfirmed() {
return getState() == ThesisState.CONFIRMED;
}
public boolean isEvaluated() {
return getState() == ThesisState.EVALUATED;
}
public boolean isInRevision() {
return getState() == ThesisState.REVISION;
}
public boolean isRejected() {
return isDraft() && getSubmission() != null;
}
public void removeMark() {
super.setMark(null);
}
@Override
public void setMark(Integer mark) {
if (!isMarkValid(mark)) {
throw new DomainException("thesis.mark.invalid");
}
super.setMark(mark);
}
public boolean isMarkValid(Integer mark) {
GradeScale scale = getEnrolment().getCurricularCourse().getGradeScaleChain();
if (scale == null) {
scale = GradeScale.TYPE20;
}
return scale.isValid(mark.toString(), EvaluationType.EXAM_TYPE); // TODO:
// thesis
// ,
// check
// grade
// type
}
private Person getParticipationPerson(ThesisEvaluationParticipant participant) {
if (participant == null) {
return null;
} else {
return participant.getPerson();
}
}
private void removeParticipation(ThesisEvaluationParticipant participant) {
if (participant != null) {
participant.delete();
}
}
public List<ThesisCondition> getStudentConditions() {
List<ThesisCondition> conditions = new ArrayList<ThesisCondition>();
if (getDiscussed() == null) {
conditions.add(new ThesisCondition("thesis.student.discussionDate.missing"));
}
if (!isThesisAbstractInBothLanguages()) {
conditions.add(new ThesisCondition("thesis.student.abstract.missing"));
}
if (!isKeywordsInBothLanguages()) {
conditions.add(new ThesisCondition("thesis.student.keywords.missing"));
}
if (isDeclarationAccepted()) {
if (getDissertation() == null) {
conditions.add(new ThesisCondition("thesis.student.dissertation.missing"));
}
if (getExtendedAbstract() == null) {
conditions.add(new ThesisCondition("thesis.student.extendedAbstract.missing"));
}
} else {
conditions.add(new ThesisCondition("thesis.student.declaration.notAccepted"));
}
return conditions;
}
public List<ThesisCondition> getConditions() {
List<ThesisCondition> conditions = new ArrayList<ThesisCondition>();
conditions.addAll(getGeneralConditions());
conditions.addAll(getOrientationConditions());
conditions.addAll(getJuryConditions());
return conditions;
}
public Collection<ThesisCondition> getGeneralConditions() {
List<ThesisCondition> conditions = new ArrayList<ThesisCondition>();
// check too few persons
int count = getJuryPersonCount();
if (count < 3) {
conditions.add(new ThesisCondition("thesis.condition.people.number.few"));
}
// check too many persons
if (count > 5) {
conditions.add(new ThesisCondition("thesis.condition.people.number.exceeded"));
}
return conditions;
}
public List<ThesisCondition> getOrientationConditions() {
List<ThesisCondition> conditions = new ArrayList<ThesisCondition>();
Person orientator = getParticipationPerson(getOrientator());
Person coorientator = getParticipationPerson(getCoorientator());
Integer orientatorCreditsDistribution = getOrientatorCreditsDistribution();
if (orientator == null) {
conditions.add(new ThesisCondition("thesis.condition.orientator.required"));
} else {
if (orientatorCreditsDistribution != null) {
if ((orientatorCreditsDistribution < 20) || (coorientator != null && getCoorientatorCreditsDistribution() < 20)) {
conditions.add(new ThesisCondition("thesis.condition.orientation.credits.low"));
}
} else if (isCreditsDistributionNeeded()) {
conditions.add(new ThesisCondition("thesis.condition.orientation.credits.notDefined"));
}
// check for duplicated persons
if (orientator == coorientator) {
conditions.add(new ThesisCondition("thesis.condition.people.repeated.orientation"));
}
}
return conditions;
}
public List<ThesisCondition> getJuryConditions() {
List<ThesisCondition> conditions = new ArrayList<ThesisCondition>();
Person president = getParticipationPerson(getPresident());
if (president == null) {
conditions.add(new ThesisCondition("thesis.condition.president.required"));
} else {
if (president.getTeacher() == null || !president.getTeacher().isActiveContractedTeacher()) {
conditions.add(new ThesisCondition("thesis.condition.president.notInternal"));
} else {
boolean isMember = false;
final Enrolment enrolment = getEnrolment();
final DegreeCurricularPlan degreeCurricularPlan = enrolment.getDegreeCurricularPlanOfDegreeModule();
final ExecutionYear executionYear = enrolment.getExecutionYear();
final ExecutionDegree executionDegree = degreeCurricularPlan.getExecutionDegreeByYear(executionYear);
if (executionDegree != null) {
for (ScientificCommission member : executionDegree.getScientificCommissionMembersSet()) {
isMember = isMember || president == member.getPerson();
if (isMember) {
break;
}
}
}
if (!isMember) {
conditions.add(new ThesisCondition("thesis.condition.president.scientificCommission.notMember"));
}
}
}
if (getVowels().size() < 2) {
conditions.add(new ThesisCondition("thesis.condition.people.vowels.two.required"));
} else {
// check duplicated person within jury
Set<Person> juryPersons = new HashSet<Person>();
//only vowels to separate the president's case
for (ThesisEvaluationParticipant vowel : getVowels()) {
juryPersons.add(vowel.getPerson());
}
if (getVowels().size() != juryPersons.size()) {
conditions.add(new ThesisCondition("thesis.condition.people.repeated.vowels"));
}
if (president != null && juryPersons.contains(president)) {
conditions.add(new ThesisCondition("thesis.condition.people.repeated.vowels.president"));
}
// check that one and only one member of the orientation is in the jury
Person orientator = getParticipationPerson(getOrientator());
Person coorientator = getParticipationPerson(getCoorientator());
juryPersons.add(president); // necessary since there is no express prohibition to the president being an orientation member
if (orientator != null) {
if (!(juryPersons.contains(orientator) ^ (coorientator != null && juryPersons.contains(coorientator)))) {
conditions.add(new ThesisCondition("thesis.condition.people.jury.orientation.members"));
}
}
}
return conditions;
}
private int getJuryPersonCount() {
Set<Person> persons = new HashSet<Person>();
ThesisEvaluationParticipant president = getPresident();
if (president != null) {
persons.add(president.getPerson());
}
for (ThesisEvaluationParticipant vowel : getVowels()) {
persons.add(vowel.getPerson());
}
return persons.size();
}
public boolean isThesisAbstractInBothLanguages() {
return getThesisAbstractPt() != null && getThesisAbstractEn() != null;
}
public boolean isKeywordsInBothLanguages() {
return getKeywordsPt() != null && getKeywordsEn() != null;
}
public String getThesisAbstractPt() {
return getThesisAbstractLanguage("pt");
}
public void setThesisAbstractPt(String text) {
check(this, ThesisPredicates.waitingConfirmation);
setThesisAbstractLanguage("pt", text);
}
public String getThesisAbstractEn() {
return getThesisAbstractLanguage("en");
}
public void setThesisAbstractEn(String text) {
check(this, ThesisPredicates.waitingConfirmation);
setThesisAbstractLanguage("en", text);
}
public String getThesisAbstractLanguage(String language) {
MultiLanguageString thesisAbstract = getThesisAbstract();
if (thesisAbstract == null) {
return null;
} else {
Locale realLanguage = new Locale.Builder().setLanguageTag(language).build();
String value = thesisAbstract.getContent(realLanguage);
if (value == null || value.length() == 0) {
return null;
} else {
return value;
}
}
}
public void setThesisAbstractLanguage(String language, String text) {
MultiLanguageString thesisAbstract = getThesisAbstract();
Locale realLanguage = new Locale.Builder().setLanguageTag(language).build();
if (thesisAbstract == null) {
setThesisAbstract(new MultiLanguageString(realLanguage, text));
} else {
thesisAbstract = thesisAbstract.with(realLanguage, text);
setThesisAbstract(thesisAbstract);
}
}
public String getKeywordsPt() {
return getKeywordsLanguage("pt");
}
public void setKeywordsPt(String text) {
check(this, ThesisPredicates.waitingConfirmation);
setKeywordsLanguage("pt", normalizeKeywords(text));
}
public String getKeywordsEn() {
return getKeywordsLanguage("en");
}
public void setKeywordsEn(String text) {
check(this, ThesisPredicates.waitingConfirmation);
setKeywordsLanguage("en", normalizeKeywords(text));
}
private String normalizeKeywords(String keywords) {
StringBuilder builder = new StringBuilder();
if (keywords == null) {
return null;
} else {
for (String part : keywords.split(",")) {
String trimmed = part.trim();
if (trimmed.length() != 0) {
if (builder.length() != 0) {
builder.append(", ");
}
builder.append(trimmed);
}
}
}
return builder.toString();
}
public String getKeywordsLanguage(String language) {
MultiLanguageString thesisAbstract = getKeywords();
if (thesisAbstract == null) {
return null;
} else {
Locale realLanguage = new Locale.Builder().setLanguageTag(language).build();
String value = thesisAbstract.getContent(realLanguage);
if (value == null || value.length() == 0) {
return null;
} else {
return value;
}
}
}
public void setKeywordsLanguage(String language, String text) {
if (text != null) {
final String[] parts = text.split(",");
if (parts.length > 6) {
throw new DomainException("label.message.thesis.keyword.number.of.words.exceeded");
} else {
for (final String part : parts) {
if (part.length() > 42) {
throw new DomainException("label.message.thesis.keyword.length.limit.exceeded");
}
}
}
}
MultiLanguageString keywords = getKeywords();
Locale realLanguage = new Locale.Builder().setLanguageTag(language).build();
if (keywords == null) {
setKeywords(new MultiLanguageString(realLanguage, text));
} else {
keywords = keywords.with(realLanguage, text);
setKeywords(keywords);
}
}
public void setOrientator(Person person) {
check(this, ThesisPredicates.isScientificCommissionOrScientificCouncil);
setParticipation(person, ThesisParticipationType.ORIENTATOR);
if (!isCreditsDistributionNeeded()) {
setCoorientatorCreditsDistribution(null);
}
}
public void setCoorientator(Person person) {
check(this, ThesisPredicates.isScientificCommissionOrScientificCouncil);
setParticipation(person, ThesisParticipationType.COORIENTATOR);
if (!isCreditsDistributionNeeded()) {
setCoorientatorCreditsDistribution(null);
}
}
public void setPresident(Person person) {
check(this, ThesisPredicates.isScientificCommissionOrScientificCouncil);
setParticipation(person, ThesisParticipationType.PRESIDENT);
}
public void setCreator(Person person) {
setParticipation(person, ThesisParticipationType.STATE_CREATOR);
}
public void setSubmitter(Person person) {
setParticipation(person, ThesisParticipationType.STATE_SUBMITTER);
}
public void setProposalApprover(Person person) {
setParticipation(person, ThesisParticipationType.STATE_PROPOSAL_APPROVER);
}
public void setConfirmer(Person person) {
setParticipation(person, ThesisParticipationType.STATE_CONFIRMER);
}
public void setEvaluationApprover(Person person) {
setParticipation(person, ThesisParticipationType.STATE_EVALUATION_APPROVER);
}
private void setParticipation(Person person, ThesisParticipationType type) {
if (person == null) {
removeParticipation(getParticipant(type));
} else {
new ThesisEvaluationParticipant(this, person, type);
}
}
public void addVowel(Person person) {
check(this, ThesisPredicates.isScientificCommissionOrScientificCouncil);
if (person != null) {
new ThesisEvaluationParticipant(this, person, ThesisParticipationType.VOWEL);
}
}
public boolean isCreditsDistributionNeeded() {
return isOrientatorCreditsDistributionNeeded() || isCoorientatorCreditsDistributionNeeded();
}
public boolean isOrientatorCreditsDistributionNeeded() {
return isInternalPerson(getParticipationPerson(getOrientator()));
}
public boolean isCoorientatorCreditsDistributionNeeded() {
return isInternalPerson(getParticipationPerson(getCoorientator()));
}
private boolean isInternalPerson(Person person) {
return person != null && person.getTeacher() != null && person.getTeacher().isActiveContractedTeacher();
}
@Override
public void setOrientatorCreditsDistribution(Integer percent) {
if (percent != null && (percent < 0 || percent > 100)) {
throw new DomainException("thesis.orietation.credits.notValid");
}
super.setOrientatorCreditsDistribution(percent);
}
public Integer getCoorientatorCreditsDistribution() {
Integer distribution = getOrientatorCreditsDistribution();
return distribution != null ? 100 - distribution : null;
}
public void setCoorientatorCreditsDistribution(Integer percent) {
if (percent != null && (percent < 0 || percent > 100)) {
throw new DomainException("thesis.orietation.credits.notValid");
}
setOrientatorCreditsDistribution(percent != null ? 100 - percent : null);
}
public DateTime getCurrentDiscussedDate() {
if (isConfirmed() || isEvaluated() || isInRevision()) {
return getDiscussed();
}
return getProposedDiscussed();
}
@Override
public void setState(final ThesisState state) {
if (hasFutureEnrolment()) {
throw new DomainException("thesis.has.enrolment.in.future");
}
if (state == ThesisState.REVISION) {
super.setConfirmmedDocuments(null);
}
super.setState(state);
}
protected boolean hasFutureEnrolment() {
final Enrolment enrolment = getEnrolment();
if (enrolment != null) {
final ExecutionSemester executionSemester = enrolment.getExecutionPeriod();
final CurricularCourse curricularCourse = enrolment.getCurricularCourse();
final StudentCurricularPlan studentCurricularPlan = enrolment.getStudentCurricularPlan();
for (final Enrolment otherEnrolment : studentCurricularPlan.getEnrolments(curricularCourse)) {
if (otherEnrolment.getExecutionPeriod().isAfter(executionSemester)) {
return true;
}
}
}
return false;
}
public static Set<Thesis> getThesesByParticipationType(final Person person,
final ThesisParticipationType thesisParticipationType) {
final Set<Thesis> theses = new HashSet<Thesis>();
for (final ThesisEvaluationParticipant thesisEvaluationParticipant : person.getThesisEvaluationParticipantsSet()) {
if (thesisParticipationType == thesisEvaluationParticipant.getType()) {
final Thesis thesis = thesisEvaluationParticipant.getThesis();
theses.add(thesis);
}
}
return theses;
}
public boolean hasCurrentDiscussedDate() {
return getCurrentDiscussedDate() != null;
}
public void checkIsScientificCommission() {
check(this, ThesisPredicates.isScientificCommission);
// Nothing to do here... just the access control stuff that is injected
// whenever necessary
}
public ExecutionYear getExecutionYear() {
return getEnrolment().getExecutionYear();
}
public boolean isAnual() {
final Enrolment enrolment = getEnrolment();
return enrolment.isAnual();
}
public List<Locale> getLanguages() {
final List<Locale> result = new ArrayList<Locale>();
add(result, getKeywords());
add(result, getThesisAbstract());
add(result, getTitle());
final ThesisFile dissertation = getDissertation();
if (dissertation != null) {
add(result, dissertation.getLanguage());
}
final ThesisFile extendedAbstract = getExtendedAbstract();
if (extendedAbstract != null) {
add(result, extendedAbstract.getLanguage());
}
return result;
}
private void add(final List<Locale> result, final MultiLanguageString mls) {
if (mls != null) {
for (final Locale language : mls.getAllLocales()) {
add(result, language);
}
}
}
private void add(final List<Locale> result, final Locale language) {
if (language != null && !result.contains(language)) {
if (language == MultiLanguageString.pt) {
result.add(0, language);
} else if (language == MultiLanguageString.en) {
if (result.size() > 0 && result.iterator().next() == MultiLanguageString.pt) {
result.add(1, language);
} else if (result.size() > 0) {
result.add(0, language);
} else {
result.add(language);
}
} else {
result.add(language);
}
}
}
public boolean areThesisFilesReadable() {
final ThesisFile thesisFile = getDissertation();
return thesisFile != null && thesisFile.areThesisFilesReadable();
}
}