Package org.fenixedu.academic.domain.degreeStructure

Source Code of org.fenixedu.academic.domain.degreeStructure.CourseGroup

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

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.comparators.ReverseComparator;
import org.fenixedu.academic.domain.CurricularCourse;
import org.fenixedu.academic.domain.DegreeCurricularPlan;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.ExecutionYear;
import org.fenixedu.academic.domain.curricularPeriod.CurricularPeriod;
import org.fenixedu.academic.domain.curricularRules.CreditsLimit;
import org.fenixedu.academic.domain.curricularRules.CurricularRule;
import org.fenixedu.academic.domain.curricularRules.CurricularRuleType;
import org.fenixedu.academic.domain.curricularRules.DegreeModulesSelectionLimit;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.predicate.CourseGroupPredicates;
import org.fenixedu.academic.util.StringFormatter;
import org.fenixedu.bennu.core.domain.Bennu;

import com.google.common.base.Strings;

public class CourseGroup extends CourseGroup_Base {

    static public List<CourseGroup> readCourseGroups() {
        final List<CourseGroup> result = new ArrayList<CourseGroup>();
        for (final DegreeModule degreeModule : Bennu.getInstance().getDegreeModulesSet()) {
            if (degreeModule instanceof CourseGroup) {
                result.add((CourseGroup) degreeModule);
            }
        }
        return result;
    }

    public CourseGroup() {
        super();
    }

    protected CourseGroup(final String name, final String nameEn) {
        this();
        init(name, nameEn);
    }

    protected void init(final String name, final String nameEn) {
        super.setName(StringFormatter.prettyPrint(name));
        super.setNameEn(StringFormatter.prettyPrint(nameEn));
    }

    public CourseGroup(final CourseGroup parentCourseGroup, final String name, final String nameEn,
            final ExecutionSemester begin, final ExecutionSemester end) {
        init(parentCourseGroup, name, nameEn, begin, end);
    }

    protected void init(CourseGroup parentCourseGroup, String name, String nameEn, ExecutionSemester begin, ExecutionSemester end) {
        init(name, nameEn);
        if (parentCourseGroup == null) {
            throw new DomainException("error.degreeStructure.CourseGroup.parentCourseGroup.cannot.be.null");
        }
        parentCourseGroup.checkDuplicateChildNames(name, nameEn);
        new Context(parentCourseGroup, this, null, begin, end);
    }

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

    public void edit(String name, String nameEn, Context context, ExecutionSemester beginExecutionPeriod,
            ExecutionSemester endExecutionPeriod) {
        // override, assure that root's name equals degree curricular plan name
        if (this.isRoot()) {
            setName(getParentDegreeCurricularPlan().getName());
            setNameEn(getParentDegreeCurricularPlan().getName());
        } else {
            setName(StringFormatter.prettyPrint(name));
            setNameEn(StringFormatter.prettyPrint(nameEn));
        }

        this.checkDuplicateBrotherNames(name, nameEn);

        if (!this.isRoot() && context != null) {
            context.edit(beginExecutionPeriod, endExecutionPeriod);
        }
    }

    @Override
    public Boolean getCanBeDeleted() {
        return super.getCanBeDeleted() && getChildContextsSet().isEmpty() && getOldCourseGroupChangeRequestsSet().isEmpty()
                && getNewCourseGroupChangeRequestsSet().isEmpty();
    }

    @Override
    public void delete() {
        if (getCanBeDeleted()) {
            super.delete();
            for (; !getParticipatingContextCurricularRulesSet().isEmpty(); getParticipatingContextCurricularRulesSet().iterator()
                    .next().delete()) {
                ;
            }
            setRootDomainObject(null);
            super.deleteDomainObject();
        } else {
            throw new DomainException("courseGroup.notEmptyCourseGroupContexts");
        }
    }

