/* GanttProject is an opensource project management tool. Copyright (C) 2005-2011 GanttProject Team This program 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; either version 3 of the License, or (at your option) any later version. This program 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package biz.ganttproject.core.calendar; import java.util.Date; import java.util.List; import com.google.common.collect.Lists; import biz.ganttproject.core.time.DateFrameable; import biz.ganttproject.core.time.TimeDuration; import biz.ganttproject.core.time.TimeUnit; /** * @author bard */ abstract class GPCalendarBase implements GPCalendarCalc { private final List<GPCalendarListener> myListeners = Lists.newArrayList(); private String myName; private String myId; @Override public String getID() { return myId == null ? myName : myId; } @Override public String getName() { return myName; } @Override public void setName(String name) { myName = name; } @Override public void setID(String id) { myId = id; } public Date shiftDate(Date input, TimeDuration shift) { if (shift.getLength() == 0) { return input; } List<GPCalendarActivity> activities = getActivities(input, shift); if (activities.isEmpty()) { throw new RuntimeException("FIXME: Failed to compute calendar activities in time period=" + shift + " starting from " + input); } Date result; if (shift.getValue() >= 0) { GPCalendarActivity lastActivity = activities.get(activities.size() - 1); result = lastActivity.getEnd(); } else { GPCalendarActivity firstActivity = activities.get(0); result = firstActivity.getStart(); } return result; } public List<GPCalendarActivity> getActivities(Date startDate, TimeUnit timeUnit, long unitCount) { return unitCount > 0 ? getActivitiesForward(startDate, timeUnit, unitCount) : getActivitiesBackward(startDate, timeUnit, -unitCount); } protected abstract List<GPCalendarActivity> getActivitiesBackward(Date startDate, TimeUnit timeUnit, long unitCount); protected abstract List<GPCalendarActivity> getActivitiesForward(Date startDate, TimeUnit timeUnit, long unitCount); public List<GPCalendarActivity> getActivities(Date startingFrom, TimeDuration period) { return getActivities(startingFrom, period.getTimeUnit(), period.getLength()); } public Date findClosest(Date time, TimeUnit timeUnit, MoveDirection direction, DayType dayType) { return findClosest(time, timeUnit, direction, dayType, null); } public Date findClosest(Date time, TimeUnit timeUnit, MoveDirection direction, DayType dayType, Date limit) { return doFindClosest(time, timeUnit, direction, dayType, limit); } protected Date doFindClosest(Date time, DateFrameable framer, MoveDirection direction, DayType dayType, Date limit) { Date nextUnitStart = direction == GPCalendarCalc.MoveDirection.FORWARD ? framer.adjustRight(time) : framer.jumpLeft(time); int nextUnitMask = getDayMask(nextUnitStart); switch (dayType) { case WORKING: if ((nextUnitMask & DayMask.WORKING) == DayMask.WORKING) { return nextUnitStart; } break; case WEEKEND: case HOLIDAY: case NON_WORKING: if ((nextUnitMask & DayMask.WORKING) == 0) { return nextUnitStart; } break; default: assert false : "Should not be here"; } if (limit != null) { if (direction == MoveDirection.FORWARD && nextUnitStart.compareTo(limit) >= 0 || direction == MoveDirection.BACKWARD && nextUnitStart.compareTo(limit) <= 0) { return null; } } return doFindClosest(nextUnitStart, framer, direction, dayType, limit); } @Override public void addListener(GPCalendarListener listener) { myListeners.add(listener); } protected void fireCalendarChanged() { for (GPCalendarListener l : myListeners) { try { l.onCalendarChange(); } catch (Throwable e) { e.printStackTrace(); } } } public abstract int getDayMask(Date date); }