///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition 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 General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.plugins.teamcal.externalsubscription; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.projectforge.plugins.teamcal.event.TeamEventDO; import org.projectforge.plugins.teamcal.event.TeamEventDao; /** * Own abstraction of a RangeMap. You can add TeamEvents and access them through their start and end date. * * @author Johannes Unterstein (j.unterstein@micromata.de) */ public class SubscriptionHolder implements Serializable { private static final long serialVersionUID = 1188093201413097949L; // one day in milliseconds private static final int ONE_DAY = 86400000; // 60*60*24*1000 // private static final long MIN_DATE_1800 = lendar private final List<TeamEventDO> eventList; private boolean sorted; public SubscriptionHolder() { eventList = new ArrayList<TeamEventDO>(); sorted = false; } public void clear() { eventList.clear(); sorted = false; } public void add(final TeamEventDO value) { eventList.add(value); sorted = false; } public void sort() { // the following comparator compares by startDate final Comparator<TeamEventDO> comparator = new Comparator<TeamEventDO>() { @Override public int compare(final TeamEventDO o1, final TeamEventDO o2) { if ((o1 == null || o1.getStartDate() == null) && (o2 == null || o2.getStartDate() == null)) { return 0; } if (o1 == null || o1.getStartDate() == null) { return -1; } if (o2 == null || o2.getStartDate() == null) { return 1; } // at this point, no NPE could occur return o1.getStartDate().compareTo(o2.getStartDate()); } }; Collections.sort(eventList, comparator); sorted = true; } public List<TeamEventDO> getResultList(final Long startTime, final Long endTime, final boolean minimalAccess) { // sorting should by synchronized synchronized (this) { if (sorted == false) { sort(); } } final List<TeamEventDO> result = new ArrayList<TeamEventDO>(); for (final TeamEventDO teamEventDo : eventList) { // all our events are sorted, if we find a event which starts // after the end date, we can break this iteration if (teamEventDo.getStartDate().getTime() > endTime) { break; } if (matches(teamEventDo, startTime, endTime) == true) { if (minimalAccess == true) { result.add(teamEventDo.createMinimalCopy()); } else { result.add(teamEventDo); } } } // and return return result; } public int size() { return eventList.size(); } private boolean matches(final TeamEventDO teamEventDo, Long startTime, Long endTime) { // Following period extension is needed due to all day events which are stored in UTC. The additional events in the result list not // matching the time period have to be removed by caller! startTime = startTime - ONE_DAY; endTime = endTime + ONE_DAY; // the following implementation is inspired by TeamEventDao with the following lines: // queryFilter.add(Restrictions.or( // (Restrictions.or(Restrictions.between("startDate", startDate, endDate), Restrictions.between("endDate", startDate, endDate))), // // get events whose duration overlap with chosen duration. // (Restrictions.and(Restrictions.le("startDate", startDate), Restrictions.ge("endDate", endDate))))); final Long eventStartTime = teamEventDo.getStartDate() != null ? teamEventDo.getStartDate().getTime() : TeamEventDao.MIN_DATE_1800; final Long eventEndTime = teamEventDo.getEndDate() != null ? teamEventDo.getEndDate().getTime() : TeamEventDao.MAX_DATE_3000; if (between(eventStartTime, startTime, endTime) || between(eventEndTime, startTime, endTime)) { return true; } if (eventStartTime <= startTime && eventEndTime >= endTime) { return true; } return false; } private boolean between(final Long searchTime, final Long startTime, final Long endTime) { return searchTime >= startTime && searchTime <= endTime; } }