    @Override
    public void print(StringBuilder dcp, String tabs, Context previousContext) {
        String tab = tabs + "\t";
        dcp.append(tab);
        dcp.append("[CG ").append(this.getExternalId()).append("] ").append(this.getName()).append("\n");

        for (Context context : this.getSortedChildContextsWithCurricularCourses()) {
            context.getChildDegreeModule().print(dcp, tab, context);
        }
        for (Context context : this.getSortedChildContextsWithCourseGroups()) {
            context.getChildDegreeModule().print(dcp, tab, context);
        }
    }

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

    @Override
    public DegreeCurricularPlan getParentDegreeCurricularPlan() {
        return !getParentContextsSet().isEmpty() ? getParentContextsSet().iterator().next().getParentCourseGroup()
                .getParentDegreeCurricularPlan() : null;
    }

    public List<Context> getChildContexts(Class<? extends DegreeModule> clazz) {
        return getValidChildContexts(clazz, (ExecutionYear) null);
    }

    public List<Context> getValidChildContexts(final ExecutionYear executionYear) {
        return getValidChildContexts(null, executionYear);
    }

    public List<Context> getValidChildContexts(final ExecutionSemester executionSemester) {
        return getValidChildContexts(null, executionSemester);
    }

    // Valid means that is open to execution year, and if is
    // CurricularCourse
    // the context must have same semester of any ExecutionPeriod of
    // ExecutionYear
    public List<Context> getValidChildContexts(final Class<? extends DegreeModule> clazz, final ExecutionYear executionYear) {
        final List<Context> result = new ArrayList<Context>();
        for (final Context context : this.getChildContextsSet()) {
            if (hasClass(clazz, context.getChildDegreeModule()) && ((executionYear == null || context.isValid(executionYear)))) {
                result.add(context);
            }
        }
        return result;
    }

    // Valid means that is open to execution period, and if is
    // CurricularCourse
    // the context must have same semester than executionPeriod
    public List<Context> getValidChildContexts(final Class<? extends DegreeModule> clazz,
            final ExecutionSemester executionSemester) {
        final List<Context> result = new ArrayList<Context>();
        for (Context context : this.getChildContextsSet()) {
            if (hasClass(clazz, context.getChildDegreeModule())
                    && ((executionSemester == null || context.isValid(executionSemester)))) {
                result.add(context);
            }
        }

        return result;
    }

    public List<Context> getSortedOpenChildContextsWithCurricularCourses(final ExecutionYear executionYear) {
        final List<Context> result = getOpenChildContexts(CurricularCourse.class, executionYear);
        Collections.sort(result);
        return result;
    }

    public List<Context> getSortedOpenChildContextsWithCourseGroups(final ExecutionYear executionYear) {
        final List<Context> result = this.getOpenChildContexts(CourseGroup.class, executionYear);
        Collections.sort(result);
        return result;
    }

    public List<Context> getSortedOpenChildContextsWithCourseGroups(final ExecutionSemester executionSemester) {
        final List<Context> result = this.getOpenChildContexts(CourseGroup.class, executionSemester);
        Collections.sort(result);
        return result;
    }

    public List<Context> getOpenChildContexts(final Class<? extends DegreeModule> clazz, final ExecutionSemester executionSemester) {
        final List<Context> result = new ArrayList<Context>();
        for (final Context context : getChildContextsSet()) {
            if (hasClass(clazz, context.getChildDegreeModule())
                    && ((executionSemester == null || context.isOpen(executionSemester)))) {
                result.add(context);
            }
        }
        return result;
    }

    public List<Context> getOpenChildContexts(final Class<? extends DegreeModule> clazz, final ExecutionYear executionYear) {
        final List<Context> result = new ArrayList<Context>();
        for (final Context context : getChildContextsSet()) {
            if (hasClass(clazz, context.getChildDegreeModule()) && ((executionYear == null || context.isOpen(executionYear)))) {
                result.add(context);
            }
        }
        return result;
    }

    private boolean hasClass(final Class<? extends DegreeModule> clazz, final DegreeModule degreeModule) {
        return clazz == null || clazz.isAssignableFrom(degreeModule.getClass());
    }

