Package org.fenixedu.academic.domain.studentCurriculum

Source Code of org.fenixedu.academic.domain.studentCurriculum.CurriculumGroup

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

import static org.fenixedu.academic.predicate.AccessControl.check;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.fenixedu.academic.domain.CurricularCourse;
import org.fenixedu.academic.domain.Enrolment;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.ExecutionYear;
import org.fenixedu.academic.domain.OptionalEnrolment;
import org.fenixedu.academic.domain.StudentCurricularPlan;
import org.fenixedu.academic.domain.curricularRules.CreditsLimit;
import org.fenixedu.academic.domain.curricularRules.CurricularRuleType;
import org.fenixedu.academic.domain.curricularRules.DegreeModulesSelectionLimit;
import org.fenixedu.academic.domain.degreeStructure.BranchCourseGroup;
import org.fenixedu.academic.domain.degreeStructure.BranchType;
import org.fenixedu.academic.domain.degreeStructure.Context;
import org.fenixedu.academic.domain.degreeStructure.CourseGroup;
import org.fenixedu.academic.domain.degreeStructure.DegreeModule;
import org.fenixedu.academic.domain.enrolment.EnroledCurriculumModuleWrapper;
import org.fenixedu.academic.domain.enrolment.IDegreeModuleToEvaluate;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.student.curriculum.Curriculum;
import org.fenixedu.academic.predicate.RolePredicates;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.joda.time.DateTime;
import org.joda.time.YearMonthDay;

import pt.utl.ist.fenix.tools.predicates.AndPredicate;
import pt.utl.ist.fenix.tools.predicates.Predicate;
import pt.utl.ist.fenix.tools.predicates.ResultCollection;

public class CurriculumGroup extends CurriculumGroup_Base {

    static final public Comparator<CurriculumGroup> COMPARATOR_BY_CHILD_ORDER_AND_ID = new Comparator<CurriculumGroup>() {
        @Override
        public int compare(CurriculumGroup o1, CurriculumGroup o2) {
            int result = o1.getChildOrder().compareTo(o2.getChildOrder());
            return (result != 0) ? result : o1.getExternalId().compareTo(o2.getExternalId());
        }
    };

    protected CurriculumGroup() {
        super();
    }

    public CurriculumGroup(final CurriculumGroup curriculumGroup, final CourseGroup courseGroup) {
        this();
        init(curriculumGroup, courseGroup);
    }

    protected void init(final CurriculumGroup curriculumGroup, final CourseGroup courseGroup) {
        if (courseGroup == null || curriculumGroup == null) {
            throw new DomainException("error.studentCurriculum.curriculumGroup.courseGroup.cannot.be.null");
        }
        checkInitConstraints(curriculumGroup, courseGroup);
        setDegreeModule(courseGroup);
        setCurriculumGroup(curriculumGroup);
    }

    protected void checkInitConstraints(final CurriculumGroup parent, final CourseGroup courseGroup) {
        if (parent.getRootCurriculumGroup().hasCourseGroup(courseGroup)) {
            throw new DomainException("error.studentCurriculum.CurriculumGroup.duplicate.courseGroup", courseGroup.getName());
        }
    }

    protected void checkParameters(CourseGroup courseGroup, ExecutionSemester executionSemester) {
        if (courseGroup == null) {
            throw new DomainException("error.studentCurriculum.curriculumGroup.courseGroup.cannot.be.null");
        }
        if (executionSemester == null) {
            throw new DomainException("error.studentCurriculum.curriculumGroup.executionPeriod.cannot.be.null");
        }
    }

    public CurriculumGroup(CurriculumGroup parentCurriculumGroup, CourseGroup courseGroup, ExecutionSemester executionSemester) {
        super();
        init(parentCurriculumGroup, courseGroup, executionSemester);
    }

    protected void init(final CurriculumGroup curriculumGroup, final CourseGroup courseGroup,
            final ExecutionSemester executionSemester) {

        checkInitConstraints(curriculumGroup, courseGroup);
        checkParameters(curriculumGroup, courseGroup, executionSemester);

        setDegreeModule(courseGroup);
        setCurriculumGroup(curriculumGroup);
        addChildCurriculumGroups(courseGroup, executionSemester);
    }

    private void checkParameters(CurriculumGroup parentCurriculumGroup, CourseGroup courseGroup,
            ExecutionSemester executionSemester) {

        if (parentCurriculumGroup == null) {
            throw new DomainException("error.studentCurriculum.curriculumGroup.parentCurriculumGroup.cannot.be.null");
        }

        checkParameters(courseGroup, executionSemester);
    }

    protected void addChildCurriculumGroups(final CourseGroup courseGroup, final ExecutionSemester executionSemester) {
        for (final CourseGroup childCourseGroup : courseGroup.getNotOptionalChildCourseGroups(executionSemester)) {
            CurriculumGroupFactory.createGroup(this, childCourseGroup, executionSemester);
        }
    }

