package net.sourceforge.fenixedu.dataTransferObject.resourceAllocationManager; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import net.sourceforge.fenixedu.domain.CurricularYearList; import net.sourceforge.fenixedu.domain.ExecutionDegree; import net.sourceforge.fenixedu.domain.ExecutionSemester; import net.sourceforge.fenixedu.domain.OccupationPeriod; import net.sourceforge.fenixedu.domain.OccupationPeriodReference; import net.sourceforge.fenixedu.domain.OccupationPeriodType; import net.sourceforge.fenixedu.domain.exceptions.DomainException; import net.sourceforge.fenixedu.util.BundleUtil; import net.sourceforge.fenixedu.util.date.IntervalTools; import org.joda.time.DateTime; import org.joda.time.Interval; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import pt.ist.fenixWebFramework.services.Service; import pt.utl.ist.fenix.tools.util.i18n.Language; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.ComparisonChain; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; /** * @author Joao Carvalho (joao.pedro.carvalho@ist.utl.pt) * */ public class OccupationPeriodBean implements Serializable, Comparable { /** * */ private static final long serialVersionUID = -9196229454898126127L; private List intervals = new ArrayList(); private OccupationPeriodType occupationPeriodType; private OccupationPeriod occupationPeriod; private Integer semester; private List references = new ArrayList(); private final int id; public OccupationPeriodBean(int id) { this.id = id; this.semester = ExecutionSemester.readActualExecutionSemester().getSemester(); this.occupationPeriodType = OccupationPeriodType.LESSONS; this.intervals = Lists.newArrayList(new Interval(new DateTime(), new DateTime().plusDays(1))); } public OccupationPeriodBean(OccupationPeriodReference reference, int id) { this.occupationPeriod = reference.getOccupationPeriod(); reloadIntervals(); this.semester = reference.getSemester(); this.occupationPeriodType = reference.getPeriodType(); this.id = id; } private void reloadIntervals() { this.intervals = occupationPeriod.getIntervals(); } public int getId() { return id; } public List getIntervals() { return intervals; } public void setIntervals(List intervals) { this.intervals = intervals; } public OccupationPeriodType getOccupationPeriodType() { return occupationPeriodType; } public void setOccupationPeriodType(OccupationPeriodType occupationPeriodType) { this.occupationPeriodType = occupationPeriodType; } public OccupationPeriod getOccupationPeriod() { return occupationPeriod; } public void setOccupationPeriod(OccupationPeriod occupationPeriod) { this.occupationPeriod = occupationPeriod; } public List getReferences() { return references; } public void setReferences(List references) { this.references = references; } public void addReference(OccupationPeriodReference reference) { references.add(reference); } public Integer getSemester() { return semester; } public void setSemester(Integer semester) { this.semester = semester; } // Note: If there ever is a need to create more than one semester, this is // the place it should be done! public Collection getPossibleSemesters() { return Lists.newArrayList(1, 2); } public boolean getNewObject() { return occupationPeriod == null; } // Presentation Utility Methods public String getDatesString() { if (intervals.size() == 0 || occupationPeriod == null) { return BundleUtil.getStringFromResourceBundle("resources.ResourceAllocationManagerResources", "label.periods.no.dates"); } DateTimeFormatter formatter = DateTimeFormat.forPattern("dd MMM").withLocale(Language.getLocale()); StringBuilder builder = new StringBuilder(); for (Interval interval : getIntervals()) { if (builder.length() > 0) builder.append(", "); builder.append(formatter.print(interval.getStart())); builder.append(" - "); builder.append(formatter.print(interval.getEnd())); } return builder.toString(); } public String getName() { if (occupationPeriod == null) return "Novo período"; return "Período de " + occupationPeriodType.getLocalizedName() + (semester == null ? "" : " - " + semester + "º Semestre"); } @Override public int compareTo(OccupationPeriodBean other) { return ComparisonChain .start() .compare(this.getOccupationPeriod().getPeriodInterval().getStartMillis(), other.getOccupationPeriod().getPeriodInterval().getStartMillis()) .compare(this.getReferences().size(), this.getReferences().size()).result(); } // Actual bean operations @Service public void updateDates(String parameter) { Iterable intervals = extractIntervals(parameter); consolidateReferences(); // The occupation period is shared by multiple types, a new one must be // created! if (this.occupationPeriod.getExecutionDegreesCount() != getReferences().size()) { this.occupationPeriod = new OccupationPeriod(intervals.iterator()); // Period has changed, lets change the references so they point to // the new period. consolidateReferences(); } else { this.occupationPeriod.editDates(intervals.iterator()); } reloadIntervals(); } @Service public void updateCourses(String parameter) { Map degreeMap = extractCourses(parameter); // Step 1, Remove non-existing references for (Iterator references = getReferences().iterator(); references.hasNext();) { OccupationPeriodReference reference = references.next(); if (!degreeMap.containsKey(reference.getExecutionDegree())) { reference.delete(); references.remove(); } } // Step 2, Add new references, and update old ones for (final Entry entry : degreeMap.entrySet()) { OccupationPeriodReference reference = null; for (OccupationPeriodReference ref : getReferences()) { if (ref.getExecutionDegree().equals(entry.getKey())) { reference = ref; break; } } if (reference == null) { references.add(new OccupationPeriodReference(occupationPeriod, entry.getKey(), occupationPeriodType, semester, entry.getValue())); } else { reference.setOccupationPeriod(occupationPeriod); reference.setPeriodType(occupationPeriodType); reference.setSemester(semester); reference.setCurricularYears(entry.getValue()); } } } @Service public void deletePeriod() { for (OccupationPeriodReference ref : getReferences()) { ref.delete(); } } @Service public void create(String intervalsStr, String courses) { Iterable intervals = extractIntervals(intervalsStr); this.occupationPeriod = new OccupationPeriod(intervals.iterator()); updateCourses(courses); } // Private Utility Methods private static final Splitter SPLITTER = Splitter.on(';').trimResults().omitEmptyStrings(); private static final DateTimeFormatter FORMATTER = DateTimeFormat.forPattern("dd/MM/yyyy"); private void consolidateReferences() { Preconditions.checkNotNull(occupationPeriod); for (OccupationPeriodReference reference : references) { reference.setOccupationPeriod(occupationPeriod); } } private Iterable extractIntervals(String parameter) { Iterable intervals = Iterables.transform(SPLITTER.split(parameter), new Function() { @Override public Interval apply(String string) { String[] dates = string.split(","); if (dates.length != 2) throw new RuntimeException("Error while recreating intervals, '" + string + "' cannot be parsed!"); LocalDate start = FORMATTER.parseDateTime(dates[0]).toLocalDate(); LocalDate end = FORMATTER.parseDateTime(dates[1]).toLocalDate(); return IntervalTools.getInterval(start, end); } }); Iterator iter = intervals.iterator(); Interval last = iter.next(); while (iter.hasNext()) { Interval current = iter.next(); if (!current.isAfter(last)) throw new DomainException("label.occupation.period.invalid.dates"); last = current; } return intervals; } private Map extractCourses(String parameter) { Map degreeMap = new HashMap(); for (String string : SPLITTER.split(parameter)) { String[] parts = string.split(":"); if (parts.length != 2) throw new RuntimeException("Error while recreating execution degree, '" + string + "' cannot be parsed!"); String oid = parts[0]; ExecutionDegree degree = ExecutionDegree.fromExternalId(oid); degreeMap.put(degree, CurricularYearList.internalize(parts[1])); } return degreeMap; } @Service public OccupationPeriodBean duplicate(int newId, OccupationPeriodType newPeriodType) { OccupationPeriodBean newBean = new OccupationPeriodBean(newId); newBean.setOccupationPeriodType(newPeriodType); newBean.setIntervals(intervals); newBean.setOccupationPeriod(occupationPeriod); newBean.setSemester(semester); for (OccupationPeriodReference reference : references) { newBean.addReference(new OccupationPeriodReference(reference.getOccupationPeriod(), reference.getExecutionDegree(), newPeriodType, semester, reference.getCurricularYears())); } return newBean; } }