    public List<Context> getSortedChildContextsWithCurricularCourses() {
        List<Context> result = this.getChildContexts(CurricularCourse.class);
        Collections.sort(result);
        return result;
    }

    public List<Context> getSortedChildContextsWithCurricularCoursesByExecutionYear(ExecutionYear executionYear) {
        List<Context> result = this.getValidChildContexts(CurricularCourse.class, executionYear);
        Collections.sort(result);
        return result;
    }

    public List<Context> getSortedChildContextsWithCourseGroups() {
        List<Context> result = new ArrayList<Context>(this.getChildContexts(CourseGroup.class));
        Collections.sort(result);
        return result;
    }

    public List<Context> getSortedChildContextsWithCourseGroupsByExecutionYear(ExecutionYear executionYear) {
        List<Context> result = this.getValidChildContexts(CourseGroup.class, executionYear);
        Collections.sort(result);
        return result;
    }

    @Override
    public List<CurricularRule> getParticipatingCurricularRules() {
        final List<CurricularRule> result = new ArrayList<CurricularRule>();
        result.addAll(super.getParticipatingCurricularRules());
        result.addAll(getParticipatingContextCurricularRulesSet());
        return result;
    }

    @Override
    public void setName(String name) {
        check(this, CourseGroupPredicates.curricularPlanMemberWritePredicate);
        super.setName(name);
    }

    @Override
    public void setNameEn(String nameEn) {
        check(this, CourseGroupPredicates.curricularPlanMemberWritePredicate);
        super.setNameEn(nameEn);
    }

    public void checkDuplicateChildNames(final String name, final String nameEn) {
        String normalizedName = StringFormatter.normalize(name);
        String normalizedNameEn = StringFormatter.normalize(nameEn);
        if (!verifyNames(normalizedName, normalizedNameEn)) {
            throw new DomainException("error.existingCourseGroupWithSameName");
        }
    }

    public void checkDuplicateBrotherNames(final String name, final String nameEn) {
        String normalizedName = StringFormatter.normalize(name);
        String normalizedNameEn = StringFormatter.normalize(nameEn);
        for (Context parentContext : getParentContextsSet()) {
            CourseGroup parentCourseGroup = parentContext.getParentCourseGroup();
            if (!parentCourseGroup.verifyNames(normalizedName, normalizedNameEn, this)) {
                throw new DomainException("error.existingCourseGroupWithSameName");
            }
        }
    }

    private boolean verifyNames(String normalizedName, String normalizedNameEn) {
        return verifyNames(normalizedName, normalizedNameEn, this);
    }

    private boolean verifyNames(String normalizedName, String normalizedNameEn, DegreeModule excludedModule) {
        for (Context context : getChildContextsSet()) {
            DegreeModule degreeModule = context.getChildDegreeModule();
            if (degreeModule != excludedModule) {
                if (!Strings.isNullOrEmpty(degreeModule.getName())
                        && StringFormatter.normalize(degreeModule.getName()).equals(normalizedName)) {
                    return false;
                }
                if (!Strings.isNullOrEmpty(degreeModule.getNameEn())
                        && StringFormatter.normalize(degreeModule.getNameEn()).equals(normalizedNameEn)) {
                    return false;
                }
            }
        }
        return true;
    }

    public void orderChild(Context contextToOrder, int position) {
        List<Context> newSort = null;
        if (contextToOrder.getChildDegreeModule() instanceof CurricularCourse) {
            newSort = this.getSortedChildContextsWithCurricularCourses();
        } else {
            newSort = this.getSortedChildContextsWithCourseGroups();
        }

        if (newSort.size() <= 1 || position < 0 || position > newSort.size()) {
            return;
        }

        newSort.remove(contextToOrder);
        newSort.add(position, contextToOrder);

        for (int newOrder = 0; newOrder < newSort.size(); newOrder++) {
            Context context = newSort.get(newOrder);

            if (context == contextToOrder && newOrder != position) {
                throw new DomainException("wrong.order.algorithm");
            }
            context.setChildOrder(newOrder);
        }
    }