    @Override
    final public boolean isLeaf() {
        return false;
    }

    @Override
    protected void checkForDeletionBlockers(Collection<String> blockers) {
        super.checkForDeletionBlockers(blockers);
        if (!getCurriculumModulesSet().isEmpty()) {
            blockers.add(BundleUtil.getString(Bundle.APPLICATION,
                    "error.studentCurriculum.CurriculumGroup.notEmptyCurriculumGroupModules", getName().getContent()));
        }
    }

    public boolean isDeletable() {
        return getDeletionBlockers().isEmpty();
    }

    @Override
    public void deleteRecursive() {
        check(this, RolePredicates.MANAGER_PREDICATE);
        for (final CurriculumModule child : getCurriculumModulesSet()) {
            child.deleteRecursive();
        }

        delete();
    }

    @Override
    final public StringBuilder print(String tabs) {
        final StringBuilder builder = new StringBuilder();
        builder.append(tabs);
        builder.append("[CG ").append(getName().getContent()).append(" ]\n");
        final String tab = tabs + "\t";
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            builder.append(curriculumModule.print(tab));
        }
        return builder;
    }

    @Override
    public CourseGroup getDegreeModule() {
        return (CourseGroup) super.getDegreeModule();
    }

    @Override
    final public List<Enrolment> getEnrolments() {
        final List<Enrolment> result = new ArrayList<Enrolment>();
        for (final CurriculumModule curriculumModule : this.getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getEnrolments());
        }
        return result;
    }

    final public Set<Enrolment> getEnrolmentsSet() {
        final Set<Enrolment> result = new HashSet<Enrolment>();
        for (final CurriculumModule curriculumModule : this.getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getEnrolments());
        }
        return result;
    }

    @Override
    final public boolean hasAnyEnrolments() {
        return hasAnyCurriculumModules(new CurriculumModulePredicateByType(Enrolment.class));
    }

    @Override
    public boolean hasAnyCurriculumModules(final Predicate<CurriculumModule> predicate) {
        if (super.hasAnyCurriculumModules(predicate)) {
            return true;
        }

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.hasAnyCurriculumModules(predicate)) {
                return true;
            }
        }

        return false;
    }

    @Override
    final public void collectDismissals(final List<Dismissal> result) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            curriculumModule.collectDismissals(result);
        }
    }

    public List<Dismissal> getChildDismissals() {
        final List<Dismissal> result = new ArrayList<Dismissal>();
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isDismissal()) {
                result.add((Dismissal) curriculumModule);
            }
        }
        return result;
    }

    public double getChildCreditsDismissalEcts() {
        double total = 0;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isCreditsDismissal()) {
                total += curriculumModule.getEctsCredits();
            }
        }

        return total;
    }

    public List<Enrolment> getChildEnrolments() {
        final List<Enrolment> result = new ArrayList<Enrolment>();
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isEnrolment()) {
                result.add((Enrolment) curriculumModule);
            }
        }

        return result;
    }

    public List<CurriculumLine> getChildCurriculumLines() {
        final List<CurriculumLine> result = new ArrayList<CurriculumLine>();
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isLeaf()) {
                result.add((CurriculumLine) curriculumModule);
            }
        }

        return result;
    }

    public List<CurriculumGroup> getChildCurriculumGroups() {
        final List<CurriculumGroup> result = new ArrayList<CurriculumGroup>();
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (!curriculumModule.isLeaf()) {
                result.add((CurriculumGroup) curriculumModule);
            }
        }

        return result;
    }

    @Override
    public boolean isRoot() {
        return false;
    }

    @Override
    public StudentCurricularPlan getStudentCurricularPlan() {
        return getCurriculumGroup().getStudentCurricularPlan();
    }

    private Collection<Context> getDegreeModulesFor(ExecutionSemester executionSemester) {
        return this.getDegreeModule().getValidChildContexts(executionSemester);
    }

    public List<Context> getCurricularCourseContextsToEnrol(ExecutionSemester executionSemester) {
        List<Context> result = new ArrayList<Context>();
        for (Context context : this.getDegreeModulesFor(executionSemester)) {
            if (context.getChildDegreeModule().isLeaf()) {
                CurricularCourse curricularCourse = (CurricularCourse) context.getChildDegreeModule();
                if (!this.getStudentCurricularPlan().isApproved(curricularCourse, executionSemester)
                        && !this.getStudentCurricularPlan().isEnroledInExecutionPeriod(curricularCourse, executionSemester)) {
                    result.add(context);
                }
            }
        }
        return result;
    }

    public List<Context> getCourseGroupContextsToEnrol(ExecutionSemester executionSemester) {
        List<Context> result = new ArrayList<Context>();
        for (Context context : this.getDegreeModulesFor(executionSemester)) {
            if (!context.getChildDegreeModule().isLeaf()) {
                if (!this.getStudentCurricularPlan().getRoot().hasDegreeModule(context.getChildDegreeModule())) {
                    result.add(context);
                }
            }
        }
        return result;
    }

    public Collection<CurricularCourse> getCurricularCoursesToDismissal(final ExecutionSemester executionSemester) {
        final Set<CurricularCourse> result = new HashSet<CurricularCourse>();
        for (final Context context : getDegreeModule().getOpenChildContexts(CurricularCourse.class, executionSemester)) {
            final CurricularCourse curricularCourse = (CurricularCourse) context.getChildDegreeModule();
            if (!getStudentCurricularPlan().getRoot().isApproved(curricularCourse, null)) {
                result.add(curricularCourse);
            }
        }
        return result;
    }

    @Override
    final public boolean isApproved(CurricularCourse curricularCourse, ExecutionSemester executionSemester) {
        for (final CurriculumModule curriculumModule : this.getCurriculumModulesSet()) {
            if (curriculumModule.isApproved(curricularCourse, executionSemester)) {
                return true;
            }
        }
        return false;
    }

    @Override
    final public boolean isEnroledInExecutionPeriod(CurricularCourse curricularCourse, ExecutionSemester executionSemester) {
        for (final CurriculumModule curriculumModule : this.getCurriculumModulesSet()) {
            if (curriculumModule.isEnroledInExecutionPeriod(curricularCourse, executionSemester)) {
                return true;
            }
        }
        return false;
    }

    @Override
    final public boolean hasEnrolmentWithEnroledState(final CurricularCourse curricularCourse,
            final ExecutionSemester executionSemester) {
        for (final CurriculumModule curriculumModule : this.getCurriculumModulesSet()) {
            if (curriculumModule.hasEnrolmentWithEnroledState(curricularCourse, executionSemester)) {
                return true;
            }
        }
        return false;
    }

    @Override
    final public ExecutionYear getIEnrolmentsLastExecutionYear() {
        ExecutionYear result = null;

        for (final CurriculumModule curriculumModule : this.getCurriculumModulesSet()) {
            final ExecutionYear lastExecutionYear = curriculumModule.getIEnrolmentsLastExecutionYear();
            if (result == null || result.isBefore(lastExecutionYear)) {
                result = lastExecutionYear;
            }
        }

        return result;
    }

    @Override
    public boolean hasDegreeModule(DegreeModule degreeModule) {
        if (super.hasDegreeModule(degreeModule)) {
            return true;
        } else {
            for (final CurriculumModule curriculumModule : this.getCurriculumModulesSet()) {
                if (curriculumModule.hasDegreeModule(degreeModule)) {
                    return true;
                }
            }
            return false;
        }
    }

    @Override
    final public boolean hasCurriculumModule(CurriculumModule curriculumModule) {
        if (super.hasCurriculumModule(curriculumModule)) {
            return true;
        }
        for (final CurriculumModule module : getCurriculumModulesSet()) {
            if (module.hasCurriculumModule(curriculumModule)) {
                return true;
            }
        }
        return false;
    }

    @Override
    final public Enrolment findEnrolmentFor(final CurricularCourse curricularCourse, final ExecutionSemester executionSemester) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            final Enrolment search = curriculumModule.findEnrolmentFor(curricularCourse, executionSemester);
            if (search != null) {
                return search;
            }
        }
        return null;
    }

    @Override
    final public Enrolment getApprovedEnrolment(final CurricularCourse curricularCourse) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            final Enrolment enrolment = curriculumModule.getApprovedEnrolment(curricularCourse);
            if (enrolment != null) {
                return enrolment;
            }
        }
        return null;
    }

    @Override
    final public Dismissal getDismissal(final CurricularCourse curricularCourse) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            final Dismissal dismissal = curriculumModule.getDismissal(curricularCourse);
            if (dismissal != null) {
                return dismissal;
            }
        }
        return null;
    }

    @Override
    final public CurriculumLine getApprovedCurriculumLine(final CurricularCourse curricularCourse) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            final CurriculumLine curriculumLine = curriculumModule.getApprovedCurriculumLine(curricularCourse);
            if (curriculumLine != null) {
                return curriculumLine;
            }
        }
        return null;
    }

    public CurriculumGroup findCurriculumGroupFor(final CourseGroup courseGroup) {
        if (getDegreeModule() == courseGroup) {
            return this;
        }
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (!curriculumModule.isLeaf()) {
                final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
                final CurriculumGroup searchCurriculumGroup = curriculumGroup.findCurriculumGroupFor(courseGroup);
                if (searchCurriculumGroup != null) {
                    return searchCurriculumGroup;
                }
            }
        }
        return null;
    }

    @Override
    public void getCurriculumModules(final ResultCollection<CurriculumModule> collection) {
        collection.condicionalAdd(this);
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            curriculumModule.getCurriculumModules(collection);
        }
    }

    final public Set<CurriculumLine> getCurriculumLines() {
        Set<CurriculumLine> result = new TreeSet<CurriculumLine>(CurriculumModule.COMPARATOR_BY_NAME_AND_ID);

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isLeaf()) {
                result.add((CurriculumLine) curriculumModule);
            }
        }

        return result;
    }

    final public boolean hasCurriculumLines() {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isLeaf()) {
                return true;
            }
        }

        return false;
    }

    @Override
    final public void addApprovedCurriculumLines(final Collection<CurriculumLine> result) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            curriculumModule.addApprovedCurriculumLines(result);
        }
    }

    @Override
    final public boolean hasAnyApprovedCurriculumLines() {
        final AndPredicate<CurriculumModule> andPredicate = new AndPredicate<CurriculumModule>();
        andPredicate.add(new CurriculumModulePredicateByType(CurriculumLine.class));
        andPredicate.add(new CurriculumModulePredicateByApproval());

        return hasAnyCurriculumModules(andPredicate);
    }

    final public Set<CurriculumGroup> getCurriculumGroups() {
        Set<CurriculumGroup> result = new TreeSet<CurriculumGroup>(CurriculumModule.COMPARATOR_BY_NAME_AND_ID);

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (!curriculumModule.isLeaf()) {
                result.add((CurriculumGroup) curriculumModule);
            }
        }

        return result;
    }

    public Set<CurriculumGroup> getCurriculumGroupsToEnrolmentProcess() {
        final Set<CurriculumGroup> result = new TreeSet<CurriculumGroup>(CurriculumModule.COMPARATOR_BY_NAME_AND_ID);

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (!curriculumModule.isLeaf() && !curriculumModule.isNoCourseGroupCurriculumGroup()) {
                result.add((CurriculumGroup) curriculumModule);
            }
        }

        return result;
    }

    public Set<BranchCurriculumGroup> getBranchCurriculumGroups() {
        final Set<BranchCurriculumGroup> result = new HashSet<BranchCurriculumGroup>(1);

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule instanceof CurriculumGroup) {
                final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
                result.addAll(curriculumGroup.getBranchCurriculumGroups());
            }
        }

        return result;
    }

    public Set<BranchCurriculumGroup> getBranchCurriculumGroups(final BranchType branchType) {
        final Set<BranchCurriculumGroup> result = new HashSet<BranchCurriculumGroup>(1);

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule instanceof CurriculumGroup) {
                final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
                result.addAll(curriculumGroup.getBranchCurriculumGroups(branchType));
            }
        }

        return result;
    }

    public boolean hasBranchCurriculumGroup(final BranchType type) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule instanceof CurriculumGroup) {
                final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
                if (curriculumGroup.hasBranchCurriculumGroup(type)) {
                    return true;
                }
            }
        }
        return false;
    }

    public Set<BranchCurriculumGroup> getMajorBranchCurriculumGroups() {
        return getBranchCurriculumGroups(BranchType.MAJOR);
    }

    public Set<BranchCurriculumGroup> getMinorBranchCurriculumGroups() {
        return getBranchCurriculumGroups(BranchType.MINOR);
    }

    public Set<BranchCourseGroup> getBranchCourseGroups(BranchType branchType) {
        final Set<BranchCourseGroup> result = new HashSet<BranchCourseGroup>();
        for (final BranchCurriculumGroup group : getBranchCurriculumGroups(branchType)) {
            result.add(group.getDegreeModule());
        }
        return result;
    }

    public Set<BranchCourseGroup> getMajorBranchCourseGroups() {
        return getBranchCourseGroups(BranchType.MAJOR);
    }

    public Set<BranchCourseGroup> getMinorBranchCourseGroups() {
        return getBranchCourseGroups(BranchType.MINOR);
    }

    @Override
    public Set<CurriculumGroup> getAllCurriculumGroups() {
        Set<CurriculumGroup> result = new HashSet<CurriculumGroup>();
        result.add(this);

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getAllCurriculumGroups());
        }
        return result;
    }

    @Override
    public Set<CurriculumGroup> getAllCurriculumGroupsWithoutNoCourseGroupCurriculumGroups() {
        Set<CurriculumGroup> result = new HashSet<CurriculumGroup>();
        result.add(this);

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getAllCurriculumGroupsWithoutNoCourseGroupCurriculumGroups());
        }
        return result;
    }

    @Override
    public Set<CurriculumLine> getAllCurriculumLines() {
        Set<CurriculumLine> result = new HashSet<CurriculumLine>();
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getAllCurriculumLines());
        }
        return result;
    }

    public Integer getChildOrder() {
        return getChildOrder(null);
    }

    public Integer getChildOrder(final ExecutionSemester executionSemester) {
        final Integer childOrder = getParentCurriculumGroup().searchChildOrderForChild(this, executionSemester);
        return childOrder != null ? childOrder : Integer.MAX_VALUE;
    }

    private CurriculumGroup getParentCurriculumGroup() {
        return getCurriculumGroup();
    }

    protected Integer searchChildOrderForChild(final CurriculumGroup child, final ExecutionSemester executionSemester) {
        for (final Context context : getDegreeModule().getValidChildContexts(executionSemester)) {
            if (context.getChildDegreeModule() == child.getDegreeModule()) {
                return context.getChildOrder();
            }
        }
        return null;
    }

    public boolean hasCourseGroup(final CourseGroup courseGroup) {
        if (getDegreeModule().equals(courseGroup)) {
            return true;
        }

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (!curriculumModule.isLeaf()) {
                CurriculumGroup group = (CurriculumGroup) curriculumModule;
                if (group.hasCourseGroup(courseGroup)) {
                    return true;
                }
            }
        }

        return false;
    }

    final public NoCourseGroupCurriculumGroup getNoCourseGroupCurriculumGroup(NoCourseGroupCurriculumGroupType groupType) {
        for (final CurriculumGroup curriculumGroup : getCurriculumGroups()) {
            if (curriculumGroup.isNoCourseGroupCurriculumGroup()) {
                NoCourseGroupCurriculumGroup noCourseGroupCurriculumGroup = (NoCourseGroupCurriculumGroup) curriculumGroup;
                if (noCourseGroupCurriculumGroup.getNoCourseGroupCurriculumGroupType().equals(groupType)) {
                    return noCourseGroupCurriculumGroup;
                }
            }
        }

        return null;
    }

    @Override
    final public Double getEctsCredits() {
        BigDecimal bigDecimal = BigDecimal.ZERO;
        for (CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            bigDecimal = bigDecimal.add(new BigDecimal(curriculumModule.getEctsCredits()));
        }
        return Double.valueOf(bigDecimal.doubleValue());
    }

    @Override
    public Double getAprovedEctsCredits() {
        BigDecimal bigDecimal = BigDecimal.ZERO;
        for (CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            bigDecimal = bigDecimal.add(new BigDecimal(curriculumModule.getAprovedEctsCredits()));
        }
        return Double.valueOf(bigDecimal.doubleValue());
    }

    @Override
    final public Double getEnroledEctsCredits(final ExecutionSemester executionSemester) {
        BigDecimal bigDecimal = BigDecimal.ZERO;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            bigDecimal = bigDecimal.add(new BigDecimal(curriculumModule.getEnroledEctsCredits(executionSemester)));
        }
        return Double.valueOf(bigDecimal.doubleValue());
    }

    @Override
    @SuppressWarnings("unchecked")
    public Double getCreditsConcluded(ExecutionYear executionYear) {
        final CreditsLimit creditsLimit =
                (CreditsLimit) getMostRecentActiveCurricularRule(CurricularRuleType.CREDITS_LIMIT, executionYear);

        Double creditsConcluded = 0d;
        for (CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            creditsConcluded += curriculumModule.getCreditsConcluded(executionYear);
        }

        if (creditsLimit == null) {
            return creditsConcluded;
        } else {
            return Math.min(creditsLimit.getMaximumCredits(), creditsConcluded);
        }
    }

    final public int getNumberOfChildCurriculumGroupsWithCourseGroup() {
        int result = 0;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (!curriculumModule.isLeaf()) {
                final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
                if (!curriculumGroup.isNoCourseGroupCurriculumGroup()) {
                    result++;
                }
            }
        }
        return result;
    }

    /**
     * This method returns the number of approved child CurriculumLines
     */
    final public int getNumberOfApprovedChildCurriculumLines() {
        int result = 0;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isCurriculumLine()) {
                final CurriculumLine curriculumLine = (CurriculumLine) curriculumModule;
                if (curriculumLine.isDismissal() && curriculumLine.hasCurricularCourse()) {
                    result++;
                } else if (curriculumLine.isEnrolment() && ((Enrolment) curriculumLine).isApproved()) {
                    result++;
                }
            }
        }
        return result;
    }

    /**
     * This method makes a deep search to count number of all enrolled
     * CurriculumLines (except NoCourseGroupCurriculumGroups)
     */
    public int getNumberOfAllEnroledCurriculumLines() {
        int result = 0;
        for (CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isCurriculumLine()) {
                final CurriculumLine curriculumLine = (CurriculumLine) curriculumModule;
                if (curriculumLine.isEnrolment()) {
                    result++;
                }
            } else {
                result += ((CurriculumGroup) curriculumModule).getNumberOfAllEnroledCurriculumLines();
            }
        }
        return result;
    }

    /**
     * This method makes a deep search to count number of all approved
     * CurriculumLines (except NoCourseGroupCurriculumGroups)
     */
    public int getNumberOfAllApprovedCurriculumLines() {
        int result = 0;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isCurriculumLine()) {
                final CurriculumLine curriculumLine = (CurriculumLine) curriculumModule;
                if (curriculumLine.isDismissal() && curriculumLine.hasCurricularCourse()) {
                    result++;
                } else if (curriculumLine.isEnrolment() && ((Enrolment) curriculumLine).isApproved()) {
                    result++;
                }
            } else {
                result += ((CurriculumGroup) curriculumModule).getNumberOfAllApprovedCurriculumLines();
            }
        }
        return result;
    }

    final public int getNumberOfChildEnrolments(final ExecutionSemester executionSemester) {
        int result = 0;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule instanceof Enrolment) {
                final Enrolment enrolment = (Enrolment) curriculumModule;
                if (enrolment.isValid(executionSemester) && enrolment.isEnroled()) {
                    result++;
                }
            }
        }
        return result;
    }

    @Override
    public int getNumberOfAllApprovedEnrolments(final ExecutionSemester executionSemester) {
        int result = 0;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            result += curriculumModule.getNumberOfAllApprovedEnrolments(executionSemester);
        }
        return result;
    }

    @Override
    public Set<IDegreeModuleToEvaluate> getDegreeModulesToEvaluate(final ExecutionSemester executionSemester) {
        final Set<IDegreeModuleToEvaluate> result = new HashSet<IDegreeModuleToEvaluate>();
        result.add(new EnroledCurriculumModuleWrapper(this, executionSemester));

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getDegreeModulesToEvaluate(executionSemester));
        }
        return result;
    }

    @Override
    public Collection<Enrolment> getSpecialSeasonEnrolments(final ExecutionYear executionYear) {
        final Collection<Enrolment> result = new HashSet<Enrolment>();
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getSpecialSeasonEnrolments(executionYear));
        }
        return result;
    }

    @Override
    public Collection<Enrolment> getSpecialSeasonEnrolments(final ExecutionSemester executionSemester) {
        final Collection<Enrolment> result = new HashSet<Enrolment>();
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            result.addAll(curriculumModule.getSpecialSeasonEnrolments(executionSemester));
        }
        return result;
    }

    @Override
    final public void getAllDegreeModules(final Collection<DegreeModule> degreeModules) {
        degreeModules.add(getDegreeModule());
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            curriculumModule.getAllDegreeModules(degreeModules);
        }
    }

    @Override
    public ConclusionValue isConcluded(final ExecutionYear executionYear) {
        if (isToCheckCreditsLimits(executionYear)) {
            return ConclusionValue.create(checkCreditsLimits(executionYear));
        } else if (isToCheckDegreeModulesSelectionLimit(executionYear)) {
            return ConclusionValue.create(checkDegreeModulesSelectionLimit(executionYear));
        } else {
            return ConclusionValue.UNKNOWN;
        }
    }

    public void assertCorrectStructure(final Collection<CurriculumGroup> result, ExecutionYear lastApprovedYear) {
        for (final CurriculumGroup curriculumGroup : getCurriculumGroups()) {
            if (curriculumGroup.getCurriculumGroups().isEmpty() && curriculumGroup.hasUnexpectedCredits(lastApprovedYear)) {
                result.add(curriculumGroup);
            } else {
                curriculumGroup.assertCorrectStructure(result, lastApprovedYear);
            }
        }
    }

    public boolean hasUnexpectedCredits(ExecutionYear lastApprovedYear) {
        return getAprovedEctsCredits().doubleValue() != getCreditsConcluded(lastApprovedYear).doubleValue();
    }

    public boolean hasInsufficientCredits() {
        return getAprovedEctsCredits().doubleValue() < getCreditsConcluded().doubleValue();
    }

    private boolean isToCheckDegreeModulesSelectionLimit(ExecutionYear executionYear) {
        return getMostRecentActiveCurricularRule(CurricularRuleType.DEGREE_MODULES_SELECTION_LIMIT, executionYear) != null;
    }

    private boolean isToCheckCreditsLimits(ExecutionYear executionYear) {
        return getMostRecentActiveCurricularRule(CurricularRuleType.CREDITS_LIMIT, executionYear) != null;
    }

    @SuppressWarnings("unchecked")
    private boolean checkCreditsLimits(ExecutionYear executionYear) {
        final CreditsLimit creditsLimit =
                (CreditsLimit) getMostRecentActiveCurricularRule(CurricularRuleType.CREDITS_LIMIT, executionYear);

        if (creditsLimit == null) {
            return false;
        } else {
            Double creditsConcluded = 0d;
            for (CurriculumModule curriculumModule : getCurriculumModulesSet()) {
                if (curriculumModule.isConcluded(executionYear).isValid()) {
                    creditsConcluded += curriculumModule.getCreditsConcluded(executionYear);
                }
            }

            return creditsConcluded >= creditsLimit.getMinimumCredits();
        }
    }

    @SuppressWarnings("unchecked")
    private boolean checkDegreeModulesSelectionLimit(ExecutionYear executionYear) {
        final DegreeModulesSelectionLimit degreeModulesSelectionLimit =
                (DegreeModulesSelectionLimit) getMostRecentActiveCurricularRule(
                        CurricularRuleType.DEGREE_MODULES_SELECTION_LIMIT, executionYear);

        if (degreeModulesSelectionLimit == null) {
            return false;
        } else {
            int modulesConcluded = 0;
            for (CurriculumModule curriculumModule : getCurriculumModulesSet()) {
                if (curriculumModule.isConcluded(executionYear).value()) {
                    modulesConcluded++;
                }
            }

            return modulesConcluded >= degreeModulesSelectionLimit.getMinimumLimit();
        }
    }

    @Override
    public boolean hasConcluded(final DegreeModule degreeModule, final ExecutionYear executionYear) {
        if (getDegreeModule() == degreeModule) {
            return isConcluded(executionYear).value();
        }

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.hasConcluded(degreeModule, executionYear)) {
                return true;
            }
        }

        return false;

    }

    @Override
    public YearMonthDay calculateConclusionDate() {
        final Collection<CurriculumModule> curriculumModules = new HashSet<CurriculumModule>(getCurriculumModulesSet());
        YearMonthDay result = null;
        for (final CurriculumModule curriculumModule : curriculumModules) {
            if (curriculumModule.isConcluded(getApprovedCurriculumLinesLastExecutionYear()).isValid()
                    && curriculumModule.hasAnyApprovedCurriculumLines()) {
                final YearMonthDay curriculumModuleConclusionDate = curriculumModule.calculateConclusionDate();
                if (curriculumModuleConclusionDate != null && (result == null || curriculumModuleConclusionDate.isAfter(result))) {
                    result = curriculumModuleConclusionDate;
                }
            }
        }

        return result;
    }

    public void assertConclusionDate(final Collection<CurriculumModule> result) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isConcluded(getApprovedCurriculumLinesLastExecutionYear()).isValid()
                    && curriculumModule.hasAnyApprovedCurriculumLines()) {
                final YearMonthDay curriculumModuleConclusionDate = curriculumModule.calculateConclusionDate();
                if (curriculumModuleConclusionDate == null) {
                    result.add(curriculumModule);
                }
            }
        }
    }

    @Override
    public Curriculum getCurriculum(final DateTime when, final ExecutionYear executionYear) {
        final Curriculum curriculum = Curriculum.createEmpty(this, executionYear);
        if (!wasCreated(when)) {
            return curriculum;
        }

        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            curriculum.add(curriculumModule.getCurriculum(when, executionYear));
        }

        return curriculum;
    }

    @Override
    public boolean isPropaedeutic() {
        return getCurriculumGroup() != null && getCurriculumGroup().isPropaedeutic();
    }

    public boolean isExtraCurriculum() {
        return false;
    }

    public boolean isStandalone() {
        return false;
    }

    public boolean canAdd(final CurriculumLine curriculumLine) {
        if (!curriculumLine.hasCurricularCourse() || !curriculumLine.isBolonhaDegree()) {
            return true;
        }

        if (curriculumLine.isEnrolment()) {
            if (curriculumLine instanceof OptionalEnrolment) {
                return getDegreeModule().hasDegreeModuleOnChilds(
                        ((OptionalEnrolment) curriculumLine).getOptionalCurricularCourse());
            }
        }

        return getDegreeModule().hasDegreeModuleOnChilds(curriculumLine.getCurricularCourse());
    }

    public Collection<CurriculumGroup> getCurricularCoursePossibleGroups(final CurricularCourse curricularCourse) {
        Collection<CurriculumGroup> result = new HashSet<CurriculumGroup>();
        if (getDegreeModule().hasDegreeModuleOnChilds(curricularCourse)) {
            result.add(this);
        }

        for (CurriculumGroup curriculumGroup : this.getCurriculumGroups()) {
            result.addAll(curriculumGroup.getCurricularCoursePossibleGroups(curricularCourse));
        }

        return result;
    }

    public Collection<CurriculumGroup> getCurricularCoursePossibleGroupsWithoutNoCourseGroupCurriculumGroups(
            final CurricularCourse curricularCourse) {
        Collection<CurriculumGroup> result = new HashSet<CurriculumGroup>();
        if (getDegreeModule().hasDegreeModuleOnChilds(curricularCourse)) {
            result.add(this);
        }

        for (CurriculumGroup curriculumGroup : this.getCurriculumGroups()) {
            result.addAll(curriculumGroup.getCurricularCoursePossibleGroupsWithoutNoCourseGroupCurriculumGroups(curricularCourse));
        }

        return result;
    }

    public Collection<NoCourseGroupCurriculumGroup> getNoCourseGroupCurriculumGroups() {
        Collection<NoCourseGroupCurriculumGroup> res = new HashSet<NoCourseGroupCurriculumGroup>();
        for (CurriculumGroup curriculumGroup : getCurriculumGroups()) {
            res.addAll(curriculumGroup.getNoCourseGroupCurriculumGroups());
        }
        return res;
    }

    public int getNoCourseGroupCurriculumGroupsCount() {
        return getNoCourseGroupCurriculumGroups().size();
    }

    public boolean hasChildDegreeModule(final DegreeModule degreeModule) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.getDegreeModule() == degreeModule) {
                return true;
            }
        }

        return false;
    }

    public CurriculumModule getChildCurriculumModule(final DegreeModule degreeModule) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.getDegreeModule() == degreeModule) {
                return curriculumModule;
            }
        }
        return null;
    }

    @Override
    public boolean hasEnrolment(ExecutionYear executionYear) {
        final AndPredicate<CurriculumModule> andPredicate = new AndPredicate<CurriculumModule>();
        andPredicate.add(new CurriculumModulePredicateByType(Enrolment.class));
        andPredicate.add(new CurriculumModulePredicateByExecutionYear(executionYear));

        return hasAnyCurriculumModules(andPredicate);
    }

    @Override
    public boolean hasEnrolment(ExecutionSemester executionSemester) {
        final AndPredicate<CurriculumModule> andPredicate = new AndPredicate<CurriculumModule>();
        andPredicate.add(new CurriculumModulePredicateByType(Enrolment.class));
        andPredicate.add(new CurriculumModulePredicateByExecutionSemester(executionSemester));

        return hasAnyCurriculumModules(andPredicate);
    }

    @Override
    public boolean isEnroledInSpecialSeason(final ExecutionSemester executionSemester) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isEnroledInSpecialSeason(executionSemester)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean isEnroledInSpecialSeason(final ExecutionYear executionYear) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isEnroledInSpecialSeason(executionYear)) {
                return true;
            }
        }
        return false;
    }

    public Set<Enrolment> getEnrolmentsBy(final ExecutionYear executionYear) {
        final Set<Enrolment> result = new HashSet<Enrolment>();
        for (final Enrolment enrolment : getEnrolmentsSet()) {
            if (enrolment.getExecutionYear() == executionYear) {
                result.add(enrolment);
            }
        }

        return result;
    }

    public Set<Enrolment> getEnrolmentsBy(final ExecutionSemester executionSemester) {
        final Set<Enrolment> result = new HashSet<Enrolment>();
        for (final Enrolment enrolment : getEnrolmentsSet()) {
            if (enrolment.getExecutionPeriod() == executionSemester) {
                result.add(enrolment);
            }
        }

        return result;
    }

    public boolean hasEnrolmentInCurricularCourseBefore(final CurricularCourse curricularCourse,
            final ExecutionSemester executionSemester) {
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isEnrolment()) {
                final Enrolment enrolment = (Enrolment) curriculumModule;
                if (!enrolment.isAnnulled() && enrolment.getExecutionPeriod().isBefore(executionSemester)
                        && enrolment.getCurricularCourse() == curricularCourse) {
                    return true;
                }
            } else if (curriculumModule instanceof CurriculumGroup) {
                final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
                if (curriculumGroup.hasEnrolmentInCurricularCourseBefore(curricularCourse, executionSemester)) {
                    return true;
                }
            }
        }
        return false;
    }

    public int calculateStudentAcumulatedEnrollments(CurricularCourse curricularCourse, ExecutionSemester executionSemester) {
        int result = 0;
        for (final CurriculumModule curriculumModule : getCurriculumModulesSet()) {
            if (curriculumModule.isEnrolment()) {
                final Enrolment enrolment = (Enrolment) curriculumModule;
                if (!enrolment.isAnnulled()
                        && enrolment.getExecutionPeriod().isBefore(executionSemester)
                        && enrolment.getCurricularCourse().getCurricularCourseUniqueKeyForEnrollment()
                                .equalsIgnoreCase(curricularCourse.getCurricularCourseUniqueKeyForEnrollment())) {
                    result++;
                }
            } else if (curriculumModule instanceof CurriculumGroup) {
                final CurriculumGroup curriculumGroup = (CurriculumGroup) curriculumModule;
                result += curriculumGroup.calculateStudentAcumulatedEnrollments(curricularCourse, executionSemester);
            }
        }
        return result;
    }

}
TOP

Related Classes of org.fenixedu.academic.domain.studentCurriculum.CurriculumGroup

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.