/**
* 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.time.calendarStructure;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import org.fenixedu.academic.domain.DomainObjectUtil;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.time.chronologies.AcademicChronology;
import org.fenixedu.academic.domain.time.chronologies.dateTimeFields.AcademicSemesterOfAcademicYearDateTimeFieldType;
import org.fenixedu.academic.dto.GenericPair;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.academic.util.DayType;
import org.fenixedu.academic.util.MultiLanguageString;
import org.fenixedu.academic.util.renderer.GanttDiagramEvent;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.joda.time.DateTime;
import org.joda.time.Interval;
public abstract class AcademicCalendarEntry extends AcademicCalendarEntry_Base implements GanttDiagramEvent {
protected abstract AcademicCalendarEntry createVirtualEntry(AcademicCalendarEntry parentEntry);
protected abstract boolean isParentEntryInvalid(AcademicCalendarEntry parentEntry);
protected abstract boolean exceededNumberOfChildEntries(AcademicCalendarEntry childEntry);
protected abstract boolean areIntersectionsPossible(AcademicCalendarEntry entryToAdd);
protected abstract boolean isPossibleToChangeTimeInterval();
protected abstract boolean associatedWithDomainEntities();
protected void afterRedefineEntry() {
}
protected void beforeRedefineEntry() {
}
public static final Comparator<AcademicCalendarEntry> COMPARATOR_BY_BEGIN_DATE = new Comparator<AcademicCalendarEntry>() {
@Override
public int compare(final AcademicCalendarEntry o1, final AcademicCalendarEntry o2) {
int c1 = o1.getBegin().compareTo(o2.getBegin());
return c1 == 0 ? DomainObjectUtil.COMPARATOR_BY_ID.compare(o1, o2) : c1;
}
};
protected AcademicCalendarEntry() {
super();
setRootDomainObject(Bennu.getInstance());
}
public void delete(AcademicCalendarRootEntry rootEntry) {
if (!canBeDeleted(rootEntry)) {
throw new DomainException("error.now.its.impossible.delete.entry.but.in.the.future.will.be.possible");
}
getBasedEntriesSet().clear();
super.setParentEntry(null);
super.setTemplateEntry(null);
setRootDomainObject(null);
deleteDomainObject();
}
public AcademicCalendarEntry edit(MultiLanguageString title, MultiLanguageString description, DateTime begin, DateTime end,
AcademicCalendarRootEntry rootEntry, AcademicCalendarEntry templateEntry) {
if (isRoot() || rootEntry == null) {
throw new DomainException("error.unsupported.operation");
}
if (!rootEntry.equals(getRootEntry())) {
if (getBegin().isEqual(begin) && getEnd().isEqual(end)) {
throw new DomainException("error.AcademicCalendarEntry.unchanged.dates");
}
AcademicCalendarEntry newParentEntry = createVirtualPathUntil(getParentEntry(), rootEntry);
AcademicCalendarEntry newEntry = createVirtualEntry(newParentEntry);
newEntry.edit(title, description, begin, end, rootEntry, templateEntry);
return newEntry;
} else {
boolean isRedefinedEntry = isVirtual();
if (isRedefinedEntry) {
beforeRedefineEntry();
}
setTitle(title);
setDescription(description);
setTimeInterval(begin, end);
if (isRedefinedEntry) {
afterRedefineEntry();
}
return this;
}
}
protected void initEntry(AcademicCalendarEntry parentEntry, MultiLanguageString title, MultiLanguageString description,
DateTime begin, DateTime end, AcademicCalendarRootEntry rootEntry) {
if (rootEntry == null || parentEntry == null) {
throw new DomainException("error.unsupported.operation");
}
parentEntry =
!parentEntry.getRootEntry().equals(rootEntry) ? createVirtualPathUntil(parentEntry, rootEntry) : parentEntry;
setParentEntry(parentEntry, false);
setTitle(title);
setDescription(description);
setTimeInterval(begin, end);
}
protected void initVirtualEntry(AcademicCalendarEntry parentEntry, AcademicCalendarEntry templateEntry) {
setParentEntry(parentEntry, true);
setTemplateEntry(templateEntry);
}
private AcademicCalendarEntry createVirtualPathUntil(AcademicCalendarEntry entry,
AcademicCalendarRootEntry rootEntryDestination) {
if (!entry.isRoot()) {
List<AcademicCalendarEntry> entryPath = entry.getFullPath();
entryPath.remove(0);// remove root entry
AcademicCalendarEntry parentEntry = rootEntryDestination;
AcademicCalendarEntry virtualOrRedefinedEntry = rootEntryDestination;
for (AcademicCalendarEntry entryToMakeCopy : entryPath) {
if (virtualOrRedefinedEntry != null) {
virtualOrRedefinedEntry = entryToMakeCopy.getVirtualOrRedefinedEntryIn(rootEntryDestination);
}
if (virtualOrRedefinedEntry == null) {
parentEntry = entryToMakeCopy.createVirtualEntry(parentEntry);
} else {
parentEntry = virtualOrRedefinedEntry;
}
}
return parentEntry;
} else {
return rootEntryDestination;
}
}
private AcademicCalendarEntry getVirtualOrRedefinedEntryIn(AcademicCalendarRootEntry rootEntry) {
if (rootEntry != null) {
Collection<AcademicCalendarEntry> basedEntries = getBasedEntriesSet();
for (AcademicCalendarEntry entry : basedEntries) {
if (entry.getRootEntry().equals(rootEntry)) {
return entry;
}
}
}
return null;
}
private boolean canBeDeleted(AcademicCalendarRootEntry rootEntry) {
if (!getRootEntry().equals(rootEntry)) {
throw new DomainException("error.AcademicCalendarEntry.different.rootEntry");
}
if (!getChildEntriesSet().isEmpty()) {
throw new DomainException("error.AcademicCalendarEntry.has.childs");
}
return true;
}
@Override
public void setTemplateEntry(AcademicCalendarEntry templateEntry) {
if (templateEntry != null
&& (!templateEntry.getClass().equals(getClass()) || getBasedEntriesSet().contains(templateEntry))) {
throw new DomainException("error.AcademicCalendarEntry.invalid.template.entry");
}
if (!isRoot()) {
AcademicCalendarRootEntry rootEntry = getRootEntry();
if (rootEntry.getTemplateEntry() == null || !rootEntry.getTemplateEntry().equals(templateEntry.getRootEntry())) {
throw new DomainException("error.AcademicCalendarEntry.invalid.template.entry");
}
}
super.setTemplateEntry(templateEntry);
}
protected void setParentEntry(AcademicCalendarEntry parentEntry, boolean virtualEntry) {
if (parentEntry == null) {
throw new DomainException("error.AcademicCalendarEntry.empty.parentEntry");
}
if (isParentEntryInvalid(parentEntry)) {
throw new DomainException("error.AcademicCalendarEntry.invalid.parent.entry", getClass().getSimpleName(), parentEntry
.getClass().getSimpleName());
}
if (!virtualEntry && parentEntry.exceededNumberOfChildEntries(this)) {
throw new DomainException("error.AcademicCalendarEntry.number.of.subEntries.exceeded");
}
super.setParentEntry(parentEntry);
}
@Override
public void setParentEntry(AcademicCalendarEntry parentEntry) {
throw new DomainException("error.unsupported.operation");
}
@Override
public void setBegin(DateTime begin) {
throw new DomainException("error.unsupported.operation");
}
@Override
public void setEnd(DateTime end) {
throw new DomainException("error.unsupported.operation");
}
@Override
public void setTitle(MultiLanguageString title) {
if (title == null || title.isEmpty()) {
throw new DomainException("error.AcademicCalendarEntry.empty.title");
}
super.setTitle(title);
}
@Override
public DateTime getBegin() {
return isVirtual() ? getTemplateEntry().getBegin() : super.getBegin();
}
@Override
public DateTime getEnd() {
return isVirtual() ? getTemplateEntry().getEnd() : super.getEnd();
}
@Override
public MultiLanguageString getTitle() {
return isVirtual() && !isRoot() ? getTemplateEntry().getTitle() : super.getTitle();
}
@Override
public MultiLanguageString getDescription() {
return isVirtual() && !isRoot() ? getTemplateEntry().getDescription() : super.getDescription();
}
protected void setTimeInterval(DateTime begin, DateTime end) {
if (begin == null) {
throw new DomainException("error.AcademicCalendarEntry.empty.begin.dateTime");
}
if (end == null) {
throw new DomainException("error.AcademicCalendarEntry.empty.end.dateTime");
}
if (!end.isAfter(begin)) {
throw new DomainException("error.begin.after.end");
}
super.setBegin(begin);
super.setEnd(end);
GenericPair<DateTime, DateTime> maxAndMinDateTimes = getChildMaxAndMinDateTimes();
if (maxAndMinDateTimes != null
&& (getBegin().isAfter(maxAndMinDateTimes.getLeft()) || getEnd().isBefore(maxAndMinDateTimes.getRight()))) {
throw new DomainException("error.AcademicCalendarEntry.out.of.bounds");
}
if (!getParentEntry().areIntersectionsPossible(this)) {
for (AcademicCalendarEntry childEntry : getParentEntry().getChildEntriesWithTemplateEntries(getClass())) {
if (!childEntry.equals(this) && childEntry.entriesTimeIntervalIntersection(begin, end)) {
throw new DomainException("error.AcademicCalendarEntry.dates.intersection");
}
}
}
refreshParentTimeInterval();
}
private void refreshParentTimeInterval() {
AcademicCalendarEntry parentEntry = getParentEntry();
if (!parentEntry.isRoot()) {
GenericPair<DateTime, DateTime> childMaxAndMinDateTimes = parentEntry.getChildMaxAndMinDateTimes();
if (childMaxAndMinDateTimes != null) {
DateTime begin = childMaxAndMinDateTimes.getLeft();
DateTime end = childMaxAndMinDateTimes.getRight();
boolean changeBeginDate = !parentEntry.getBegin().isBefore(begin);
boolean changeEndDate = !parentEntry.getEnd().isAfter(end);
if (parentEntry.isPossibleToChangeTimeInterval()) {
if (changeBeginDate || changeEndDate) {
DateTime beginDate = changeBeginDate ? begin : parentEntry.getBegin();
DateTime endDate = changeEndDate ? end : parentEntry.getEnd();
parentEntry.edit(parentEntry.getTitle(), parentEntry.getDescription(), beginDate, endDate,
parentEntry.getRootEntry(), parentEntry.getTemplateEntry());
}
} else if (changeBeginDate || changeEndDate) {
throw new DomainException("error.AcademicCalendarEntry.impossible.refresh.time.interval", getClass()
.getName());
}
}
}
}
public GenericPair<DateTime, DateTime> getChildMaxAndMinDateTimes() {
List<AcademicCalendarEntry> childEntries = getChildEntriesWithTemplateEntries();
if (!childEntries.isEmpty()) {
DateTime begin = null;
DateTime end = null;
for (AcademicCalendarEntry entry : childEntries) {
if (begin == null || entry.getBegin().isBefore(begin)) {
begin = entry.getBegin();
}
if (end == null || entry.getEnd().isAfter(end)) {
end = entry.getEnd();
}
}
return new GenericPair<DateTime, DateTime>(begin, end);
} else {
return null;
}
}
public AcademicCalendarEntry getNonVirtualTemplateEntry() {
if (isVirtual()) {
return getTemplateEntry().getNonVirtualTemplateEntry();
}
return this;
}
public AcademicCalendarEntry getOriginalTemplateEntry() {
if (getTemplateEntry() != null) {
return getTemplateEntry().getOriginalTemplateEntry();
}
return this;
}
public boolean isRedefined() {
return isVirtual();
// return hasTemplateEntry() && super.getBegin() != null;
}
public boolean isVirtual() {
return super.getBegin() == null && getTemplateEntry() != null;
}
public EntryState getEntryState() {
return isVirtual() ? EntryState.VIRTUAL : EntryState.ORIGINAL;
// return isVirtual() ? EntryState.VIRTUAL : isRedefined() ?
// EntryState.REDEFINED : EntryState.ORIGINAL;
}
public static enum EntryState {
VIRTUAL, REDEFINED, ORIGINAL;
public String getName() {
return name();
}
}
public List<AcademicCalendarEntry> getFullPath() {
List<AcademicCalendarEntry> result = new ArrayList<AcademicCalendarEntry>();
result.add(this);
AcademicCalendarEntry parentEntry = getParentEntry();
while (parentEntry != null) {
result.add(0, parentEntry);
parentEntry = parentEntry.getParentEntry();
}
return result;
}
public List<AcademicInterval> getFullPathInDeep() {
List<AcademicInterval> result = new ArrayList<AcademicInterval>();
getChildFullPathInDeep(result, getRootEntry());
return result;
}
private void getChildFullPathInDeep(List<AcademicInterval> result, AcademicCalendarRootEntry rootEntry) {
if (associatedWithDomainEntities()) {
result.add(new AcademicInterval(this, rootEntry));
}
Collection<AcademicCalendarEntry> childEntries =
getTemplateEntry() != null ? getChildEntriesWithTemplateEntries() : getChildEntriesSet();
for (AcademicCalendarEntry child : childEntries) {
child.getChildFullPathInDeep(result, rootEntry);
}
}
public String getPresentationTimeInterval() {
if (!isRoot()) {
return getBegin().toString("dd-MM-yyyy HH:mm") + " - " + getEnd().toString("dd-MM-yyyy HH:mm");
} else {
DateTime begin = getBegin();
return begin != null ? begin.toString("dd-MM-yyyy HH:mm") + " - " + "**-**-**** **:**" : "";
}
}
public MultiLanguageString getType() {
MultiLanguageString type = new MultiLanguageString();
String key = "label." + getClass().getSimpleName() + ".type";
type = type.with(MultiLanguageString.pt, BundleUtil.getString(Bundle.MANAGER, new Locale("pt", "PT"), key));
return type;
}
public String getPresentationName() {
return getTitle().getContent() + " - " + "[" + getType() + "]";
}
public AcademicCalendarRootEntry getAcademicCalendar() {
return getRootEntry();
}
public AcademicCalendarRootEntry getRootEntry() {
if (isRoot()) {
return (AcademicCalendarRootEntry) this;
}
return getParentEntry().getRootEntry();
}
public AcademicChronology getAcademicChronology() {
return getRootEntry().getAcademicChronology();
}
public List<AcademicCalendarEntry> getChildEntriesWithTemplateEntries() {
List<AcademicCalendarEntry> result = new ArrayList<AcademicCalendarEntry>();
getChildEntriesWithTemplateEntries(null, result, null, null, null);
return result;
}
public List<AcademicCalendarEntry> getChildEntriesWithTemplateEntries(Long instant) {
List<AcademicCalendarEntry> result = new ArrayList<AcademicCalendarEntry>();
getChildEntriesWithTemplateEntries(instant, result, null, null, null);
return result;
}
public List<AcademicCalendarEntry> getChildEntriesWithTemplateEntries(Class<? extends AcademicCalendarEntry> subEntryClass) {
if (subEntryClass == null) {
return Collections.emptyList();
}
List<AcademicCalendarEntry> allChildEntries = new ArrayList<AcademicCalendarEntry>();
getChildEntriesWithTemplateEntries(null, allChildEntries, null, null, subEntryClass);
return allChildEntries;
}
public List<AcademicCalendarEntry> getAllChildEntriesWithTemplateEntries(Class<? extends AcademicCalendarEntry> subEntryClass) {
if (subEntryClass == null) {
return Collections.emptyList();
}
List<AcademicCalendarEntry> allChildEntries = new ArrayList<AcademicCalendarEntry>();
getChildEntriesWithTemplateEntries(null, allChildEntries, null, null, subEntryClass);
for (AcademicCalendarEntry child : getChildEntriesSet()) {
allChildEntries.addAll(child.getAllChildEntriesWithTemplateEntries(subEntryClass));
}
return allChildEntries;
}
public List<AcademicCalendarEntry> getChildEntriesWithTemplateEntriesOrderByDate(DateTime begin, DateTime end) {
List<AcademicCalendarEntry> result = getChildEntriesWithTemplateEntries(begin, end, null);
Collections.sort(result, COMPARATOR_BY_BEGIN_DATE);
return result;
}
public List<AcademicCalendarEntry> getChildEntriesWithTemplateEntries(DateTime begin, DateTime end,
Class<? extends AcademicCalendarEntry> subEntryClass) {
List<AcademicCalendarEntry> result = new ArrayList<AcademicCalendarEntry>();
getChildEntriesWithTemplateEntries(null, result, begin, end, subEntryClass);
return result;
}
private List<AcademicCalendarEntry> getChildEntriesWithTemplateEntries(Long instant, DateTime begin, DateTime end,
Class<? extends AcademicCalendarEntry> subEntryClass) {
List<AcademicCalendarEntry> result = new ArrayList<AcademicCalendarEntry>();
getChildEntriesWithTemplateEntries(instant, result, begin, end, subEntryClass);
return result;
}
protected List<AcademicCalendarEntry> getChildEntriesWithTemplateEntries(Long instant, List<AcademicCalendarEntry> result,
DateTime begin, DateTime end, Class<? extends AcademicCalendarEntry> subEntryClass) {
boolean hasTemplateEntry = getTemplateEntry() != null;
List<AcademicCalendarEntry> templateEntries = hasTemplateEntry ? new ArrayList<AcademicCalendarEntry>() : null;
for (AcademicCalendarEntry subEntry : getChildEntriesSet()) {
if ((subEntryClass == null || subEntry.getClass().equals(subEntryClass))
&& (instant == null || subEntry.containsInstant(instant))
&& (begin == null || subEntry.belongsToPeriod(begin, end))) {
result.add(subEntry);
}
if (hasTemplateEntry && subEntry.getTemplateEntry() != null) {
templateEntries.add(subEntry.getTemplateEntry());
}
}
if (hasTemplateEntry) {
for (AcademicCalendarEntry entry : getTemplateEntry().getChildEntriesWithTemplateEntries(instant, begin, end,
subEntryClass)) {
if (!templateEntries.contains(entry)) {
result.add(entry);
}
}
}
return result;
}
protected void getFirstChildEntriesWithTemplateEntries(Long instant, Class<? extends AcademicCalendarEntry> subEntryClass,
Class<? extends AcademicCalendarEntry> parentEntryClass, List<AcademicCalendarEntry> childrenEntriesList) {
if (getClass().equals(parentEntryClass)) {
getChildEntriesWithTemplateEntries(instant, childrenEntriesList, null, null, subEntryClass);
} else {
if (getTemplateEntry() == null) {
for (AcademicCalendarEntry subEntry : getChildEntriesSet()) {
if (instant == null || subEntry.containsInstant(instant)) {
subEntry.getFirstChildEntriesWithTemplateEntries(instant, subEntryClass, parentEntryClass,
childrenEntriesList);
}
}
} else {
for (AcademicCalendarEntry subEntry : getChildEntriesWithTemplateEntries(instant)) {
subEntry.getFirstChildEntriesWithTemplateEntries(instant, subEntryClass, parentEntryClass,
childrenEntriesList);
}
}
}
}
/**
* Computes a list of the children which type matches the AcademicPeriod in
* order of a depth first search.
*
* @param period
* The AcademicPeriod for type checking.
* @return the list with the matching entries.
*/
private List<AcademicCalendarEntry> getChildEntriesWithTemplateEntries(AcademicPeriod period) {
List<AcademicCalendarEntry> result = new ArrayList<AcademicCalendarEntry>();
if (isOfType(period)) {
result.add(this);
}
List<AcademicCalendarEntry> children = new ArrayList<AcademicCalendarEntry>();
children.addAll(getChildEntriesSet());
Collections.sort(children, COMPARATOR_BY_BEGIN_DATE);
for (AcademicCalendarEntry child : children) {
result.addAll(child.getChildEntriesWithTemplateEntries(period));
}
return result;
}
public AcademicCalendarEntry getChildAcademicCalendarEntry(AcademicPeriod period, int cardinal) {
List<AcademicCalendarEntry> children = getChildEntriesWithTemplateEntries(period);
if (children.size() >= cardinal) {
return children.get(cardinal - 1);
}
return null;
}
public AcademicCalendarEntry getEntryForCalendar(final AcademicCalendarRootEntry academicCalendar) {
AcademicCalendarRootEntry rootEntry = getRootEntry();
if (rootEntry.equals(academicCalendar)) {
return this;
}
for (final AcademicCalendarEntry basedEntry : getBasedEntriesSet()) {
final AcademicCalendarEntry basedEntryFor = basedEntry.getEntryForCalendar(academicCalendar);
if (basedEntryFor != null) {
return basedEntryFor;
}
}
for (AcademicCalendarEntry otherRoot = academicCalendar; otherRoot != null; otherRoot = otherRoot.getTemplateEntry()) {
if (otherRoot == rootEntry) {
return this;
}
}
return null;
}
public int getAcademicSemesterOfAcademicYear(final AcademicChronology academicChronology) {
return getBegin().withChronology(academicChronology).get(
AcademicSemesterOfAcademicYearDateTimeFieldType.academicSemesterOfAcademicYear());
}
public boolean belongsToPeriod(DateTime begin, DateTime end) {
return !getBegin().isAfter(end) && !getEnd().isBefore(begin);
}
public boolean containsInstant(long instant) {
return getBegin().getMillis() <= instant && getEnd().getMillis() >= instant;
}
private boolean entriesTimeIntervalIntersection(DateTime begin, DateTime end) {
return !getBegin().isAfter(end) && !getEnd().isBefore(begin);
}
@Override
public List<Interval> getGanttDiagramEventSortedIntervals() {
List<Interval> result = new ArrayList<Interval>();
result.add(new Interval(getBegin(), getEnd()));
return result;
}
@Override
public MultiLanguageString getGanttDiagramEventName() {
return getTitle();
}
@Override
public int getGanttDiagramEventOffset() {
if (getParentEntry() == null) {
return 0;
}
return getParentEntry().getGanttDiagramEventOffset() + 1;
}
@Override
public String getGanttDiagramEventObservations() {
return "-";
}
@Override
public String getGanttDiagramEventPeriod() {
return getBegin().toString("dd/MM/yyyy HH:mm") + " - " + getEnd().toString("dd/MM/yyyy HH:mm");
}
@Override
public String getGanttDiagramEventIdentifier() {
return getExternalId().toString();
}
@Override
public Integer getGanttDiagramEventMonth() {
return null;
}
@Override
public String getGanttDiagramEventUrlAddOns() {
return null;
}
@Override
public boolean isGanttDiagramEventIntervalsLongerThanOneDay() {
return false;
}
@Override
public boolean isGanttDiagramEventToMarkWeekendsAndHolidays() {
return false;
}
@Override
public DayType getGanttDiagramEventDayType(Interval interval) {
return null;
}
public abstract boolean isOfType(AcademicPeriod period);
public boolean isAcademicYear() {
return false;
}
public boolean isAcademicSemester() {
return false;
}
public boolean isAcademicTrimester() {
return false;
}
public boolean isLessonsPerid() {
return false;
}
public boolean isExamsPeriod() {
return false;
}
public boolean isEnrolmentsPeriod() {
return false;
}
public boolean isGradeSubmissionPeriod() {
return false;
}
public boolean isRoot() {
return false;
}
public boolean isEqualOrEquivalent(AcademicCalendarEntry entry) {
if (this.equals(entry)) {
return true;
}
if (!getClass().equals(entry.getClass())) {
return false;
}
return getOriginalTemplateEntry().equals(entry.getOriginalTemplateEntry());
}
public AcademicCalendarEntry getNextAcademicCalendarEntry() {
AcademicCalendarEntry closest = null;
for (AcademicCalendarEntry entry : this.getRootEntry().getAllChildEntriesWithTemplateEntries(this.getClass())) {
if (entry.getBegin().isAfter(this.getBegin())) {
if (closest == null || entry.getBegin().isBefore(closest.getBegin())) {
closest = entry;
}
}
}
return closest;
}
public AcademicCalendarEntry getPreviousAcademicCalendarEntry() {
AcademicCalendarEntry closest = null;
for (AcademicCalendarEntry entry : this.getRootEntry().getAllChildEntriesWithTemplateEntries(this.getClass())) {
if (entry.getBegin().isBefore(this.getBegin())) {
if (closest == null || entry.getBegin().isAfter(closest.getBegin())) {
closest = entry;
}
}
}
return closest;
}
public int getCardinalityOfCalendarEntry(AcademicCalendarEntry child) {
int count = 1;
for (AcademicCalendarEntry entry : getChildEntriesWithTemplateEntries(child.getClass())) {
if (entry.getBegin().isBefore(child.getBegin())) {
count++;
}
}
return count;
}
}