    public Set<DegreeModule> collectAllChildDegreeModules(final Class<? extends DegreeModule> clazz,
            final ExecutionYear executionYear) {
        final Set<DegreeModule> result = new HashSet<DegreeModule>();
        for (final Context context : this.getValidChildContexts(executionYear)) {
            final DegreeModule degreeModule = context.getChildDegreeModule();
            if (clazz.isAssignableFrom(degreeModule.getClass())) {
                result.add(degreeModule);
            }
            if (!degreeModule.isLeaf()) {
                final CourseGroup courseGroup = (CourseGroup) degreeModule;
                result.addAll(courseGroup.collectAllChildDegreeModules(clazz, executionYear));
            }
        }
        return result;
    }

    public Set<DegreeModule> collectAllChildDegreeModules(final Class<? extends DegreeModule> clazz,
            final ExecutionSemester executionSemester) {
        final Set<DegreeModule> result = new HashSet<DegreeModule>();
        for (final Context context : getValidChildContexts(executionSemester)) {
            final DegreeModule degreeModule = context.getChildDegreeModule();
            if (clazz.isAssignableFrom(degreeModule.getClass())) {
                result.add(degreeModule);
            }
            if (!degreeModule.isLeaf()) {
                final CourseGroup courseGroup = (CourseGroup) degreeModule;
                result.addAll(courseGroup.collectAllChildDegreeModules(clazz, executionSemester));
            }
        }
        return result;
    }

    public void collectChildDegreeModulesIncludingFullPath(Class<? extends DegreeModule> clazz, List<List<DegreeModule>> result,
            List<DegreeModule> previousDegreeModulesPath, ExecutionYear executionYear) {
        final List<DegreeModule> currentDegreeModulesPath = previousDegreeModulesPath;
        for (final Context context : this.getValidChildContexts(executionYear)) {
            List<DegreeModule> newDegreeModulesPath = null;
            if (clazz.isAssignableFrom(context.getChildDegreeModule().getClass())) {
                newDegreeModulesPath =
                        initNewDegreeModulesPath(newDegreeModulesPath, currentDegreeModulesPath, context.getChildDegreeModule());
                result.add(newDegreeModulesPath);
            }
            if (!context.getChildDegreeModule().isLeaf()) {
                newDegreeModulesPath =
                        initNewDegreeModulesPath(newDegreeModulesPath, currentDegreeModulesPath, context.getChildDegreeModule());
                ((CourseGroup) context.getChildDegreeModule()).collectChildDegreeModulesIncludingFullPath(clazz, result,
                        newDegreeModulesPath, executionYear);
            }
        }
    }

    private List<DegreeModule> initNewDegreeModulesPath(List<DegreeModule> newDegreeModulesPath,
            final List<DegreeModule> currentDegreeModulesPath, final DegreeModule degreeModule) {
        if (newDegreeModulesPath == null) {
            newDegreeModulesPath = new ArrayList<DegreeModule>(currentDegreeModulesPath);
            newDegreeModulesPath.add(degreeModule);
        }
        return newDegreeModulesPath;
    }

    public Collection<CourseGroup> getNotOptionalChildCourseGroups(final ExecutionSemester executionSemester) {

        final Collection<DegreeModule> degreeModules = getDegreeModulesByExecutionPeriod(executionSemester);
        final Collection<CurricularRule> curricularRules = getCurricularRulesByExecutionPeriod(executionSemester);
        final DegreeModulesSelectionLimit degreeModulesSelectionLimit = getDegreeModulesSelectionLimitRule(curricularRules);

        if (degreeModulesSelectionLimit != null) {

            if (degreeModulesSelectionLimit.getMinimumLimit().equals(degreeModulesSelectionLimit.getMaximumLimit())
                    && degreeModulesSelectionLimit.getMaximumLimit().equals(degreeModules.size())) {

                return filterCourseGroups(degreeModules);

            } else {
                return Collections.EMPTY_LIST;
            }
        }
        return filterCourseGroups(degreeModules);
    }

