Package org.fenixedu.academic.domain.degreeStructure

Source Code of org.fenixedu.academic.domain.degreeStructure.Context$DegreeModuleScopeContext

/**
* 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.text.Collator;
import java.util.Collection;
import java.util.Comparator;
import java.util.Set;

import org.fenixedu.academic.domain.CurricularCourse;
import org.fenixedu.academic.domain.DegreeModuleScope;
import org.fenixedu.academic.domain.DomainObjectUtil;
import org.fenixedu.academic.domain.ExecutionInterval;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.ExecutionYear;
import org.fenixedu.academic.domain.curricularPeriod.CurricularPeriod;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.studentCurriculum.CurriculumLine;
import org.fenixedu.academic.domain.studentCurriculum.CurriculumModule;
import org.fenixedu.academic.domain.time.calendarStructure.AcademicInterval;
import org.fenixedu.academic.predicate.ContextPredicates;
import org.fenixedu.bennu.core.domain.Bennu;

import pt.ist.fenixframework.dml.runtime.RelationAdapter;

public class Context extends Context_Base implements Comparable<Context> {

    public static final Comparator<Context> COMPARATOR_BY_DEGREE_MODULE_NAME = new Comparator<Context>() {

        @Override
        public int compare(Context o1, Context o2) {
            final DegreeModule d1 = o1.getChildDegreeModule();
            final DegreeModule d2 = o2.getChildDegreeModule();
            final int c = Collator.getInstance().compare(d1.getName(), d2.getName());
            return c == 0 ? DomainObjectUtil.COMPARATOR_BY_ID.compare(d1, d2) : c;
        }

    };

    public static Comparator<Context> COMPARATOR_BY_CURRICULAR_YEAR = new Comparator<Context>() {
        @Override
        public int compare(Context leftContext, Context rightContext) {
            int comparationResult = leftContext.getCurricularYear().compareTo(rightContext.getCurricularYear());
            return (comparationResult == 0) ? leftContext.getExternalId().compareTo(rightContext.getExternalId()) : comparationResult;
        }
    };

    static {
        getRelationCourseGroupContext().addListener(new RelationAdapter<CourseGroup, Context>() {

            @Override
            public void beforeAdd(CourseGroup courseGroup, Context context) {
                if (context != null && courseGroup != null) {
                    if (context.getChildDegreeModule() != null && context.getChildDegreeModule().isCycleCourseGroup()) {
                        validateCycleCourseGroupParent(context, courseGroup);
                    }

                    if (context.getChildDegreeModule() != null && context.getParentCourseGroup() != null
                            && context.getParentCourseGroup().hasAnyParentBranchCourseGroup()
                            && context.getChildDegreeModule().isBranchCourseGroup()) {
                        throw new DomainException("error.degreeStructure.BranchCourseGroup.cant.have.branch.parent");
                    }
                }
            }

            private void validateCycleCourseGroupParent(Context context, CourseGroup courseGroup) {
                CycleCourseGroup cycleCourseGroup = (CycleCourseGroup) context.getChildDegreeModule();
                if (cycleCourseGroup.getParentContextsSet().size() > 1) {
                    throw new DomainException("error.degreeStructure.CycleCourseGroup.can.only.have.one.parent");
                }
                if (!courseGroup.isRoot()) {
                    throw new DomainException("error.degreeStructure.CycleCourseGroup.parent.must.be.RootCourseGroup");
                }
            }

        });

        getRelationDegreeModuleContext().addListener(new RelationAdapter<Context, DegreeModule>() {
            @Override
            public void beforeAdd(Context context, DegreeModule degreeModule) {
                if (context != null && degreeModule != null) {
                    if (degreeModule.isRoot()) {
                        throw new DomainException("error.degreeStructure.RootCourseGroup.cannot.have.parent.contexts");
                    }
                    if (degreeModule.isCycleCourseGroup()) {
                        CycleCourseGroup cycleCourseGroup = (CycleCourseGroup) degreeModule;
                        if (cycleCourseGroup.getParentContextsSet().size() > 0) {
                            throw new DomainException("error.degreeStructure.CycleCourseGroup.can.only.have.one.parent");
                        }
                        if (context.getParentCourseGroup() != null && !context.getParentCourseGroup().isRoot()) {
                            throw new DomainException("error.degreeStructure.CycleCourseGroup.parent.must.be.RootCourseGroup");
                        }
                    }
                }
            }
        });

    }

    protected Context() {
        super();
        setRootDomainObject(Bennu.getInstance());
        this.setChildOrder(0);
    }

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

        this();

        checkParameters(courseGroup, degreeModule, begin);
        checkExecutionPeriods(begin, end);
        checkIfCanAddDegreeModuleToCourseGroup(courseGroup, degreeModule, curricularPeriod, begin.getExecutionYear());
        checkExistingCourseGroupContexts(courseGroup, degreeModule, curricularPeriod, begin, end);

        super.setParentCourseGroup(courseGroup);
        super.setChildDegreeModule(degreeModule);
        super.setCurricularPeriod(curricularPeriod);
        super.setBeginExecutionPeriod(begin);
        super.setEndExecutionPeriod(end);
    }

    private void checkIfCanAddDegreeModuleToCourseGroup(final CourseGroup courseGroup, final DegreeModule degreeModule,
            final CurricularPeriod curricularPeriod, final ExecutionYear executionYear) {
        if (degreeModule.isLeaf()) {
            checkIfCanAddCurricularCourseToCourseGroup(courseGroup, (CurricularCourse) degreeModule, curricularPeriod,
                    executionYear);
        } else {
            checkIfCanAddCourseGroupToCourseGroup(courseGroup, (CourseGroup) degreeModule);
        }
    }

    private void checkIfCanAddCurricularCourseToCourseGroup(final CourseGroup parent, final CurricularCourse curricularCourse,
            final CurricularPeriod curricularPeriod, final ExecutionYear executionYear) {
        if (curricularCourse.getCompetenceCourse() != null && curricularCourse.getCompetenceCourse().isAnual(executionYear)
                && !curricularPeriod.hasChildOrderValue(1)) {
            throw new DomainException("competenceCourse.anual.but.trying.to.associate.curricular.course.not.to.first.period");
        }
    }

    private void checkIfCanAddCourseGroupToCourseGroup(final CourseGroup parent, final CourseGroup courseGroup) {
        parent.checkDuplicateChildNames(courseGroup.getName(), courseGroup.getNameEn());
    }

    private void checkParameters(CourseGroup courseGroup, DegreeModule degreeModule, ExecutionSemester beginExecutionPeriod) {
        if (courseGroup == null || degreeModule == null || beginExecutionPeriod == null) {
            throw new DomainException("error.incorrectContextValues");
        }
    }

    private void checkExistingCourseGroupContexts(final CourseGroup courseGroup, final DegreeModule degreeModule,
            final CurricularPeriod curricularPeriod, final ExecutionSemester begin, final ExecutionSemester end) {

        for (final Context context : courseGroup.getChildContextsSet()) {
            if (context != this && context.hasChildDegreeModule(degreeModule) && context.hasCurricularPeriod(curricularPeriod)
                    && context.contains(begin, end)) {
                throw new DomainException("courseGroup.contextAlreadyExistForCourseGroup");
            }
        }
    }

    public void edit(final CourseGroup parent, final CurricularPeriod curricularPeriod, final ExecutionSemester begin,
            final ExecutionSemester end) {
        setParentCourseGroup(parent);
        setCurricularPeriod(curricularPeriod);
        edit(begin, end);
    }

    protected void edit(final ExecutionSemester begin, final ExecutionSemester end) {
        checkExecutionPeriods(begin, end);
        checkExistingCourseGroupContexts(getParentCourseGroup(), getChildDegreeModule(), getCurricularPeriod(), begin, end);
        setBeginExecutionPeriod(begin);
        setEndExecutionPeriod(end);
        checkCurriculumLines(getChildDegreeModule());
    }

    private void checkCurriculumLines(final DegreeModule degreeModule) {
        for (final CurriculumModule curriculumModule : degreeModule.getCurriculumModulesSet()) {
            if (curriculumModule.isCurriculumLine()) {
                final CurriculumLine curriculumLine = (CurriculumLine) curriculumModule;
                if (curriculumLine.hasExecutionPeriod()
                        && !degreeModule.hasAnyOpenParentContexts(curriculumLine.getExecutionPeriod())) {
                    throw new DomainException("error.Context.cannot.modify.begin.and.end.because.of.enroled.curriculumLines");
                }
            }
        }
    }

    public void delete() {

        final DegreeModule degreeModule = getChildDegreeModule();
        setChildDegreeModule(null);
        /*
         * First remove child and then check if all curriculum lines remain
         * valid
         */
        checkCurriculumLines(degreeModule);

        setCurricularPeriod(null);
        setParentCourseGroup(null);
        super.setBeginExecutionPeriod(null);
        setEndExecutionPeriod(null);
        setRootDomainObject(null);
        getAssociatedWrittenEvaluationsSet().clear();
        super.deleteDomainObject();
    }

    @Override
    public int compareTo(Context o) {
        int orderCompare = this.getChildOrder().compareTo(o.getChildOrder());
        if (this.getParentCourseGroup().equals(o.getParentCourseGroup()) && orderCompare != 0) {
            return orderCompare;
        } else {
            if (this.getChildDegreeModule() instanceof CurricularCourse) {
                int periodsCompare = this.getCurricularPeriod().compareTo(o.getCurricularPeriod());
                if (periodsCompare != 0) {
                    return periodsCompare;
                }
                return Collator.getInstance().compare(this.getChildDegreeModule().getName(), o.getChildDegreeModule().getName());
            } else {
                return Collator.getInstance().compare(this.getChildDegreeModule().getName(), o.getChildDegreeModule().getName());
            }
        }
    }

    @Override
    public void setParentCourseGroup(CourseGroup courseGroup) {
        check(this, ContextPredicates.curricularPlanMemberWritePredicate);
        super.setParentCourseGroup(courseGroup);
    }

    @Override
    public void setCurricularPeriod(CurricularPeriod curricularPeriod) {
        check(this, ContextPredicates.curricularPlanMemberWritePredicate);
        super.setCurricularPeriod(curricularPeriod);
    }

    @Override
    public void setChildDegreeModule(DegreeModule degreeModule) {
        check(this, ContextPredicates.curricularPlanMemberWritePredicate);
        super.setChildDegreeModule(degreeModule);
    }

    public boolean isValid(final ExecutionSemester executionSemester) {
        if (isOpen(executionSemester)) {
            if (getChildDegreeModule().isCurricularCourse()) {
                CurricularCourse curricularCourse = (CurricularCourse) getChildDegreeModule();
                if (!curricularCourse.isAnual(executionSemester.getExecutionYear())) {
                    return containsSemester(executionSemester.getSemester());
                }
            }
            return true;
        }
        return false;
    }

    public boolean isValid(final ExecutionYear executionYear) {
        for (final ExecutionSemester executionSemester : executionYear.getExecutionPeriodsSet()) {
            if (isValid(executionSemester)) {
                return true;
            }
        }
        return false;
    }

    public boolean isValid(AcademicInterval academicInterval) {
        ExecutionInterval interval = ExecutionInterval.getExecutionInterval(academicInterval);
        if (interval instanceof ExecutionSemester) {
            return isValid((ExecutionSemester) interval);
        }
        if (interval instanceof ExecutionYear) {
            return isValid((ExecutionYear) interval);
        }
        throw new UnsupportedOperationException("Unknown academicIntervalType: " + academicInterval);
    }

    protected void checkExecutionPeriods(ExecutionSemester beginExecutionPeriod, ExecutionSemester endExecutionPeriod) {
        if (beginExecutionPeriod == null) {
            throw new DomainException("context.begin.execution.period.cannot.be.null");
        }
        if (endExecutionPeriod != null && beginExecutionPeriod.isAfter(endExecutionPeriod)) {
            throw new DomainException("context.begin.is.after.end.execution.period");
        }
    }

    public boolean isOpen(final ExecutionSemester executionSemester) {
        return getBeginExecutionPeriod().isBeforeOrEquals(executionSemester)
                && (getEndExecutionPeriod() == null || getEndExecutionPeriod().isAfterOrEquals(executionSemester));
    }

    public boolean isOpen(final ExecutionYear executionYear) {
        for (final ExecutionSemester executionSemester : executionYear.getExecutionPeriodsSet()) {
            if (isOpen(executionSemester)) {
                return true;
            }
        }
        return false;
    }

    public boolean isOpen() {
        return isOpen(ExecutionSemester.readActualExecutionSemester());
    }

    public boolean contains(final ExecutionSemester begin, final ExecutionSemester end) {
        if (end != null && begin.isAfter(end)) {
            throw new DomainException("context.begin.is.after.end.execution.period");
        }

        if (begin.isAfterOrEquals(getBeginExecutionPeriod())) {
            return getEndExecutionPeriod() == null || begin.isBeforeOrEquals(getEndExecutionPeriod());
        } else {
            return end == null || end.isAfterOrEquals(getBeginExecutionPeriod());
        }
    }

    @Deprecated
    public Integer getOrder() {
        return super.getChildOrder();
    }

    @Deprecated
    public void setOrder(Integer order) {
        super.setChildOrder(order);
    }

    public boolean containsCurricularYear(final Integer curricularYear) {
        final CurricularPeriod firstCurricularPeriod = getCurricularPeriod().getParent();
        final int firstCurricularPeriodOrder = firstCurricularPeriod.getAbsoluteOrderOfChild();
        return curricularYear.intValue() == firstCurricularPeriodOrder;
    }

    public boolean containsSemester(final Integer semester) {
        final CurricularPeriod firstCurricularPeriod = getCurricularPeriod();
        final int firstCurricularPeriodOrder = firstCurricularPeriod.getChildOrder();
        return semester.intValue() == firstCurricularPeriodOrder;
    }

    public boolean containsSemesterAndCurricularYear(final Integer semester, final Integer curricularYear,
            final RegimeType regimeType) {

        final int argumentOrder = (curricularYear - 1) * 2 + semester.intValue();
        final CurricularPeriod firstCurricularPeriod = getCurricularPeriod();
        final int firstCurricularPeriodOrder = firstCurricularPeriod.getAbsoluteOrderOfChild();
        final int duration;
        if (regimeType == RegimeType.ANUAL) {
            duration = 2;
        } else if (regimeType == RegimeType.SEMESTRIAL) {
            duration = 1;
        } else {
            throw new IllegalArgumentException("Unknown regimeType: " + regimeType);
        }
        final int lastCurricularPeriodOrder = firstCurricularPeriodOrder + duration - 1;
        return firstCurricularPeriodOrder <= argumentOrder && argumentOrder <= lastCurricularPeriodOrder;
    }

    public DegreeModuleScopeContext getDegreeModuleScopeContext() {
        return new DegreeModuleScopeContext(this);
    }

    @Override
    public void setBeginExecutionPeriod(ExecutionSemester beginExecutionPeriod) {
        if (beginExecutionPeriod == null) {
            throw new DomainException("curricular.rule.begin.execution.period.cannot.be.null");
        }
        super.setBeginExecutionPeriod(beginExecutionPeriod);
    }

    public void removeBeginExecutionPeriod() {
        super.setBeginExecutionPeriod(null);
    }

    public Integer getCurricularYear() {
        return getCurricularPeriod().getParent().getAbsoluteOrderOfChild();
    }

    public void addAllCourseGroups(Set<CourseGroup> courseGroups) {
        final DegreeModule degreeModule = getChildDegreeModule();
        if (!degreeModule.isLeaf()) {
            final CourseGroup courseGroup = (CourseGroup) degreeModule;
            courseGroups.add(courseGroup);
            courseGroup.getAllCoursesGroupse(courseGroups);
        }
    }

    public void getAllDegreeModules(final Collection<DegreeModule> degreeModules) {
        final DegreeModule degreeModule = getChildDegreeModule();
        degreeModule.getAllDegreeModules(degreeModules);
    }

    public boolean hasChildDegreeModule(final DegreeModule degreeModule) {
        return getChildDegreeModule() != null && getChildDegreeModule().equals(degreeModule);
    }

    public boolean hasCurricularPeriod(final CurricularPeriod curricularPeriod) {
        return getCurricularPeriod() != null && getCurricularPeriod().equals(curricularPeriod);
    }

    public class DegreeModuleScopeContext extends DegreeModuleScope {

        private final Context context;

        private DegreeModuleScopeContext(Context context) {
            this.context = context;
        }

        @Override
        public String getExternalId() {
            return context.getExternalId();
        }

        @Override
        public Integer getCurricularSemester() {
            return context.getCurricularPeriod().getChildOrder();
        }

        @Override
        public Integer getCurricularYear() {
            return context.getCurricularYear();
        }

        @Override
        public String getBranch() {
            return "";
        }

        public Context getContext() {
            return context;
        }

        @Override
        public boolean isActiveForExecutionPeriod(final ExecutionSemester executionSemester) {
            final ExecutionYear executionYear = executionSemester.getExecutionYear();
            return getCurricularCourse().isAnual(executionYear) ? getContext().isValid(executionYear) : getContext().isValid(
                    executionSemester);
        }

        @Override
        public boolean isActiveForAcademicInterval(final AcademicInterval academicInterval) {
            return getContext().isValid(academicInterval);
        }

        @Override
        public CurricularCourse getCurricularCourse() {
            return (CurricularCourse) context.getChildDegreeModule();
        }

        @Override
        public String getAnotation() {
            return null;
        }

        @Override
        public String getClassName() {
            return context.getClass().getName();
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof DegreeModuleScopeContext)) {
                return false;
            }
            return context.equals(((DegreeModuleScopeContext) obj).getContext());
        }

        @Override
        public int hashCode() {
            return context.hashCode();
        }
    }

}
TOP

Related Classes of org.fenixedu.academic.domain.degreeStructure.Context$DegreeModuleScopeContext

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.