diff --git a/biz.ganttproject.core/src/biz/ganttproject/core/calendar/GPCalendarBase.java b/biz.ganttproject.core/src/biz/ganttproject/core/calendar/GPCalendarBase.java index f14c7939bf..c65581622a 100644 --- a/biz.ganttproject.core/src/biz/ganttproject/core/calendar/GPCalendarBase.java +++ b/biz.ganttproject.core/src/biz/ganttproject/core/calendar/GPCalendarBase.java @@ -32,20 +32,23 @@ of the License, or (at your option) any later version. * @author bard */ abstract class GPCalendarBase implements GPCalendarCalc { + + static final int MAX_WEEKEND_DAYS = 7; + private final List 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; @@ -94,39 +97,47 @@ public Date findClosest(Date time, TimeUnit timeUnit, MoveDirection direction, D } public Date findClosest(Date time, TimeUnit timeUnit, MoveDirection direction, DayType dayType, Date limit) { - return doFindClosest(time, timeUnit, direction, dayType, limit); + return doFindClosest(time, timeUnit, direction, dayType, limit, MAX_WEEKEND_DAYS); } - - protected Date doFindClosest(Date time, DateFrameable framer, MoveDirection direction, DayType dayType, Date limit) { + + protected Date doFindClosest(Date time, DateFrameable framer, MoveDirection direction, DayType findDayType, Date dateLimit, int maxWeekendDays) { + if (maxWeekendDays == 0) { + throw new UnsupportedOperationException("Error: all days are configured as 'weekend day'. That's not meaningful. Please, configure at least one day as non-weekend."); + } 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 ((nextUnitMask & DayMask.WEEKEND) == DayMask.WEEKEND) { + maxWeekendDays--; + } else { + maxWeekendDays = MAX_WEEKEND_DAYS; } - if (limit != null) { - if (direction == MoveDirection.FORWARD && nextUnitStart.compareTo(limit) >= 0 - || direction == MoveDirection.BACKWARD && nextUnitStart.compareTo(limit) <= 0) { + switch (findDayType) { + 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 (dateLimit != null) { + if (direction == MoveDirection.FORWARD && nextUnitStart.compareTo(dateLimit) >= 0 + || direction == MoveDirection.BACKWARD && nextUnitStart.compareTo(dateLimit) <= 0) { return null; } } - return doFindClosest(nextUnitStart, framer, direction, dayType, limit); + return doFindClosest(nextUnitStart, framer, direction, findDayType, dateLimit, maxWeekendDays); } - + @Override public void addListener(GPCalendarListener listener) { myListeners.add(listener); @@ -141,5 +152,6 @@ protected void fireCalendarChanged() { } } } + public abstract int getDayMask(Date date); } diff --git a/biz.ganttproject.core/src/biz/ganttproject/core/calendar/WeekendCalendarImpl.java b/biz.ganttproject.core/src/biz/ganttproject/core/calendar/WeekendCalendarImpl.java index 6af703116e..2f41cf35f7 100644 --- a/biz.ganttproject.core/src/biz/ganttproject/core/calendar/WeekendCalendarImpl.java +++ b/biz.ganttproject.core/src/biz/ganttproject/core/calendar/WeekendCalendarImpl.java @@ -104,7 +104,7 @@ public List getActivities(Date startDate, final Date endDate boolean isWeekendState = (getDayMask(curDayStart) & DayMask.WORKING) == 0; while (curDayStart.before(endDate)) { Date changeStateDayStart = doFindClosest(curDayStart, myFramer, MoveDirection.FORWARD, - isWeekendState ? DayType.WORKING : DayType.NON_WORKING, endDate); + isWeekendState ? DayType.WORKING : DayType.NON_WORKING, endDate, MAX_WEEKEND_DAYS); if (changeStateDayStart == null) { changeStateDayStart = endDate; } @@ -214,7 +214,7 @@ public Date findClosestWorkingTime(Date time) { if ((dayMask & DayMask.WORKING) == DayMask.WORKING) { return time; } - return doFindClosest(time, myFramer, MoveDirection.FORWARD, DayType.WORKING, null); + return doFindClosest(time, myFramer, MoveDirection.FORWARD, DayType.WORKING, null, MAX_WEEKEND_DAYS); } private boolean isPublicHoliDay(Date curDayStart) { diff --git a/ganttproject-tester/test/biz/ganttproject/core/calendar/WeekendCalendarImplTest.java b/ganttproject-tester/test/biz/ganttproject/core/calendar/WeekendCalendarImplTest.java index 4a95d5da52..286d3c4bfa 100644 --- a/ganttproject-tester/test/biz/ganttproject/core/calendar/WeekendCalendarImplTest.java +++ b/ganttproject-tester/test/biz/ganttproject/core/calendar/WeekendCalendarImplTest.java @@ -23,20 +23,24 @@ import java.util.List; import java.util.Locale; -import biz.ganttproject.core.calendar.CalendarEvent.Type; import biz.ganttproject.core.calendar.GPCalendar.DayMask; import biz.ganttproject.core.calendar.GPCalendar.DayType; import biz.ganttproject.core.time.CalendarFactory; +import biz.ganttproject.core.time.GanttCalendar; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import junit.framework.TestCase; +import org.junit.Assert; + +import static biz.ganttproject.core.calendar.GPCalendar.DayType.WEEKEND; +import static java.util.Calendar.*; /** - * Tests for {@link WeekendsCalendarImpl} class. + * Tests for {@link WeekendCalendarImpl} class. * * @author dbarashev (Dmitry Barashev) */ @@ -130,4 +134,29 @@ public void testOneOffWorkingWeekend() { assertEquals(0, calendar.getDayMask(CalendarFactory.createGanttCalendar(2014, 0, 11).getTime()) & DayMask.WORKING); assertEquals(DayMask.WEEKEND, calendar.getDayMask(CalendarFactory.createGanttCalendar(2014, 0, 11).getTime()) & DayMask.WEEKEND); } + + /** + * @see