    private Collection<CourseGroup> filterCourseGroups(final Collection<DegreeModule> degreeModules) {
        final Collection<CourseGroup> result = new HashSet<CourseGroup>();
        for (final DegreeModule degreeModule : degreeModules) {
            if (!degreeModule.isLeaf()) {
                result.add((CourseGroup) degreeModule);
            }
        }
        return result;
    }

    private DegreeModulesSelectionLimit getDegreeModulesSelectionLimitRule(final Collection<CurricularRule> curricularRules) {
        for (final CurricularRule curricularRule : curricularRules) {
            if (curricularRule.getCurricularRuleType() == CurricularRuleType.DEGREE_MODULES_SELECTION_LIMIT) {
                return (DegreeModulesSelectionLimit) curricularRule;
            }
        }
        return null;
    }

    private Collection<CurricularRule> getCurricularRulesByExecutionPeriod(final ExecutionSemester executionSemester) {
        final Collection<CurricularRule> result = new HashSet<CurricularRule>();
        for (final CurricularRule curricularRule : this.getCurricularRulesSet()) {
            if (curricularRule.isValid(executionSemester)) {
                result.add(curricularRule);
            }
        }
        return result;
    }

    private Collection<DegreeModule> getDegreeModulesByExecutionPeriod(final ExecutionSemester executionSemester) {
        final Collection<DegreeModule> result = new HashSet<DegreeModule>();
        for (final Context context : this.getChildContextsSet()) {
            if (context.isValid(executionSemester)) {
                result.add(context.getChildDegreeModule());
            }
        }
        return result;
    }

    public boolean validate(CurricularCourse curricularCourse) {
        for (final Context context : this.getChildContextsSet()) {
            if (context.getChildDegreeModule() instanceof CurricularCourse) {
                CurricularCourse childCurricularCourse = (CurricularCourse) context.getChildDegreeModule();
                if (childCurricularCourse.isEquivalent(curricularCourse)) {
                    return true;
                }
            }
        }
        return false;
    }

    public Collection<Context> getContextsWithCurricularCourseByCurricularPeriod(final CurricularPeriod curricularPeriod,
            final ExecutionSemester executionSemester) {

        final Collection<Context> result = new HashSet<Context>();

        for (final Context context : this.getChildContextsSet()) {

            if (context.getChildDegreeModule().isLeaf() && context.getCurricularPeriod() != null
                    && context.getCurricularPeriod().equals(curricularPeriod) && context.isValid(executionSemester)) {

                result.add(context);
            }
        }
        return result;
    }

    public Set<DegreeModule> getOpenChildDegreeModulesByExecutionPeriod(final ExecutionSemester executionSemester) {
        final Set<DegreeModule> result = new HashSet<DegreeModule>();
        for (final Context context : getChildContextsSet()) {
            if (context.isOpen(executionSemester)) {
                result.add(context.getChildDegreeModule());
            }
        }
        return result;
    }

    @Override
    public Set<CourseGroup> getParentCourseGroups() {
        final Set<CourseGroup> result = new HashSet<CourseGroup>();
        for (final Context context : getParentContextsSet()) {
            result.add(context.getParentCourseGroup());
        }
        return result;
    }

    @Override
    public Double getMaxEctsCredits(final ExecutionSemester executionSemester) {
        final List<CreditsLimit> creditsLimitRules =
                (List<CreditsLimit>) getCurricularRules(CurricularRuleType.CREDITS_LIMIT, executionSemester);
        if (!creditsLimitRules.isEmpty()) {
            for (final CreditsLimit creditsLimit : creditsLimitRules) {
                if (getParentCourseGroups().contains(creditsLimit.getContextCourseGroup())) {
                    return creditsLimit.getMaximumCredits();
                }
            }
            return creditsLimitRules.iterator().next().getMaximumCredits();
        }

        final Collection<DegreeModule> modulesByExecutionPeriod = getOpenChildDegreeModulesByExecutionPeriod(executionSemester);
        final DegreeModulesSelectionLimit modulesSelectionLimit = getDegreeModulesSelectionLimitRule(executionSemester);
        if (modulesSelectionLimit != null) {
            return countMaxEctsCredits(modulesByExecutionPeriod, executionSemester, modulesSelectionLimit.getMaximumLimit());
        }

        return countMaxEctsCredits(modulesByExecutionPeriod, executionSemester, modulesByExecutionPeriod.size());
    }

