Package org.fenixedu.academic.domain.phd.candidacy

Source Code of org.fenixedu.academic.domain.phd.candidacy.PhdProgramCandidacyProcess

/**
* 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.phd.candidacy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.fenixedu.academic.domain.DegreeCurricularPlan;
import org.fenixedu.academic.domain.ExecutionDegree;
import org.fenixedu.academic.domain.ExecutionYear;
import org.fenixedu.academic.domain.Person;
import org.fenixedu.academic.domain.PhotoState;
import org.fenixedu.academic.domain.Photograph;
import org.fenixedu.academic.domain.accounting.EventType;
import org.fenixedu.academic.domain.accounting.PostingRule;
import org.fenixedu.academic.domain.accounting.events.insurance.InsuranceEvent;
import org.fenixedu.academic.domain.accounting.paymentCodes.IndividualCandidacyPaymentCode;
import org.fenixedu.academic.domain.candidacy.Ingression;
import org.fenixedu.academic.domain.caseHandling.Activity;
import org.fenixedu.academic.domain.caseHandling.StartActivity;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.person.RoleType;
import org.fenixedu.academic.domain.phd.PhdCandidacyProcessState;
import org.fenixedu.academic.domain.phd.PhdIndividualProgramDocumentType;
import org.fenixedu.academic.domain.phd.PhdIndividualProgramProcess;
import org.fenixedu.academic.domain.phd.PhdIndividualProgramProcessState;
import org.fenixedu.academic.domain.phd.PhdProgram;
import org.fenixedu.academic.domain.phd.PhdProgramCandidacyProcessState;
import org.fenixedu.academic.domain.phd.PhdProgramFocusArea;
import org.fenixedu.academic.domain.phd.PhdProgramProcessDocument;
import org.fenixedu.academic.domain.phd.PhdProgramServiceAgreementTemplate;
import org.fenixedu.academic.domain.phd.alert.PhdFinalProofRequestAlert;
import org.fenixedu.academic.domain.phd.alert.PhdPublicPresentationSeminarAlert;
import org.fenixedu.academic.domain.phd.alert.PhdRegistrationFormalizationAlert;
import org.fenixedu.academic.domain.phd.candidacy.activities.AddCandidacyReferees;
import org.fenixedu.academic.domain.phd.candidacy.activities.AddNotification;
import org.fenixedu.academic.domain.phd.candidacy.activities.AddState;
import org.fenixedu.academic.domain.phd.candidacy.activities.AssociateRegistration;
import org.fenixedu.academic.domain.phd.candidacy.activities.DeleteCandidacyReview;
import org.fenixedu.academic.domain.phd.candidacy.activities.DeleteDocument;
import org.fenixedu.academic.domain.phd.candidacy.activities.EditCandidacyDate;
import org.fenixedu.academic.domain.phd.candidacy.activities.EditProcessAttributes;
import org.fenixedu.academic.domain.phd.candidacy.activities.PhdProgramCandidacyProcessActivity;
import org.fenixedu.academic.domain.phd.candidacy.activities.RatifyCandidacy;
import org.fenixedu.academic.domain.phd.candidacy.activities.RegistrationFormalization;
import org.fenixedu.academic.domain.phd.candidacy.activities.RejectCandidacyProcess;
import org.fenixedu.academic.domain.phd.candidacy.activities.RemoveCandidacyDocument;
import org.fenixedu.academic.domain.phd.candidacy.activities.RemoveLastState;
import org.fenixedu.academic.domain.phd.candidacy.activities.RequestCandidacyReview;
import org.fenixedu.academic.domain.phd.candidacy.activities.RequestRatifyCandidacy;
import org.fenixedu.academic.domain.phd.candidacy.activities.UploadCandidacyReview;
import org.fenixedu.academic.domain.phd.candidacy.activities.UploadDocuments;
import org.fenixedu.academic.domain.phd.candidacy.activities.ValidatedByCandidate;
import org.fenixedu.academic.domain.phd.debts.PhdRegistrationFee;
import org.fenixedu.academic.domain.student.PersonalIngressionData;
import org.fenixedu.academic.domain.student.PrecedentDegreeInformation;
import org.fenixedu.academic.domain.student.Registration;
import org.fenixedu.academic.domain.student.RegistrationProtocol;
import org.fenixedu.academic.domain.student.Student;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.joda.time.LocalDate;

public class PhdProgramCandidacyProcess extends PhdProgramCandidacyProcess_Base {

    @StartActivity
    public static class CreateCandidacy extends PhdProgramCandidacyProcessActivity {

        @Override
        protected void activityPreConditions(PhdProgramCandidacyProcess process, User userView) {
        }

        @Override
        protected PhdProgramCandidacyProcess executeActivity(PhdProgramCandidacyProcess process, User userView, Object object) {
            final Object[] values = (Object[]) object;
            final PhdProgramCandidacyProcessBean bean = readBean(values);
            final Person person = readPerson(values);
            final PhdIndividualProgramProcess individualProgramProcess = readPhdIndividualProgramProcess(values);
            final PhdProgramCandidacyProcess result =
                    new PhdProgramCandidacyProcess(bean, person, bean.getMigratedProcess(), individualProgramProcess);
            result.createState(bean.getState(), person, "");
            return result;
        }

        private Person readPerson(final Object[] values) {
            return (Person) values[1];
        }

        private PhdProgramCandidacyProcessBean readBean(final Object[] values) {
            return (PhdProgramCandidacyProcessBean) values[0];
        }

        private PhdIndividualProgramProcess readPhdIndividualProgramProcess(final Object[] values) {
            return (PhdIndividualProgramProcess) values[2];
        }
    }

    static private List<Activity> activities = new ArrayList<Activity>();
    static {
        activities.add(new UploadDocuments());
        activities.add(new DeleteDocument());
        activities.add(new EditCandidacyDate());
        activities.add(new AddCandidacyReferees());
        activities.add(new ValidatedByCandidate());

        activities.add(new RequestCandidacyReview());
        activities.add(new UploadCandidacyReview());
        activities.add(new DeleteCandidacyReview());
        activities.add(new RejectCandidacyProcess());

        activities.add(new RequestRatifyCandidacy());
        activities.add(new RatifyCandidacy());

        activities.add(new AddNotification());
        activities.add(new RegistrationFormalization());
        activities.add(new AssociateRegistration());

        activities.add(new AddState());
        activities.add(new RemoveLastState());
        activities.add(new EditProcessAttributes());

        activities.add(new RemoveCandidacyDocument());
    }

    @Override
    public boolean isAllowedToManageProcess(User userView) {
        return this.getIndividualProgramProcess().isAllowedToManageProcess(userView);
    }

    private PhdProgramCandidacyProcess(final PhdProgramCandidacyProcessBean bean, final Person person, boolean isMigratedProcess,
            final PhdIndividualProgramProcess individualProgramProcess) {
        super();

        checkCandidacyDate(bean.getExecutionYear(), bean.getCandidacyDate());
        setCandidacyDate(bean.getCandidacyDate());
        setValidatedByCandidate(false);

        setCandidacyHashCode(bean.getCandidacyHashCode());
        PHDProgramCandidacy candidacy = new PHDProgramCandidacy(person);
        setCandidacy(candidacy);

        setIndividualProgramProcess(individualProgramProcess);

        if (bean.hasDegree()) {
            getCandidacy().setExecutionDegree(bean.getExecutionDegree());
        }

        if (!isMigratedProcess) {
            if (!bean.hasCollaborationType() || bean.getCollaborationType().generateCandidacyDebt()) {
                if (hasPaymentFees(EventType.CANDIDACY_ENROLMENT)) {
                    new PhdProgramCandidacyEvent(person, this);
                }
            }
        }

        if (isPublicCandidacy()) {
            if (bean.getPhdCandidacyPeriod() == null) {
                throw new DomainException("error.phd.candidacy.PhdProgramCandidacyProcess.public.candidacy.period.is.missing");
            }

            setPublicPhdCandidacyPeriod(bean.getPhdCandidacyPeriod());
        }

    }

    private boolean hasPaymentFees(final EventType candidacyEnrolmentEventType) {
        final PhdProgramServiceAgreementTemplate serviceAgreementTemplate = getPhdProgram().getServiceAgreementTemplate();
        for (final PostingRule postingRule : serviceAgreementTemplate.getAllPostingRulesFor(candidacyEnrolmentEventType)) {
            if (postingRule.isActive()) {
                if (postingRule instanceof PhdProgramCandidacyPR) {
                    final PhdProgramCandidacyPR phdProgramCandidacyPR = (PhdProgramCandidacyPR) postingRule;
                    if (phdProgramCandidacyPR.getFixedAmount().isPositive()) {
                        return true;
                    }
                } else {
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean hasOnlineApplicationForPeriod(final Person person, PhdCandidacyPeriod phdCandidacyPeriod) {
        Collection<PhdIndividualProgramProcess> phdIndividualProgramProcesses = person.getPhdIndividualProgramProcessesSet();

        for (PhdIndividualProgramProcess phdIndividualProgramProcess : phdIndividualProgramProcesses) {
            if (phdCandidacyPeriod == phdIndividualProgramProcess.getCandidacyProcess().getPublicPhdCandidacyPeriod()) {
                return true;
            }
        }

        return false;
    }

    public boolean isPublicCandidacy() {
        return getCandidacyHashCode() != null;
    }

    public IndividualCandidacyPaymentCode getAssociatedPaymentCode() {
        if (getEvent() == null) {
            return null;
        }

        return getEvent().getAssociatedPaymentCode();
    }

    public boolean hasPaymentCodeToPay() {
        if (getEvent() == null) {
            return false;
        }
        return getEvent().getAssociatedPaymentCode().getMinAmount().isPositive()
                && getEvent().getAssociatedPaymentCode().getMaxAmount().isPositive();
    }

    private void checkCandidacyDate(ExecutionYear executionYear, LocalDate candidacyDate) {
        // TODO: check this - in august candidacy dates will not be contained in
        // given execution year

        String[] args = {};
        if (candidacyDate == null) {
            throw new DomainException("error.phd.candidacy.PhdProgramCandidacyProcess.invalid.candidacy.date", args);
        }
        // if (!executionYear.containsDate(candidacyDate)) {
        // throw new DomainException(
        // "error.phd.candidacy.PhdProgramCandidacyProcess.executionYear.doesnot.contains.candidacy.date",
        // candidacyDate
        // .toString("dd/MM/yyyy"), executionYear.getQualifiedName(),
        // executionYear.getBeginDateYearMonthDay()
        // .toString("dd/MM/yyyy"),
        // executionYear.getEndDateYearMonthDay().toString("dd/MM/yyyy"));
        // }
    }

    @Override
    public boolean canExecuteActivity(User userView) {
        return false;
    }

    @Override
    public List<Activity> getActivities() {
        return activities;
    }

    @Override
    public String getDisplayName() {
        return BundleUtil.getString(Bundle.PHD, getClass().getSimpleName());
    }

    public PhdProgramCandidacyProcess edit(final LocalDate candidacyDate) {
        checkCandidacyDate(getExecutionYear(), candidacyDate);
        setCandidacyDate(candidacyDate);
        return this;
    }

    private ExecutionYear getExecutionYear() {
        return getIndividualProgramProcess().getExecutionYear();
    }

    public boolean hasAnyPayments() {
        return getEvent() != null && getEvent().hasAnyPayments();
    }

    public void cancelDebt(final Person responsible) {
        if (getEvent() != null && getEvent().isOpen()) {
            getEvent().cancel(responsible);
        }
    }

    public String getProcessNumber() {
        return getIndividualProgramProcess().getProcessNumber();
    }

    @Override
    public Person getPerson() {
        return getIndividualProgramProcess().getPerson();
    }

    public Set<PhdProgramProcessDocument> getCandidacyReviewDocuments() {
        return getLatestDocumentsByType(PhdIndividualProgramDocumentType.CANDIDACY_REVIEW);
    }

    public boolean hasAnyDocuments(final PhdIndividualProgramDocumentType type) {
        return !getLatestDocumentsByType(type).isEmpty();
    }

    public int getDocumentsCount(final PhdIndividualProgramDocumentType type) {
        return getLatestDocumentsByType(type).size();
    }

    public boolean isValidatedByCandidate() {
        return getValidatedByCandidate() != null && getValidatedByCandidate().booleanValue();
    }

    public boolean isOngoingApplicationAndValidatedByApplicant() {
        return isValidatedByCandidate()
                || getIndividualProgramProcess().getActiveState() != PhdIndividualProgramProcessState.CANDIDACY;
    }

    public Set<PhdProgramProcessDocument> getStudyPlanRelevantDocuments() {
        final Set<PhdProgramProcessDocument> result = new HashSet<PhdProgramProcessDocument>();
        result.addAll(getLatestDocumentsByType(PhdIndividualProgramDocumentType.STUDY_PLAN));
        result.addAll(getLatestDocumentsByType(PhdIndividualProgramDocumentType.CANDIDACY_REVIEW));

        return result;
    }

    public void createState(final PhdProgramCandidacyProcessState stateType, final Person person, final String remarks) {
        PhdCandidacyProcessState.createStateWithInferredStateDate(this, stateType, person, remarks);
    }

    @Override
    public PhdCandidacyProcessState getMostRecentState() {
        return (PhdCandidacyProcessState) super.getMostRecentState();
    }

    @Override
    public PhdProgramCandidacyProcessState getActiveState() {
        return (PhdProgramCandidacyProcessState) super.getActiveState();
    }

    public boolean isInState(final PhdProgramCandidacyProcessState state) {
        return getActiveState().equals(state);
    }

    public void ratify(RatifyCandidacyBean bean, Person responsible) {

        Object obj = bean.getWhenRatified();
        String[] args = {};
        if (obj == null) {
            throw new DomainException("error.phd.candidacy.PhdProgramCandidacyProcess.when.ratified.cannot.be.null", args);
        }

        if (!getIndividualProgramProcess().getPhdConfigurationIndividualProgramProcess().isMigratedProcess()
                && !bean.getRatificationFile().hasAnyInformation()) {
            throw new DomainException("error.phd.candidacy.PhdProgramCandidacyProcess.ratification.document.is.required");
        }

        setWhenRatified(bean.getWhenRatified());

        if (bean.getRatificationFile().hasAnyInformation()) {
            addDocument(bean.getRatificationFile(), responsible);
        }

        if (!getIndividualProgramProcess().getPhdConfigurationIndividualProgramProcess().isMigratedProcess()
                && !getIndividualProgramProcess().hasAnyRegistrationFormalizationActiveAlert()) {
            new PhdRegistrationFormalizationAlert(getIndividualProgramProcess(), bean.getMaxDaysToFormalizeRegistration());
        }

        createState(PhdProgramCandidacyProcessState.RATIFIED_BY_SCIENTIFIC_COUNCIL, responsible, "");

    }

    public PhdProgramCandidacyProcess registrationFormalization(final RegistrationFormalizationBean bean, final Person responsible) {

        if (!hasStudyPlan()) {
            throw new DomainException(
                    "error.phd.candidacy.PhdProgramCandidacyProcess.registrationFormalization.must.create.study.plan");
        }

        LocalDate whenFormalizedRegistration = new LocalDate();

        getIndividualProgramProcess().setWhenFormalizedRegistration(whenFormalizedRegistration);
        getIndividualProgramProcess().setWhenStartedStudies(bean.getWhenStartedStudies());

        assertPersonInformation();

        if (!getIndividualProgramProcess().getPhdConfigurationIndividualProgramProcess().isMigratedProcess()) {
            final DegreeCurricularPlan dcp = getPhdProgramLastActiveDegreeCurricularPlan();
            assertStudyPlanInformation(bean, dcp);
            assertDebts(bean);
            assertRegistrationFormalizationAlerts();
        }

        createState(PhdProgramCandidacyProcessState.CONCLUDED, responsible, "");
        getIndividualProgramProcess().createState(PhdIndividualProgramProcessState.WORK_DEVELOPMENT, responsible, "");

        return this;
    }

    private void assertStudyPlanInformation(final RegistrationFormalizationBean bean,
            final DegreeCurricularPlan degreeCurricularPlan) {
        final ExecutionYear executionYear = ExecutionYear.readByDateTime(bean.getWhenStartedStudies());

        if (executionYear == null) {
            throw new DomainException("error.phd.candidacy.PhdProgramCandidacyProcess.StudyPlan.invalid.start.date");
        }

        if (hasCurricularStudyPlan()) {
            assertCandidacy(degreeCurricularPlan, executionYear);
            assertRegistration(bean, degreeCurricularPlan, executionYear);
        }
    }

    public PhdProgramCandidacyProcess associateRegistration(final RegistrationFormalizationBean bean) {

        if (isStudyPlanExempted()) {
            throw new DomainException(
                    "error.phd.candidacy.PhdProgramCandidacyProcess.associateRegistration.study.plan.is.exempted");
        }

        assertStudyPlanInformation(bean, bean.getRegistration().getLastDegreeCurricularPlan());
        assertRegistrationFormalizationAlerts();

        if (!getIndividualProgramProcess().getPhdConfigurationIndividualProgramProcess().isMigratedProcess()) {
            assertDebts(bean);
        }

        return this;
    }

    private void assertPersonInformation() {
        final Person person = getPerson();

        if (getPerson().getStudent() == null) {
            new Student(getPerson());
        }

        Student student = getPerson().getStudent();
        PrecedentDegreeInformation precedentDegreeInformation = getCandidacy().getPrecedentDegreeInformation();
        ExecutionYear executionYear = getExecutionYear();
        if (getPerson().getStudent().getPersonalIngressionDataByExecutionYear(executionYear) == null) {
            new PersonalIngressionData(student, executionYear, precedentDegreeInformation);
        }

        PersonalIngressionData personalIngressionData =
                getPerson().getStudent().getPersonalIngressionDataByExecutionYear(executionYear);
        personalIngressionData.addPrecedentDegreesInformations(precedentDegreeInformation);
        precedentDegreeInformation.setPhdIndividualProgramProcess(getIndividualProgramProcess());

        RoleType.grant(RoleType.PERSON, person.getUser());
        RoleType.grant(RoleType.STUDENT, person.getUser());
        RoleType.grant(RoleType.RESEARCHER, person.getUser());

        if (person.getPersonalPhoto() == null) {
            final Photograph photograph = person.getPersonalPhotoEvenIfPending();
            if (photograph != null) {
                photograph.setState(PhotoState.APPROVED);
            }
        }
    }

    private void assertCandidacy(final DegreeCurricularPlan dcp, final ExecutionYear executionYear) {
        if (getCandidacy().getExecutionDegree() == null) {
            final ExecutionDegree executionDegree = dcp.getExecutionDegreeByAcademicInterval(executionYear.getAcademicInterval());
            getCandidacy().setExecutionDegree(executionDegree);
        }

        getCandidacy().setIngression(Ingression.CIA3C);
    }

    private void assertRegistration(final RegistrationFormalizationBean bean, final DegreeCurricularPlan dcp,
            final ExecutionYear executionYear) {

        final Registration registration = getOrCreateRegistration(bean, dcp, executionYear);

        registration.setHomologationDate(getWhenRatified());
        registration.setStudiesStartDate(bean.getWhenStartedStudies());
        registration.setIngression(Ingression.CIA3C);
        registration.setPhdIndividualProgramProcess(getIndividualProgramProcess());

        registration.editStartDates(bean.getWhenStartedStudies(), getWhenRatified(), bean.getWhenStartedStudies());

        if (registration.getStudentCandidacy() == getIndividualProgramProcess().getCandidacyProcess().getCandidacy()) {
            return;
        }

    }

    private Registration getOrCreateRegistration(final RegistrationFormalizationBean bean, final DegreeCurricularPlan dcp,
            final ExecutionYear executionYear) {

        final Registration registration;
        if (getIndividualProgramProcess().getPhdConfigurationIndividualProgramProcess().isMigratedProcess()
                && bean.hasRegistration()) {
            return bean.getRegistration();
        }

        if (hasActiveRegistrationFor(dcp)) {
            if (!bean.hasRegistration()) {
                throw new DomainException("error.PhdProgramCandidacyProcess.regisration.formalization.already.has.registration");
            }
            registration = bean.getRegistration();
        } else {
            registration =
                    new Registration(getPerson(), dcp, getCandidacy(), RegistrationProtocol.getDefault(), null, executionYear);
        }

        return registration;
    }

    private void assertDebts(final RegistrationFormalizationBean bean) {
        assertPhdRegistrationFee();
        assertInsuranceEvent(ExecutionYear.readByDateTime(bean.getWhenStartedStudies()));
    }

    private void assertPhdRegistrationFee() {
        if (getIndividualProgramProcess().getRegistrationFee() == null) {
            new PhdRegistrationFee(getIndividualProgramProcess());
        }
    }

    private void assertInsuranceEvent(final ExecutionYear executionYear) {
        if (!getPerson().hasInsuranceEventFor(executionYear)
                && !getPerson().hasAdministrativeOfficeFeeInsuranceEventFor(executionYear)) {
            new InsuranceEvent(getPerson(), executionYear);
        }
    }

    private void assertRegistrationFormalizationAlerts() {
        if (!getIndividualProgramProcess().getPhdConfigurationIndividualProgramProcess().isMigratedProcess()
                && !getIndividualProgramProcess().hasPhdPublicPresentationSeminarAlert()) {
            new PhdPublicPresentationSeminarAlert(getIndividualProgramProcess());
        }

        if (!getIndividualProgramProcess().getPhdConfigurationIndividualProgramProcess().isMigratedProcess()
                && !getIndividualProgramProcess().hasPhdFinalProofRequestAlert()) {
            new PhdFinalProofRequestAlert(getIndividualProgramProcess());
        }
    }

    private boolean hasCurricularStudyPlan() {
        return hasStudyPlan() && !getIndividualProgramProcess().getStudyPlan().isExempted();
    }

    public DegreeCurricularPlan getPhdProgramLastActiveDegreeCurricularPlan() {
        return hasPhdProgram() ? getPhdProgram().getDegree().getLastActiveDegreeCurricularPlan() : null;
    }

    PhdProgram getPhdProgram() {
        return getIndividualProgramProcess().getPhdProgram();
    }

    PhdProgramFocusArea getPhdProgramFocusArea() {
        return getIndividualProgramProcess().getPhdProgramFocusArea();
    }

    boolean hasPhdProgramFocusArea() {
        return getPhdProgramFocusArea() != null;
    }

    public boolean hasPhdProgram() {
        return getPhdProgram() != null;
    }

    public boolean hasStudyPlan() {
        return getIndividualProgramProcess().getStudyPlan() != null;
    }

    public boolean isStudyPlanExempted() {
        return hasStudyPlan() && getIndividualProgramProcess().getStudyPlan().isExempted();
    }

    public boolean hasActiveRegistrationFor(DegreeCurricularPlan degreeCurricularPlan) {
        return getPerson().getStudent() != null ? getPerson().getStudent().hasActiveRegistrationFor(degreeCurricularPlan) : false;
    }

    public LocalDate getWhenStartedStudies() {
        return getIndividualProgramProcess().getWhenStartedStudies();
    }

    public void deleteLastState() {
        if (getStatesSet().size() <= 1) {
            throw new DomainException("error.phd.candidacy.PhdProgramCandidacyProcess.cannot.delete.the.only.state");
        }

        getMostRecentState().delete();
    }

    public PhdCandidacyReferee getCandidacyRefereeByEmail(final String email) {
        Collection<PhdCandidacyReferee> candidacyReferees = getCandidacyRefereesSet();

        for (PhdCandidacyReferee phdCandidacyReferee : candidacyReferees) {
            if (phdCandidacyReferee.getEmail().trim().equals(email.trim())) {
                return phdCandidacyReferee;
            }
        }

        return null;
    }

    @Override
    @Deprecated
    public java.util.Set<org.fenixedu.academic.domain.phd.PhdCandidacyProcessState> getStates() {
        return getStatesSet();
    }

    @Override
    public boolean hasAnyStates() {
        return !getStatesSet().isEmpty();
    }

}
TOP

Related Classes of org.fenixedu.academic.domain.phd.candidacy.PhdProgramCandidacyProcess

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.