/** * 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.curricularPeriod; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Locale; import org.fenixedu.academic.domain.CurricularCourse; import org.fenixedu.academic.domain.ExecutionSemester; import org.fenixedu.academic.domain.degreeStructure.Context; import org.fenixedu.academic.domain.degreeStructure.DegreeModule; import org.fenixedu.academic.domain.exceptions.DomainException; import org.fenixedu.academic.domain.time.calendarStructure.AcademicPeriod; import org.fenixedu.academic.dto.CurricularPeriodInfoDTO; import org.fenixedu.academic.util.CurricularPeriodLabelFormatter; import org.fenixedu.bennu.core.domain.Bennu; import pt.ist.fenixframework.dml.runtime.RelationAdapter; /** * * @author - Shezad Anavarali (shezad@ist.utl.pt) * * */ public class CurricularPeriod extends CurricularPeriod_Base implements Comparable<CurricularPeriod> { static { getRelationCurricularPeriodParentChilds().addListener(new CurricularPeriodParentChildsListener()); } public CurricularPeriod(AcademicPeriod academicPeriod) { super(); setRootDomainObject(Bennu.getInstance()); setAcademicPeriod(academicPeriod); } public CurricularPeriod(AcademicPeriod academicPeriod, Integer order, CurricularPeriod parent) { this(academicPeriod); setChildOrder(order); setParent(parent); } public List<CurricularPeriod> getSortedChilds() { List<CurricularPeriod> sortedChilds = new ArrayList<CurricularPeriod>(); sortedChilds.addAll(getChildsSet()); Collections.sort(sortedChilds); return sortedChilds; } public CurricularPeriod getChildByOrder(Integer order) { for (CurricularPeriod curricularPeriod : getChildsSet()) { if (curricularPeriod.getChildOrder().equals(order)) { return curricularPeriod; } } return null; } private CurricularPeriod findChild(AcademicPeriod academicPeriod, Integer order) { for (CurricularPeriod curricularPeriod : getChildsSet()) { if (curricularPeriod.getChildOrder().equals(order) && curricularPeriod.getAcademicPeriod().equals(academicPeriod)) { return curricularPeriod; } } return null; } public CurricularPeriod getCurricularPeriod(CurricularPeriodInfoDTO... curricularPeriodsPaths) { validatePath(curricularPeriodsPaths); CurricularPeriod curricularPeriod = this; for (CurricularPeriodInfoDTO path : curricularPeriodsPaths) { curricularPeriod = curricularPeriod.findChild(path.getPeriodType(), path.getOrder()); if (curricularPeriod == null) { return null; } } return curricularPeriod; } public CurricularPeriod addCurricularPeriod(CurricularPeriodInfoDTO... curricularPeriodsPaths) { validatePath(curricularPeriodsPaths); CurricularPeriod curricularPeriod = null; CurricularPeriod curricularPeriodParent = this; for (CurricularPeriodInfoDTO path : curricularPeriodsPaths) { curricularPeriod = curricularPeriodParent.findChild(path.getPeriodType(), path.getOrder()); if (curricularPeriod == null) { curricularPeriod = new CurricularPeriod(path.getPeriodType(), path.getOrder(), curricularPeriodParent); } curricularPeriodParent = curricularPeriod; } return curricularPeriod; } public Integer getOrderByType(AcademicPeriod academicPeriod) { Integer resultOrder = null; if (this.getAcademicPeriod().equals(academicPeriod)) { resultOrder = this.getChildOrder(); } else if (this.getParent() != null && this.getParent().getAcademicPeriod().getWeight() > this.getAcademicPeriod().getWeight()) { resultOrder = (this.getParent()).getOrderByType(academicPeriod); } return resultOrder; } private void validatePath(CurricularPeriodInfoDTO... curricularPeriodsPaths) { Arrays.sort(curricularPeriodsPaths, new Comparator<CurricularPeriodInfoDTO>() { @Override public int compare(CurricularPeriodInfoDTO c1, CurricularPeriodInfoDTO c2) { if (c1.getPeriodType().getWeight() > c2.getPeriodType().getWeight()) { return -1; } else if (c1.getPeriodType().getWeight() < c2.getPeriodType().getWeight()) { return 1; } throw new DomainException("error.pathShouldNotHaveSameTypePeriods"); } }); } public void delete() { getContextsSet().clear(); setDegreeCurricularPlan(null); setParent(null); for (CurricularPeriod child : getChildsSet()) { child.delete(); } setRootDomainObject(null); deleteDomainObject(); } public String getLabel() { return CurricularPeriodLabelFormatter.getLabel(this, false); } public String getFullLabel() { return CurricularPeriodLabelFormatter.getFullLabel(this, false); } public String getFullLabel(final Locale locale) { return CurricularPeriodLabelFormatter.getFullLabelI18N(this, false, locale); } @Override public int compareTo(CurricularPeriod o) { return this.getFullWeight().compareTo(o.getFullWeight()); } private Float getWeight() { float periodTypeWeight = (this.getAcademicPeriod() == null) ? 0 : this.getAcademicPeriod().getWeight(); float periodOrder = (this.getChildOrder() == null) ? 0 : this.getChildOrder(); return periodTypeWeight * periodOrder; } private Float getFullWeight() { return this.getWeight() + this.collectParentsWeight(this); } private Float collectParentsWeight(CurricularPeriod period) { Float result = Float.valueOf(0); if (period.getParent() != null) { result = period.getParent().getWeight() + collectParentsWeight(period.getParent()); } return result; } private static class CurricularPeriodParentChildsListener extends RelationAdapter<CurricularPeriod, CurricularPeriod> { @Override public void beforeAdd(CurricularPeriod parent, CurricularPeriod child) { if (parent == null) { return; } if (child.getAcademicPeriod().getWeight() >= parent.getAcademicPeriod().getWeight()) { throw new DomainException("error.childTypeGreaterThanParentType"); } float childsWeight = child.getAcademicPeriod().getWeight(); for (CurricularPeriod period : parent.getChildsSet()) { childsWeight += period.getAcademicPeriod().getWeight(); } if (childsWeight > parent.getAcademicPeriod().getWeight()) { throw new DomainException("error.childWeightOutOfLimit"); } // re-order childs Integer order = child.getChildOrder(); if (order == null) { child.setChildOrder(parent.getChildsSet().size() + 1); } else { if (parent.getChildByOrder(order) != null) { throw new DomainException("error.childAlreadyExists"); } } } } public Integer getParentOrder() { if (this.getParent() != null) { return this.getParent().getChildOrder(); } return null; } public CurricularPeriod getNext() { List<CurricularPeriod> brothers = this.getParent().getSortedChilds(); for (Iterator<CurricularPeriod> iterator = brothers.iterator(); iterator.hasNext();) { CurricularPeriod brother = iterator.next(); if (brother.getChildOrder().equals(this.getChildOrder()) && iterator.hasNext()) { return iterator.next(); } } return null; } public CurricularPeriod contains(AcademicPeriod academicPeriod, Integer order) { if (this.getAcademicPeriod().equals(academicPeriod) && this.getChildOrder().equals(order)) { return this; } for (CurricularPeriod curricularPeriod : getChildsSet()) { CurricularPeriod period = curricularPeriod.contains(academicPeriod, order); if (period != null) { return period; } } return null; } public boolean hasCurricularPeriod(AcademicPeriod academicPeriod, Integer order) { if (this.getAcademicPeriod().equals(academicPeriod) && this.getChildOrder().equals(order)) { return true; } if (getParent() != null) { return getParent().hasCurricularPeriod(academicPeriod, order); } else { return false; } } @Deprecated public Integer getOrder() { return super.getChildOrder(); } @Deprecated public void setOrder(Integer order) { super.setChildOrder(order); } public int getAbsoluteOrderOfChild() { if (getChildOrder() == null) { return 1; } else { final CurricularPeriod parentCurricularPeriod = getParent(); final int absoluteOrderOfParent = parentCurricularPeriod.getAbsoluteOrderOfChild(); final int numberOfBrothersAndSisters = parentCurricularPeriod.getChildsSet().size(); return (absoluteOrderOfParent - 1) * numberOfBrothersAndSisters + getChildOrder().intValue(); } } public List<Context> getContextsWithCurricularCourses() { return getContextsWithCurricularCourses(null); } public List<Context> getContextsWithCurricularCourses(final ExecutionSemester executionSemester) { return getChildContexts(CurricularCourse.class, executionSemester); } public List<Context> getChildContexts(final Class<? extends DegreeModule> clazz, final ExecutionSemester executionSemester) { final List<Context> result = new ArrayList<Context>(); for (final Context context : super.getContextsSet()) { if ((clazz == null || clazz.isAssignableFrom(context.getChildDegreeModule().getClass())) && (executionSemester == null || context.isValid(executionSemester))) { result.add(context); } } return result; } public boolean hasChildOrder() { return getChildOrder() != null; } public boolean hasChildOrderValue(final Integer order) { return hasChildOrder() && getChildOrder().equals(order); } }