    private Double countMaxEctsCredits(final Collection<DegreeModule> modulesByExecutionPeriod,
            final ExecutionSemester executionSemester, final Integer maximumLimit) {

        final List<Double> ectsCredits = new ArrayList<Double>();
        for (final DegreeModule degreeModule : modulesByExecutionPeriod) {
            ectsCredits.add(degreeModule.getMaxEctsCredits(executionSemester));
        }
        Collections.sort(ectsCredits, new ReverseComparator());
        return sumEctsCredits(ectsCredits, maximumLimit.intValue());
    }

    @Override
    public Double getMinEctsCredits(final ExecutionSemester executionSemester) {
        final List<CreditsLimit> creditsLimitRules =
                (List<CreditsLimit>) getCurricularRules(CurricularRuleType.CREDITS_LIMIT, executionSemester);
        if (!creditsLimitRules.isEmpty()) {
            for (final CreditsLimit creditsLimit : creditsLimitRules) {
                if (getParentCourseGroups().contains(creditsLimit.getContextCourseGroup())) {
                    return creditsLimit.getMinimumCredits();
                }
            }
            return creditsLimitRules.iterator().next().getMinimumCredits();
        }

        final Collection<DegreeModule> modulesByExecutionPeriod = getOpenChildDegreeModulesByExecutionPeriod(executionSemester);
        final DegreeModulesSelectionLimit modulesSelectionLimit = getDegreeModulesSelectionLimitRule(executionSemester);
        if (modulesSelectionLimit != null) {
            return countMinEctsCredits(modulesByExecutionPeriod, executionSemester, modulesSelectionLimit.getMinimumLimit());
        }

        return countMinEctsCredits(modulesByExecutionPeriod, executionSemester, modulesByExecutionPeriod.size());
    }

    private Double countMinEctsCredits(final Collection<DegreeModule> modulesByExecutionPeriod,
            final ExecutionSemester executionSemester, final Integer minimumLimit) {

        final List<Double> ectsCredits = new ArrayList<Double>();
        for (final DegreeModule degreeModule : modulesByExecutionPeriod) {
            ectsCredits.add(degreeModule.getMinEctsCredits(executionSemester));
        }
        Collections.sort(ectsCredits);
        return sumEctsCredits(ectsCredits, minimumLimit.intValue());
    }

    private Double sumEctsCredits(final List<Double> ectsCredits, int limit) {
        double result = 0d;
        final Iterator<Double> ectsCreditsIter = ectsCredits.iterator();
        for (; ectsCreditsIter.hasNext() && limit > 0; limit--) {
            result += ectsCreditsIter.next().doubleValue();
        }
        return Double.valueOf(result);
    }

    @Override
    public boolean hasDegreeModule(final DegreeModule degreeModule) {
        if (super.hasDegreeModule(degreeModule)) {
            return true;
        }
        for (final Context context : getChildContextsSet()) {
            if (context.getChildDegreeModule().hasDegreeModule(degreeModule)) {
                return true;
            }
        }
        return false;
    }

    public Context addCurricularCourse(final CurricularCourse curricularCourse, final CurricularPeriod curricularPeriod,
            final ExecutionSemester begin, final ExecutionSemester end) {
        return addContext(curricularCourse, curricularPeriod, begin, end);
    }

    public Context addContext(final DegreeModule degreeModule, final CurricularPeriod curricularPeriod,
            final ExecutionSemester begin, final ExecutionSemester end) {

        if (!allowChildWith(begin)) {
            throw new DomainException("degreeModule.cannot.add.context.with.begin.execution.period", getName(), begin.getName(),
                    begin.getExecutionYear().getYear());
        }
        return new Context(this, degreeModule, curricularPeriod, begin, end);
    }

    @Override
    public void getAllDegreeModules(final Collection<DegreeModule> degreeModules) {
        degreeModules.add(this);
        for (Context context : getChildContextsSet()) {
            context.getAllDegreeModules(degreeModules);
        }
    }

    public void getAllCoursesGroupse(final Set<CourseGroup> courseGroups) {
        for (final Context context : getChildContextsSet()) {
            context.addAllCourseGroups(courseGroups);
        }
    }

    public boolean allowChildWith(final ExecutionSemester executionSemester) {
        return getMinimumExecutionPeriod().isBeforeOrEquals(executionSemester);
    }

    public Set<Context> getChildContextsSortedByDegreeModuleName() {
        final Set<Context> contexts = new TreeSet<Context>(Context.COMPARATOR_BY_DEGREE_MODULE_NAME);
        contexts.addAll(getChildContextsSet());
        return contexts;
    }

    public Set<DegreeModule> getChildDegreeModules() {
        final Set<DegreeModule> result = new HashSet<DegreeModule>();
        for (final Context context : getChildContextsSet()) {
            result.add(context.getChildDegreeModule());
        }
        return result;
    }

    public Set<DegreeModule> getChildDegreeModulesValidOn(final ExecutionSemester executionSemester) {
        final Set<DegreeModule> result = new HashSet<DegreeModule>();
        for (final Context context : getValidChildContexts(executionSemester)) {
            result.add(context.getChildDegreeModule());
        }

        return result;
    }

    public Set<DegreeModule> getChildDegreeModulesValidOn(final ExecutionYear executionYear) {
        final Set<DegreeModule> result = new HashSet<DegreeModule>();
        for (final Context context : getValidChildContexts(executionYear)) {
            result.add(context.getChildDegreeModule());
        }

        return result;
    }

    public Set<Context> getActiveChildContexts() {
        final Set<Context> result = new HashSet<Context>();

        for (final Context context : getChildContextsSet()) {
            if (context.isOpen()) {
                result.add(context);
            }
        }

        return result;
    }

    public Set<Context> getActiveChildContextsWithMax(final ExecutionSemester executionSemester) {
        final Map<DegreeModule, Context> maxContextsByDegreeModule = new HashMap<DegreeModule, Context>();

        for (final Context context : getActiveChildContexts()) {
            if (maxContextsByDegreeModule.containsKey(context.getChildDegreeModule())) {
                final Context existingContext = maxContextsByDegreeModule.get(context.getChildDegreeModule());
                if (existingContext.getCurricularPeriod().getChildOrder().intValue() != executionSemester.getSemester()
                        .intValue()
                        && context.getCurricularPeriod().getChildOrder().intValue() == executionSemester.getSemester().intValue()) {
                    maxContextsByDegreeModule.put(context.getChildDegreeModule(), context);
                }

            } else {
                maxContextsByDegreeModule.put(context.getChildDegreeModule(), context);
            }
        }

        return new HashSet<Context>(maxContextsByDegreeModule.values());
    }

    public Map<CurricularPeriod, Set<Context>> getActiveChildCurricularContextsWithMaxByCurricularPeriod(
            final ExecutionSemester executionSemester) {
        final Map<CurricularPeriod, Set<Context>> result = new HashMap<CurricularPeriod, Set<Context>>();

        for (final Context context : getActiveChildContextsWithMax(executionSemester)) {
            if (context.getChildDegreeModule().isCurricularCourse()) {
                if (!result.containsKey(context.getCurricularPeriod())) {
                    result.put(context.getCurricularPeriod(), new HashSet<Context>());
                }

                result.get(context.getCurricularPeriod()).add(context);
            }
        }

        return result;
    }

    public Set<CurricularCourse> getChildCurricularCoursesValidOn(final ExecutionSemester executionSemester) {
        final Set<CurricularCourse> result = new HashSet<CurricularCourse>();

        for (final Context context : getValidChildContexts(executionSemester)) {
            if (context.getChildDegreeModule().isCurricularCourse()) {
                result.add((CurricularCourse) context.getChildDegreeModule());
            }
        }

        return result;
    }

    public List<Context> getChildContextsForCurricularCourses(final ExecutionSemester executionSemester) {
        final List<Context> result = new ArrayList<Context>();
        for (final Context context : getChildContexts(CurricularCourse.class)) {
            if (context.isValid(executionSemester)) {
                result.add(context);
            }
        }

        return result;
    }

    public Set<Context> getActiveChildContextsWithMaxCurricularPeriodForCurricularCourses(
            final ExecutionSemester executionSemester) {
        final Set<Context> result = new HashSet<Context>();
        for (final Context context : getActiveChildContextsWithMax(executionSemester)) {
            if (context.getChildDegreeModule().isCurricularCourse()) {
                result.add(context);
            }
        }

        return result;
    }

    public boolean hasDegreeModuleOnChilds(final DegreeModule degreeModuleToSearch) {
        for (final Context context : getChildContextsSet()) {
            if (context.getChildDegreeModule() == degreeModuleToSearch) {
                return true;
            }
        }
        return false;
    }

    public boolean hasAnyChildContextWithCurricularCourse() {
        for (final Context context : getChildContextsSet()) {
            if (context.getChildDegreeModule().isCurricularCourse()) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean isCourseGroup() {
        return true;
    }

    @Override
    public Set<CurricularCourse> getAllCurricularCourses(final ExecutionSemester executionSemester) {
        final Set<CurricularCourse> result = new HashSet<CurricularCourse>();
        for (final Context context : getChildContextsSet()) {
            if (executionSemester == null || context.isOpen(executionSemester)) {
                result.addAll(context.getChildDegreeModule().getAllCurricularCourses(executionSemester));
            }
        }
        return result;
    }

    @Override
    public Set<CurricularCourse> getAllCurricularCourses() {
        return getAllCurricularCourses(null);
    }

    public Set<CurricularCourse> getAllOpenCurricularCourses() {
        return getAllCurricularCourses(ExecutionSemester.readActualExecutionSemester());
    }

    public Set<ExecutionYear> getBeginContextExecutionYears() {
        final Set<ExecutionYear> result = new HashSet<ExecutionYear>();
        for (final Context context : getChildContexts(CourseGroup.class)) {
            result.add(context.getBeginExecutionPeriod().getExecutionYear());
            result.addAll(((CourseGroup) context.getChildDegreeModule()).getBeginContextExecutionYears());
        }
        return result;
    }

    @Override
    public void doForAllCurricularCourses(final CurricularCourseFunctor curricularCourseFunctor) {
        for (final Context context : getChildContextsSet()) {
            final DegreeModule degreeModule = context.getChildDegreeModule();
            degreeModule.doForAllCurricularCourses(curricularCourseFunctor);
            if (!curricularCourseFunctor.keepDoing()) {
                return;
            }
        }
    }

    public boolean hasAnyParentBranchCourseGroup() {

        if (isBranchCourseGroup()) {
            return true;
        } else {
            for (Context context : getParentContextsSet()) {
                if (context.getParentCourseGroup().hasAnyParentBranchCourseGroup()) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void applyToCurricularCourses(final ExecutionYear executionYear, final Predicate predicate) {
        for (final Context context : getChildContextsSet()) {
            if (executionYear == null || context.isValid(executionYear)) {
                final DegreeModule childDegreeModule = context.getChildDegreeModule();
                childDegreeModule.applyToCurricularCourses(executionYear, predicate);
            }
        }
    }

}
TOP

Related Classes of org.fenixedu.academic.domain.degreeStructure.CourseGroup

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.